Always try to project predicates when finding auto traits in rustdoc
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.
2019-05-13 00:37:04 -05:00
|
|
|
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
|
2022-09-25 15:52:26 -05:00
|
|
|
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
|
2021-06-02 03:59:10 -05:00
|
|
|
// "impl<T> !Send for IntoIter<T>"
|
2022-09-25 15:52:26 -05:00
|
|
|
// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
|
2021-06-02 03:59:10 -05:00
|
|
|
// "impl<T> !Sync for IntoIter<T>"
|
Always try to project predicates when finding auto traits in rustdoc
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.
2019-05-13 00:37:04 -05:00
|
|
|
pub struct IntoIter<T>{
|
|
|
|
hello:DynTrait<FooInterface<T>>,
|
|
|
|
}
|