You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Reject bounds in type aliases in a future edition #49441
I propose to make the type_alias_bounds lint deny-by-default with the next edition. See #21903 for more information on the issue being linted, and #48326 and #48909 for the PRs implementing the lint.
I thought deny-by-default-lint was as hard as we wanted to make things in the next edition, but yeah -- there is no good reason to still allow this code, other than to ease porting to the next edition by allowing the lint.
@nikomatsakis you mentioned some plans to fix where clauses in type aliases properly, so that they are added as obligations when type aliases are expanded. What is the status of that? I think this lint should become an error in the next edition, but whether it becomes Deny-by-default or a hard error I guess depends on whether we need this to be rule out for a transition in the 2021 edition.
After some talking with @Centril, I think ideally we want a lint that
complains about type SendVec<T: Send> = Vec<T> because the bound is ignored
complains about type Baz<I> = <I as Iterator>::Item because associated items should have a bound
does not complain about type Baz<I: Iterator> = <I as Iterator>::Item because the bound is, de facto, enforced after expansion.
What makes this hard is that associated items are not the only way that a bound can be used; using a type like struct Foo<T: Send>(T) is another way -- but @eddyb said he had ideas.
My idea is to diff what WF needs (i.e. the things that would error if not satisfied) with the predicates (bounds) written by the user.
Without Chalk this will be tricky, but we can manually run trait selection (or just plug something optional into the fulfillment context) to peek at how each WF requirement is satisfied, and mark every predicate that actually ends up used as part of that process, as useful - everything else, we'll warn (we can even have a consistency check, that if we remove the "unused bounds", WF still passes).
EDIT: Hang on, we might be able to do "difference" much easier by trying every declared bound with WF bounds as assumed: if they fail, that means the WF conditions enforced onto the user of the type alias aren't enough to subsume it, which is really what we want to check for (equivalence)!
We actually have a very good reason to check "WF of RHS implies bounds" and not "used":
typeDEIItem<T:DoubleEndedIterator> = T::Item;
The DoubleEndedIterator bound won't be checked in uses, only WF(T::Item) i.e. T: Iterator will.
And whenever we can start checking uses, then we don't really care if the bounds are used.
Since I see this being considered for edition 2024, I'll note that this lint fires on lifetime bounds which, while not enforced, are also not inert. In summary, if you want the below alias to behave like &T behaves with regards to dyn lifetime defaults, you need the bound (and removing the bound can break code relying on it).
pubtypeBorrow<'a,T:'a> = &'aT;// With the bound, `Borrow<'a, dyn Trait>` is `&'a (dyn Trait + 'a)`// Without the bound, it is `&'a (dyn Trait + 'static)`
Activity
RalfJung commentedon Mar 28, 2018
Also maybe in the light of this, the lint message should be extended to also link to #21903 or something else providing further information?
Manishearth commentedon Mar 28, 2018
cc @withoutboats
We can make it a hard error instead, fwiw.
RalfJung commentedon Mar 28, 2018
I thought deny-by-default-lint was as hard as we wanted to make things in the next edition, but yeah -- there is no good reason to still allow this code, other than to ease porting to the next edition by allowing the lint.
Would that mean this is a topic for rustfix?
Manishearth commentedon Mar 28, 2018
Yes -- edition breakages work by taking a warn lint in a certain group and making it a hard error; and having a good suggestion that rustfix can apply
RalfJung commentedon May 27, 2018
@nikomatsakis you mentioned some plans to fix where clauses in type aliases properly, so that they are added as obligations when type aliases are expanded. What is the status of that? I think this lint should become an error in the next edition, but whether it becomes Deny-by-default or a hard error I guess depends on whether we need this to be rule out for a transition in the 2021 edition.
RalfJung commentedon Aug 20, 2018
After some talking with @Centril, I think ideally we want a lint that
type SendVec<T: Send> = Vec<T>because the bound is ignoredtype Baz<I> = <I as Iterator>::Itembecause associated items should have a boundtype Baz<I: Iterator> = <I as Iterator>::Itembecause the bound is, de facto, enforced after expansion.What makes this hard is that associated items are not the only way that a bound can be used; using a type like
struct Foo<T: Send>(T)is another way -- but @eddyb said he had ideas.eddyb commentedon Aug 20, 2018
My idea is to diff what WF needs (i.e. the things that would error if not satisfied) with the predicates (bounds) written by the user.
Without Chalk this will be tricky, but we can manually run trait selection (or just plug something optional into the fulfillment context) to peek at how each WF requirement is satisfied, and mark every predicate that actually ends up used as part of that process, as useful - everything else, we'll warn (we can even have a consistency check, that if we remove the "unused bounds", WF still passes).EDIT: Hang on, we might be able to do "difference" much easier by trying every declared bound with WF bounds as assumed: if they fail, that means the WF conditions enforced onto the user of the type alias aren't enough to subsume it, which is really what we want to check for (equivalence)!
eddyb commentedon Aug 25, 2018
We actually have a very good reason to check "WF of RHS implies bounds" and not "used":
The
DoubleEndedIteratorbound won't be checked in uses, onlyWF(T::Item)i.e.T: Iteratorwill.And whenever we can start checking uses, then we don't really care if the bounds are used.
eddyb commentedon Sep 7, 2018
I guess this is the same problem I recognized last year (#44075 (comment)), but now I have a plan.
RalfJung commentedon Sep 9, 2018
@eddyb What is the deadline for this so that it could actually be an error in the next edition? Seeing #54057 makes me think it is already too late.
37 remaining items
RalfJung commentedon Oct 25, 2018
Related: #55222
[-]Reject bounds in type aliases with edition 2018[/-][+]Reject bounds in type aliases with edition 2024[/+]jpost-collegenet commentedon Dec 13, 2023
Since I see this being considered for edition 2024, I'll note that this lint fires on lifetime bounds which, while not enforced, are also not inert. In summary, if you want the below alias to behave like
&Tbehaves with regards todynlifetime defaults, you need the bound (and removing the bound can break code relying on it).I.e. this applies to alias definitions in addition to
struct(etc) definitions.fmease commentedon Jan 10, 2024
Superseded by #112792.
[-]Reject bounds in type aliases with edition 2024[/-][+]Reject bounds in type aliases a future edition[/+][-]Reject bounds in type aliases a future edition[/-][+]Reject bounds in type aliases in a future edition[/+]