Skip to content

Tracking Issue for sound builtin auto trait impls #93367

Closed
@lcnr

Description

@lcnr

This is the summary issue for the SUSPICIOUS_AUTO_TRAIT_IMPLS future-compatibility warning. The goal of this page is to describe why this lint was added and how you can fix code that is affected by it. It also provides a place to ask questions
or register a complaint if you feel the change should not be made. For more information on the policy around future-compatibility warnings, see our breaking change policy guidelines.

What is the warning for?

Rust has some special traits, called either "auto traits" or "traits with a default impl", which are automatically implemented for your types under certain conditions. The most notable examples for this are the traits Send and Sync. A type implements these trait automatically if all its fields also implement this trait. This means that types like struct MyData { data: Vec<String> } automatically implement Send without the user having to think about it.

There are some cases where the builtin impls are not enough. For traits like Send, Sync and Unpin these builtin impls can even be unsound when implementing abstractions using unsafe code. Because of this, it is allowed to also manually implement these traits, disabling the builtin impl for your type in the process.

The way we currently disable builtin impls has some quite subtle bugs, causing unsoundness: #84857. This unsoundness is luckily quite difficult to exploit, but can be triggered under the following conditions:

  • There exists an explicit specialized impl of an auto trait which has a stronger where-clauses than the type definition. We consider an impl to be "specialized" here if the generic arguments of the Self type of the impl are not simply unique generic parameters. impl Trait for X is specialized if X is Vec<i32>, HashMap<String, V> or even HashMap<T, T> and not specialized for Vec<T> or HashMap<K, V>.
  • The builtin impl for the self type of that explicit impl applies for at least one concrete type rejected by the where-clauses of the explicit impl

EXAMPLE

To fix this unsoundness, we intend to simplify the rules for builtin auto trait implementations. Right now, we only discard the builtin implementation if an explicit impl applies to the given type while ignoring where-clauses of that explicit impl. This will be changed to just always discard the builtin impl once at least one explicit impl for that type exists.

As this can cause types to stop implementing auto traits if a specialized impl for that type exists, we now warn again specialized impls if builtin impls could apply for your type. If the builtin impl would definitely not apply for your type, this change will not affect you, and we therefore try to not emit a warning in these cases.

When will this change take effect?

After a crater run detected that our intended change to make builtin auto trait impls sound causes some breakage in the wider ecosystem.

We are currently searching for ways to lessen the impact by modifying the implementation to be more similar to the current situation, while still being sound. If that is not possible, we will introduce this change after the future compatibility lint has been on stable for long enough to reduce the impact of landing this change and if there are existing workarounds for breakage caused by the new rules.

Some of the cases which broke need either marker traits (#29864) or negative impls (#68318) affecting coherence to get back the old behavior. Both of these are currently not too far away from stabilization, so this will probably remain as a future compatibility warning until one of these ends up getting stabilized.

How to fix this?

This depends on why the explicit impl has been added in the first place. If you do not want the builtin impl to apply, you may add a field to your type which definitely does not implement the given auto trait. You may also be able to remove the explicit impl entirely, if that case is already currently covered by the builtin impl. For anything else, please report your case here so that we know about the issue and are able to extend this section.

If your code triggered this lint, please tell us about it in this issue so we may take it into consideration when deciding on how to proceed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-auto-traitsArea: auto traits (e.g., `auto trait Send {}`)A-trait-systemArea: Trait systemC-future-incompatibilityCategory: Future-incompatibility lintsT-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    Status

    Idea

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions