Refactor TraitObject to Slice<ExistentialPredicate>#37965
Refactor TraitObject to Slice<ExistentialPredicate>#37965bors merged 7 commits intorust-lang:masterfrom
Conversation
eddyb
left a comment
There was a problem hiding this comment.
LGTM modulo comments. cc @nikomatsakis about Binder discipline.
src/librustc/traits/coherence.rs
Outdated
There was a problem hiding this comment.
You shouldn't need ref in positions by this, the match is on an rvalue anyway.
src/librustc/traits/coherence.rs
Outdated
There was a problem hiding this comment.
Same extraneous ref. It might be worth using map_or in cases like this, I'm not sure.
src/librustc/traits/select.rs
Outdated
src/librustc/traits/select.rs
Outdated
src/librustc/traits/select.rs
Outdated
There was a problem hiding this comment.
This can be written using map_or.
src/librustc_typeck/collect.rs
Outdated
There was a problem hiding this comment.
I'm not sure this partitioning should even exist until a TyDynamic is created.
There was a problem hiding this comment.
This can be wrapped in an if let Some instead of using .unwrap().
src/librustc/ty/sty.rs
Outdated
b475ea0 to
2c1ec2f
Compare
|
☔ The latest upstream changes (presumably #37890) made this pull request unmergeable. Please resolve the merge conflicts. |
3c63d7c to
8d76e7e
Compare
|
@eddyb Ready for the crater run, I think, but might want to review before? |
90d69cd to
72f54e0
Compare
src/librustc_trans/trans_item.rs
Outdated
There was a problem hiding this comment.
Shouldn't allocate.
src/librustc_typeck/check/wfcheck.rs
Outdated
There was a problem hiding this comment.
Replace with require_lang_item.
fdb5b7b to
c0eca6a
Compare
|
Expanded the description with discussion and elaboration on what this PR does. @eddyb Let me know what parts of that should be transferred into documentation comments in the code. |
c0eca6a to
eb7bb54
Compare
|
Squashed the remaining fix commits. r? @eddyb |
|
Started crater run. |
src/librustc/infer/mod.rs
Outdated
src/librustc/traits/coherence.rs
Outdated
There was a problem hiding this comment.
This (and other places) could use map_or for brevity.
src/librustc/traits/select.rs
Outdated
There was a problem hiding this comment.
Comment is unnecessary/misleading.
src/librustc/traits/select.rs
Outdated
There was a problem hiding this comment.
Not necessary in this PR, but these push calls could be replaced with collecting an iterator to a Vec.
src/librustc/ty/context.rs
Outdated
src/librustc_typeck/astconv.rs
Outdated
src/librustc_typeck/check/wfcheck.rs
Outdated
There was a problem hiding this comment.
Is this check necessary anymore? AFAIK trait_has_default_impl returns true for Send and Sync.
src/librustc_typeck/collect.rs
Outdated
src/librustc_typeck/collect.rs
Outdated
src/librustc_typeck/diagnostics.rs
Outdated
|
Crater report contains no legitimate regressions (ignoring uses of |
6b84098 to
17ac55e
Compare
|
☔ The latest upstream changes (presumably #37676) made this pull request unmergeable. Please resolve the merge conflicts. |
17ac55e to
0ae852c
Compare
|
@eddyb Rebased, but haven't run tests--started those locally (and Travis will test too, of course). |
src/librustc/ty/walk.rs
Outdated
There was a problem hiding this comment.
My suggestion was to move the .types().rev() here.
src/librustc/traits/mod.rs
Outdated
There was a problem hiding this comment.
There's a few indentation aberrations, here and in a few other places. Let me know if you want a list.
src/librustc/traits/select.rs
Outdated
There was a problem hiding this comment.
Hmm, to make this nicer I think you should call .skip_binder on data_a and data_b (with a comment that it's reintroduced below).
src/librustc_typeck/astconv.rs
Outdated
There was a problem hiding this comment.
At least use .skip_binder() instead of .0.
Renames TyTrait to TyDynamic.
Replaces instances of tcx.lang_items.require(..) with fatal unwrap with this method.
0ae852c to
8b82fd7
Compare
|
Fixed review comments. r? @eddyb |
|
@bors r+ |
|
📌 Commit 8b82fd7 has been approved by |
…=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),
}
```
|
⌛ Testing commit 8b82fd7 with merge 8e373b4... |
Refactor ty::FnSig to contain a &'tcx Slice<Ty<'tcx>> We refactor this in order to achieve the following wins: - Decrease the size of `FnSig` (`Vec` + `bool`: 32, `&Slice` + `bool`: 24). - Potentially decrease total allocated memory due to arena-allocating `FnSig` inputs/output; since they are allocated in the type list arena, other users of type lists can reuse the same allocation for an equivalent type list. - Remove the last part of the type system which needs drop glue (#37965 removed the other remaining part). This makes arenas containing `FnSig` faster to drop (since we don't need to drop a Vec for each one), and makes reusing them without clearing/dropping potentially possible. r? @eddyb
|
@Mark-Simulacrum: Very late to the party, but I just ran into the the sort order while spelunking for #41444, and I'm curious about:
What does "correct" mean? I can see from the code that the only time the assertion runs is when it is passed something that has previously been sorted using the same
Why not just tie-break by |
Since we now represent I think I answered the second question as well. You do make a good point about possibly more efficient interning if we sorted with tie-breaking by Let me know if you have any more questions! |
|
You simply can't have more than one |
|
@Mark-Simulacrum: Thanks for the explanation. I have one follow-up question on the following (and it's not really a question about this code in particular any more):
The comment on
I guess it depends on what is meant by "same contents", but it would seem to me that at this point you could wind up interning both of the slices |
|
Slices can be compared by pointer and length because they're always interned, which means that |
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
TraitObjectinto a list ofExistentialPredicates to allow for a couple of things:TraitObjectintoTyDynamic. This permits wrapping only theExistentialPredicatelist inBinder.BuiltinBoundsandBuiltinBoundare removed entirely from the codebase, to permit future non-constrained auto traits. These are replaced withExistentialPredicate::AutoTrait, which only requires aDefId. For the time being, onlySendandSyncare supported; this constraint can be lifted in a future pull request.ExistentialPredicateinto the parent (Binder<Slice<EP>>), soPolyXs are insideTraitObjectare replaced withX.The code requires a sorting order for
ExistentialPredicates in the internedSlice. The sort order is asserted to be correct during interning, but the slices are not sorted at that point.ExistentialPredicate::Traitare defined as always equal; This may be wrong; should we be comparing them and sorting them in some way?ExistentialPredicate::Projection: Compared byExistentialProjection::sort_key.ExistentialPredicate::AutoTrait: Compared byTraitDef.def_path_hash.Construction of
ExistentialPredicates is conducted throughTyCtxt::mk_existential_predicates, which interns a passed iterator as aSlice. 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.