- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Refactor TraitObject to Slice<ExistentialPredicate> #37965
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
Refactor TraitObject to Slice<ExistentialPredicate> #37965
Conversation
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.
LGTM modulo comments. cc @nikomatsakis about Binder discipline.
        
          
                src/librustc/traits/coherence.rs
              
                Outdated
          
        
      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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same extraneous ref. It might be worth using map_or in cases like this, I'm not sure.
        
          
                src/librustc/traits/select.rs
              
                Outdated
          
        
      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.
This should be an if-else chain.
        
          
                src/librustc/traits/select.rs
              
                Outdated
          
        
      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.
Same extraneous ref.
        
          
                src/librustc/traits/select.rs
              
                Outdated
          
        
      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.
Same extraneous ref.
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.
Same odd reg.
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.
This can be written using map_or.
        
          
                src/librustc_typeck/collect.rs
              
                Outdated
          
        
      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 not sure this partitioning should even exist until a TyDynamic is created.
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.
This can be wrapped in an if let Some instead of using .unwrap().
        
          
                src/librustc/ty/sty.rs
              
                Outdated
          
        
      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.
This shouldn't .unwrap().
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't allocate.
        
          
                src/librustc_typeck/check/wfcheck.rs
              
                Outdated
          
        
      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.
Replace with require_lang_item.
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.
reg
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
          
        
      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.
copy_trait or copy_def_id.
        
          
                src/librustc/traits/coherence.rs
              
                Outdated
          
        
      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.
This (and other places) could use map_or for brevity.
        
          
                src/librustc/traits/select.rs
              
                Outdated
          
        
      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.
Comment is unnecessary/misleading.
        
          
                src/librustc/traits/select.rs
              
                Outdated
          
        
      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.
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
          
        
      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.
Maybe rename this to mk_dynamic?
        
          
                src/librustc_typeck/astconv.rs
              
                Outdated
          
        
      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.
Use if let Some here.
        
          
                src/librustc_typeck/check/wfcheck.rs
              
                Outdated
          
        
      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.
Is this check necessary anymore? AFAIK trait_has_default_impl returns true for Send and Sync.
        
          
                src/librustc_typeck/collect.rs
              
                Outdated
          
        
      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.
No need to .clone().
        
          
                src/librustc_typeck/collect.rs
              
                Outdated
          
        
      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.
Unnecessary ref.
        
          
                src/librustc_typeck/diagnostics.rs
              
                Outdated
          
        
      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.
s/type/trait
| 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion was to move the .types().rev() here.
        
          
                src/librustc/traits/mod.rs
              
                Outdated
          
        
      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.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.