-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Always try to project predicates when finding auto traits in rustdoc #60773
Conversation
Fixes rust-lang#60726 Previous, AutoTraitFinder would only try to project predicates when the predicate type contained an inference variable. When finding auto traits, we only project to try to unify inference variables - we don't otherwise learn any new information about the required bounds. However, this lead to failing to properly generate a negative auto trait impl (indicating that a type never implements a certain auto trait) in the following unusual scenario: In almost all cases, a type has an (implicit) negative impl of an auto trait due some other type having an explicit *negative* impl of that auto trait. For example: struct MyType<T> { field: *const T } has an implicit 'impl<T> !Send for MyType<T>', due to the explicit negative impl (in libcore) 'impl<T: ?Sized> !Send for *const T'. However, as exposed by the 'abi_stable' crate, this isn't always the case. This minimzed example shows how a type can never implement 'Send', due to a projection error: ``` pub struct True; pub struct False; pub trait MyTrait { type Project; } pub struct MyStruct<T> { field: T } impl MyTrait for u8 { type Project = False; } unsafe impl<T> Send for MyStruct<T> where T: MyTrait<Project=True> {} pub struct Wrapper { inner: MyStruct<u8> } ``` In this example, `<u8 as MyTrait>::Project == True' must hold for 'MyStruct<u8>: Send' to hold. However, '<u8 as MyTrait>::Project == False' holds instead To properly account for this unusual case, we need to call 'poly_project_and_unify' on *all* predicates, not just those with inference variables. This ensures that we catch the projection error that occurs above, and don't incorrectly determine that 'Wrapper: Send' holds.
r? @eddyb (rust_highfive has picked a reviewer for you, use r? to override) |
Would you mind reducing the testcase a little bit? pub struct True;
pub struct False;
pub trait InterfaceType {
type Send;
}
pub struct FooInterface;
pub struct DynTrait<I>(I);
pub struct IntoIter(DynTrait<FooInterface>);
impl InterfaceType for FooInterface {
type Send = False;
}
unsafe impl<I> Send for DynTrait<I> where I: InterfaceType<Send = True> {} |
ping from triage @eddyb waiting for your review on this |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit dubious on this whole module but AFAIK it only affects rustdoc
right now.
cc @rust-lang/wg-traits You might want to review this change at some point (and the whole module - maybe it can be simplified/deduplicated with other parts of the trait system?) @bors r+ |
📌 Commit 476ea9e has been approved by |
…r=eddyb Always try to project predicates when finding auto traits in rustdoc Fixes rust-lang#60726 Previous, AutoTraitFinder would only try to project predicates when the predicate type contained an inference variable. When finding auto traits, we only project to try to unify inference variables - we don't otherwise learn any new information about the required bounds. However, this lead to failing to properly generate a negative auto trait impl (indicating that a type never implements a certain auto trait) in the following unusual scenario: In almost all cases, a type has an (implicit) negative impl of an auto trait due some other type having an explicit *negative* impl of that auto trait. For example: struct MyType<T> { field: *const T } has an implicit 'impl<T> !Send for MyType<T>', due to the explicit negative impl (in libcore) 'impl<T: ?Sized> !Send for *const T'. However, as exposed by the 'abi_stable' crate, this isn't always the case. This minimzed example shows how a type can never implement 'Send', due to a projection error: ``` pub struct True; pub struct False; pub trait MyTrait { type Project; } pub struct MyStruct<T> { field: T } impl MyTrait for u8 { type Project = False; } unsafe impl<T> Send for MyStruct<T> where T: MyTrait<Project=True> {} pub struct Wrapper { inner: MyStruct<u8> } ``` In this example, `<u8 as MyTrait>::Project == True' must hold for 'MyStruct<u8>: Send' to hold. However, '<u8 as MyTrait>::Project == False' holds instead To properly account for this unusual case, we need to call 'poly_project_and_unify' on *all* predicates, not just those with inference variables. This ensures that we catch the projection error that occurs above, and don't incorrectly determine that 'Wrapper: Send' holds.
Rollup of 8 pull requests Successful merges: - #60300 (Allow null-pointer-optimized enums in FFI if their underlying representation is FFI safe) - #60773 (Always try to project predicates when finding auto traits in rustdoc) - #60809 (Add FAQ for NLL migration) - #61023 (Migrate from recursion to iterate on qualify consts visitor impl) - #61029 (Simplify RefCell minimum_spanning_tree example) - #61030 (Make maybe_codegen_consume_direct iterate instead of doing recursion) - #61034 (rustc_metadata: parametrize schema::CrateRoot by 'tcx and rip out old unused incremental infra.) - #61037 (Update clippy submodule) Failed merges: r? @ghost
Fixes #60726
Previous, AutoTraitFinder would only try to project predicates when the
predicate type contained an inference variable. When finding auto
traits, we only project to try to unify inference variables - we don't
otherwise learn any new information about the required bounds.
However, this lead to failing to properly generate a negative auto trait
impl (indicating that a type never implements a certain auto trait) in
the following unusual scenario:
In almost all cases, a type has an (implicit) negative impl of an auto
trait due some other type having an explicit negative impl of that
auto trait. For example:
struct MyType {
field: *const T
}
has an implicit 'impl !Send for MyType', due to the explicit
negative impl (in libcore) 'impl<T: ?Sized> !Send for *const T'.
However, as exposed by the 'abi_stable' crate, this isn't always the
case. This minimzed example shows how a type can never implement
'Send', due to a projection error:
In this example, `::Project == True'
must hold for 'MyStruct: Send' to hold.
However, '::Project == False' holds instead
To properly account for this unusual case, we need to call
'poly_project_and_unify' on all predicates, not just those with
inference variables. This ensures that we catch the projection error
that occurs above, and don't incorrectly determine that 'Wrapper: Send'
holds.