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<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.
35 lines
755 B
Rust
35 lines
755 B
Rust
use std::marker::PhantomData;
|
|
|
|
pub struct True;
|
|
pub struct False;
|
|
|
|
pub trait InterfaceType{
|
|
type Send;
|
|
}
|
|
|
|
|
|
pub struct FooInterface<T>(PhantomData<fn()->T>);
|
|
|
|
impl<T> InterfaceType for FooInterface<T> {
|
|
type Send=False;
|
|
}
|
|
|
|
|
|
pub struct DynTrait<I>{
|
|
_interface:PhantomData<fn()->I>,
|
|
_unsync_unsend:PhantomData<::std::rc::Rc<()>>,
|
|
}
|
|
|
|
unsafe impl<I> Send for DynTrait<I>
|
|
where
|
|
I:InterfaceType<Send=True>
|
|
{}
|
|
|
|
// @has issue_60726/struct.IntoIter.html
|
|
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Send for \
|
|
// IntoIter<T>"
|
|
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//code' "impl<T> !Sync for \
|
|
// IntoIter<T>"
|
|
pub struct IntoIter<T>{
|
|
hello:DynTrait<FooInterface<T>>,
|
|
}
|