-
Notifications
You must be signed in to change notification settings - Fork 13.5k
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
} | ||
|
||
declare_lint! { | ||
pub DUPLICATE_AUTO_TRAITS_IN_BOUNDS, |
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 boundFoo: Bar + Baz
-- a compound boundBar
-- 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: Bar
andFoo: 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 operatorbound, 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 theBar
part).
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 boundFoo: Bar + Baz
-- a compound boundBar
-- 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 constraintfor<'a> Foo<'a>: Bar
-- still a constraint, but generic/universally quantified over lifetimesBar + Baz
-- a compound boundBar
-- a boundfor<'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
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.
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 theBar
infn foo<T: Bar>()
ordyn Bar
as 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_BOUNDS
lint (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_OBJECTS
future-compatibility warning #57059.CC @nikomatsakis @scalexm