- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Various fixes to trait alias feature #55994
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
Conversation
| (rust_highfive has picked a reviewer for you, use r? to override) | 
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
| I still want to improve error messages a bit, but this is nearly ready. Feel free to review. | 
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
| Ready for review and (hopefully) merge now, I think. | 
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
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.
Looks great! Left one nit (on the test)
| @bors r+ | 
| 📌 Commit c180d7ce09bba0ab7c97365e2a1d1c33face2618 has been approved by  | 
| ☔ The latest upstream changes (presumably #55808) made this pull request unmergeable. Please resolve the merge conflicts. | 
| What on Earth... this didn't merge yet?! | 
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
| @bors r=nikomatsakis | 
| 📌 Commit 4fb40da has been approved by  | 
Disallow multiple regular traits in trait objects when trait aliases used
This ensures code like the following fails to compile.
```rust
#![feature(trait_alias)]
trait Foo = std::io::Read + std::io::Write;
fn main() {
    let foo: Box<dyn Foo>;
}
```
CC @nikomatsakis @scalexm
    | 💔 Test failed - status-appveyor | 
| Err, what's up with this? @nikomatsakis  | 
| We discussed this failure on Zulip and concluded that we probably need to do a future-compatibility warning here. | 
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
| @nikomatsakis Unless you want to extend the lint to all traits (not just auto traits), can we get this r+'ed soon please? :-) | 
| ☔ The latest upstream changes (presumably #55937) made this pull request unmergeable. Please resolve the merge conflicts. | 
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.
Two nits.
        
          
                src/librustc/lint/builtin.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 think we should just call this DUPLICATE_BOUNDS In particular, I think we could easily extend this in the future to non-auto-traits as well as to other sorts of bounds (e.g., where Self: 'static, Self: 'static etc).
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 agree we should keep this general for any sort of bound... However, Foo: Bar and Bar + Baz cannot both be bounds at the same time; I call the former a constraint and the latter a bound; Thus, Self: 'static, Self: 'static and Self: 'static + 'static are not the same thing, the first is duplicate constraints and the latter duplicate bounds. (tho you can desugar the latter to the former)
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.
Interesting. I'm not sure I see what distinction you are drawing, precisely. Is if the difference between Foo: Bar (where the self type is stated) and just Bar (which is missing the self type), or is the difference between Foo: Bar and Foo: Bar + Baz?
In the compiler / in the past, I think we draw the distinction between a where clause (which includes the self type, so e.g. Foo: Bar) and a bound (which is just the Bar part).
I think that the term "bound" and "constraint" don't make it particularly clear what we are referring to. They seem basically like synonyms to me. I wonder if we can use modifiers instead?
- Foo: Bar-- a bound
- Foo: Bar + Baz-- a compound bound
- Bar-- an .. incomplete bound? =)
OTOH I'm not sure if it's really important to have a term for Bar without the self type -- though it obviously comes up for trait objects, at least grammatically. Still I feel like we could get by just using one term.
In general, I like the term "where clause" because it seems to be clearly linked to Rust syntax, and hence the most obvious. But I fear that people will assume (reasonably) that a "where clause" must be introduced with where, and hence may be confused if we refer to the Bar in fn foo<T: Bar>() or dyn Bar as a "where clause".
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.
Interesting. I'm not sure I see what distinction you are drawing, precisely. Is if the difference between
Foo: Bar(where the self type is stated) and justBar(which is missing the self type), or is the difference betweenFoo: BarandFoo: Bar + Baz?
The difference between former; i.e. Foo: Bar + 'a vs. Bar + 'a.
In my model, I think of Rust roughly (forgetting about for<'a> and such...) as having:
- base kinds k0 ::= type | lifetime;
- bounds as "incomplete constraints": bound = k0 -> constraint("1-argument curried constraint")
- +as a binary operator- bound, bound -> bound(tho in reality its a list)
- axiom sets: where [constraint]*
In the compiler / in the past, I think we draw the distinction between a where clause (which includes the self type, so e.g.
Foo: Bar) and a bound (which is just theBarpart).
In Wadler's terminology (as per the paper Quantified Class Constraints) a where clause would correspond to an "axiom set" (denoted by A in the paper) and an axiom set consists of a list of "constraints".
I think that the term "bound" and "constraint" don't make it particularly clear what we are referring to.
ISTM that this is mainly due to using "bound" both for Foo: Bar and Bar which is confusing. I find that we primarily use "bound" for Bar right now. For the reference we need clear terminology, and since Wadler came up with type classes, my preference is for using Wadler's "constraint" terminology... ;)
They seem basically like synonyms to me. I wonder if we can use modifiers instead?
Foo: Bar-- a bound
Foo: Bar + Baz-- a compound bound
Bar-- an .. incomplete bound? =)
I'd categorize as this instead:
where Foo: Bar, Baz: Quux-- a where clause (or axiom set, but we don't need to call it that...)
Foo: Bar-- a constraint
for<'a> Foo<'a>: Bar-- still a constraint, but generic/universally quantified over lifetimes
Bar + Baz-- a compound bound
Bar-- a bound
for<'a> Bar<'a>-- still a bound, but generic over lifetimes
where bounds are constraint-constructors (but we don't need to call it that in user documentation...)
OTOH I'm not sure if it's really important to have a term for
Barwithout the self type -- though it obviously comes up for trait objects, at least grammatically. Still I feel like we could get by just using one term.
I feel like at least for the sake of not confusing ourselves (which I find happens often) we need 2 terms... trait objects are a good reason distinguish; we can think of dyn as an operator bound -> type.
In general, I like the term "where clause" because it seems to be clearly linked to Rust syntax, and hence the most obvious. But I fear that people will assume (reasonably) that a "where clause" must be introduced with
where, and hence may be confused if we refer to theBarinfn foo<T: Bar>()ordyn Baras a "where clause".
<T: Bar> is a bit tricky here since it's both quantification and an axiom set at the same time... I think we should probably leave "where clause" to the syntactic rather than semantic construct...
      
        
              This comment has been minimized.
        
        
      
    
  This comment has been minimized.
| @nikomatsakis Okay, finally reading for r+ I think! Linting has been removed; that will be addressed in a separated PR. | 
| ☔ The latest upstream changes (presumably #56837) made this pull request unmergeable. Please resolve the merge conflicts. | 
| Ping from triage @alexreg : Have you been able to make any progress on this PR? | 
| @stokhos 2 and 4 have been factored out into a separate PR by @nikomatsakis (and merged), while he is still working on 1, because it's slightly non-trivial. 3 is postponed for now. Perhaps we should close this PR? | 
| Let's go ahead and close this PR, the relevant commits are in other branches by now. | 
…nikomatsakis make trait-aliases work across crates This is rebase of a small part of @alexreg's PR rust-lang#55994. It focuses just on the changes that integrate trait aliases properly into crate metadata, excluding the stylistic edits and the trait objects. The stylistic edits I also rebased and can open a separate PR. The trait object stuff I found challenging and decided it basically needed to be reimplemented. For now I've excluded it. Since this is really @alexreg's work (I really just rebased) I am going to make it r=me once it is working. Fixes rust-lang#56488. Fixes rust-lang#57023.
…=oli-obk Ban multi-trait objects via trait aliases Obviously, multi-trait objects are not normally supported, so they should not be supported via trait aliases. This has been factored out from the previous PR #55994 (see point 1). r? @Centril CC @nikomatsakis
…=oli-obk Ban multi-trait objects via trait aliases Obviously, multi-trait objects are not normally supported, so they should not be supported via trait aliases. This has been factored out from the previous PR #55994 (see point 1). r? @Centril CC @nikomatsakis ------------------ ### RELNOTES: We now allow `dyn Send + fmt::Debug` with equivalent semantics to `dyn fmt::Debug + Send`. That is, the order of the mentioned traits does not matter wrt. principal/not-principal traits. This is a small change that might deserve a mention in the blog post because it is a language change but most likely not. See https://github.com/rust-lang/rust/blob/ce2ee305f9165c037ecddddb5792588a15ff6c37/src/test/ui/traits/wf-trait-object-reverse-order.rs. // @Centril
Disallows multiple regular traits in trait objects when trait aliases used, ensuring code like the following fails to compile.
Implemented cross-crate usage of trait aliases. They know get properly encoded and decoded in crate metadata. Added test.
Introduces the
DUPLICATE_AUTO_TRAITS_IN_BOUNDSlint (warn-by-default).Added test for issue ICE with trait aliases and use items #56488. (Appears to be false positive.)
Issue fixes
unexpected definition: TraitAlias#57023.INCOHERENT_AUTO_TRAIT_OBJECTSfuture-compatibility warning #57059.CC @nikomatsakis @scalexm