Auto merge of #37965 - Mark-Simulacrum:trait-obj-to-exis-predicate, r=eddyb
Refactor TraitObject to Slice<ExistentialPredicate>
For reference, the primary types changes in this PR are shown below. They may add in the understanding of what is discussed below, though they should not be required.
We change `TraitObject` into a list of `ExistentialPredicate`s to allow for a couple of things:
- Principal (ExistentialPredicate::Trait) is now optional.
- Region bounds are moved out of `TraitObject` into `TyDynamic`. This permits wrapping only the `ExistentialPredicate` list in `Binder`.
- `BuiltinBounds` and `BuiltinBound` are removed entirely from the codebase, to permit future non-constrained auto traits. These are replaced with `ExistentialPredicate::AutoTrait`, which only requires a `DefId`. For the time being, only `Send` and `Sync` are supported; this constraint can be lifted in a future pull request.
- Binder-related logic is extracted from `ExistentialPredicate` into the parent (`Binder<Slice<EP>>`), so `PolyX`s are inside `TraitObject` are replaced with `X`.
The code requires a sorting order for `ExistentialPredicate`s in the interned `Slice`. The sort order is asserted to be correct during interning, but the slices are not sorted at that point.
1. `ExistentialPredicate::Trait` are defined as always equal; **This may be wrong; should we be comparing them and sorting them in some way?**
1. `ExistentialPredicate::Projection`: Compared by `ExistentialProjection::sort_key`.
1. `ExistentialPredicate::AutoTrait`: Compared by `TraitDef.def_path_hash`.
Construction of `ExistentialPredicate`s is conducted through `TyCtxt::mk_existential_predicates`, which interns a passed iterator as a `Slice`. There are no convenience functions to construct from a set of separate iterators; callers must pass an iterator chain. The lack of convenience functions is primarily due to few uses and the relative difficulty in defining a nice API due to optional parts and difficulty in recognizing which argument goes where. It is also true that the current situation isn't significantly better than 4 arguments to a constructor function; but the extra work is deemed unnecessary as of this time.
```rust
// before this PR
struct TraitObject<'tcx> {
pub principal: PolyExistentialTraitRef<'tcx>,
pub region_bound: &'tcx ty::Region,
pub builtin_bounds: BuiltinBounds,
pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>,
}
// after
pub enum ExistentialPredicate<'tcx> {
// e.g. Iterator
Trait(ExistentialTraitRef<'tcx>),
// e.g. Iterator::Item = T
Projection(ExistentialProjection<'tcx>),
// e.g. Send
AutoTrait(DefId),
}
```
This commit is contained in:
commit
8e373b4787
71 changed files with 893 additions and 901 deletions
|
|
@ -10,6 +10,6 @@
|
|||
|
||||
fn main() {
|
||||
let _: Box<std::io::Read + std::io::Write>;
|
||||
//~^ ERROR only the builtin traits can be used as closure or object bounds [E0225]
|
||||
//~| NOTE non-builtin trait used as bounds
|
||||
//~^ ERROR only Send/Sync traits can be used as additional traits in a trait object [E0225]
|
||||
//~| NOTE non-Send/Sync additional trait
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ trait Trait {}
|
|||
|
||||
pub fn main() {
|
||||
let x: Vec<Trait + Sized> = Vec::new();
|
||||
//~^ ERROR `Trait + Sized: std::marker::Sized` is not satisfied
|
||||
//~| ERROR the trait `std::marker::Sized` cannot be made into an object
|
||||
//~| ERROR `Trait + Sized: std::marker::Sized` is not satisfied
|
||||
//~| ERROR the trait `std::marker::Sized` cannot be made into an object
|
||||
//~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
|
||||
//~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
|
||||
//~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync));
|
||||
//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied
|
||||
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static`
|
||||
//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
|
||||
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
|
||||
//~| NOTE does not have a constant size known at compile-time
|
||||
//~| NOTE constant expressions must have a statically known size
|
||||
|
||||
|
|
@ -23,8 +23,8 @@ const CONST_FOO: str = *"foo";
|
|||
//~| NOTE constant expressions must have a statically known size
|
||||
|
||||
static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync));
|
||||
//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied
|
||||
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static`
|
||||
//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied
|
||||
//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn
|
||||
//~| NOTE does not have a constant size known at compile-time
|
||||
//~| NOTE constant expressions must have a statically known size
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:type annotations required
|
||||
// error-pattern:type annotations or generic parameter binding required
|
||||
fn main() {
|
||||
panic!(
|
||||
std::default::Default::default()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@ type Test = Add +
|
|||
//~| NOTE missing associated type `Output` value
|
||||
Sub;
|
||||
//~^ ERROR E0225
|
||||
//~| NOTE non-builtin trait used as bounds
|
||||
//~| NOTE non-Send/Sync additional trait
|
||||
|
||||
fn main() { }
|
||||
|
|
|
|||
|
|
@ -16,6 +16,6 @@ fn size_of_copy<T: Copy+?Sized>() -> usize { mem::size_of::<T>() }
|
|||
|
||||
fn main() {
|
||||
size_of_copy::<Misc+Copy>();
|
||||
//~^ ERROR `Misc + Copy: std::marker::Copy` is not satisfied
|
||||
//~| ERROR the trait `std::marker::Copy` cannot be made into an object
|
||||
//~^ ERROR only Send/Sync traits can be used as additional traits in a trait object
|
||||
//~| ERROR the trait bound `Misc: std::marker::Copy` is not satisfied
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ fn c(x: Box<Foo+Sync+Send>) {
|
|||
}
|
||||
|
||||
fn d(x: Box<Foo>) {
|
||||
a(x); //~ ERROR mismatched types
|
||||
//~| expected type `Box<Foo + Send + 'static>`
|
||||
//~| found type `Box<Foo + 'static>`
|
||||
//~| expected bounds `Send`, found no bounds
|
||||
a(x); //~ ERROR mismatched types [E0308]
|
||||
//~| NOTE expected type `Box<Foo + std::marker::Send + 'static>`
|
||||
//~| NOTE found type `Box<Foo + 'static>`
|
||||
//~| NOTE expected trait `Foo + std::marker::Send`, found trait `Foo`
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ trait Foo {
|
|||
// This should emit the less confusing error, not the more confusing one.
|
||||
|
||||
fn foo(_x: Foo + Send) {
|
||||
//~^ ERROR `Foo + Send + 'static: std::marker::Sized` is not satisfied
|
||||
//~^ ERROR the trait bound `Foo + std::marker::Send + 'static: std::marker::Sized` is not
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ pub mod testtypes {
|
|||
// Tests TyFnPtr
|
||||
pub type FooFnPtr = fn(u8) -> bool;
|
||||
|
||||
// Tests TyTrait
|
||||
// Tests TyDynamic
|
||||
pub trait FooTrait {
|
||||
fn foo_method(&self) -> usize;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue