Stream: wg-traits

Topic: type aliases and implied bounds


nikomatsakis (Oct 22 2018 at 18:21, on Zulip):

So @scalexm briefly...

nikomatsakis (Oct 22 2018 at 18:22, on Zulip):

today, when we see type Foo = Bar, during type lowering we convert it into Bar

nikomatsakis (Oct 22 2018 at 18:22, on Zulip):

this means that if you have e.g. type Foo<X> = Vec<X>, and you have fn func(x: Foo<u32>), we never see Foo<u32> as a Ty<'tcx> at all

scalexm (Oct 22 2018 at 18:22, on Zulip):

ok

nikomatsakis (Oct 22 2018 at 18:22, on Zulip):

this means that we never really considered very much what bounds are declared on the type alias

nikomatsakis (Oct 22 2018 at 18:23, on Zulip):

so e.g. struct HashSet<K: Hash>, type Foo<K> = HashSet<K>, does not get an error

scalexm (Oct 22 2018 at 18:23, on Zulip):

yes I'm familiar with that

nikomatsakis (Oct 22 2018 at 18:23, on Zulip):

as you can imagine, it is hard to change this without breaking code — though perhaps not as much as I feared

nikomatsakis (Oct 22 2018 at 18:23, on Zulip):

we've been investigating various parameters of this

nikomatsakis (Oct 22 2018 at 18:23, on Zulip):

there was some hope of making some things hard errors in Rust 2018 to lay groundwork

nikomatsakis (Oct 22 2018 at 18:24, on Zulip):

in particular extra bounds

nikomatsakis (Oct 22 2018 at 18:24, on Zulip):

i.e., you could "ret-con" type Foo = Bar as having an implied where clause like WellFormed(Bar)

nikomatsakis (Oct 22 2018 at 18:24, on Zulip):

but if there are extra bounds like type Foo<T: Hash> = Vec<T>

nikomatsakis (Oct 22 2018 at 18:24, on Zulip):

and we started enforcing those

nikomatsakis (Oct 22 2018 at 18:24, on Zulip):

it would break existing code

nikomatsakis (Oct 22 2018 at 18:25, on Zulip):

so we wanted to error if you have a bound B unless WellFormed(Bar) => Implemented(B)

nikomatsakis (Oct 22 2018 at 18:25, on Zulip):

I'm however feeling like there's not time to do this change right

nikomatsakis (Oct 22 2018 at 18:25, on Zulip):

I guess I don't know if I have a question for you specifically

scalexm (Oct 22 2018 at 18:26, on Zulip):

mmh ok we want to error if you have a non-existing bound, and we would also want to error if the type alias is not well-formed, e.g. in your type Foo<K> = HashSet<K> we would now complain that K: Hash is missing?

nikomatsakis (Oct 22 2018 at 18:27, on Zulip):

well

nikomatsakis (Oct 22 2018 at 18:27, on Zulip):

if we could go back to pre-1.0 days =)

nikomatsakis (Oct 22 2018 at 18:27, on Zulip):

I think I would make type aliases be implemented literally as a kind of "custom projection"

nikomatsakis (Oct 22 2018 at 18:27, on Zulip):

e.g., type Foo<P*> = X would be

nikomatsakis (Oct 22 2018 at 18:28, on Zulip):
trait Foo<P*> {
    type Out;
}

impl<P*> Foo<P*> for () {
    type Out = X;
}
nikomatsakis (Oct 22 2018 at 18:28, on Zulip):

and each reference to Foo<A*> would be <() as Foo<A*>>::Out

nikomatsakis (Oct 22 2018 at 18:28, on Zulip):

however

nikomatsakis (Oct 22 2018 at 18:28, on Zulip):

as I said, that would break a lot of crates, probably not an option without either an edition or a long migration period,

nikomatsakis (Oct 22 2018 at 18:28, on Zulip):

mmh ok we want to error if you have a non-existing bound, and we would also want to error if the type alias is not well-formed, e.g. in your type Foo<K> = HashSet<K> we would now complain that K: Hash is missing?

precisely because of this

scalexm (Oct 22 2018 at 18:29, on Zulip):

yes ok so we just want to deal with extra bounds right now

nikomatsakis (Oct 22 2018 at 18:29, on Zulip):

I think the hope was

nikomatsakis (Oct 22 2018 at 18:29, on Zulip):

if we dealt with that

nikomatsakis (Oct 22 2018 at 18:29, on Zulip):

we could (in Rust 2018)

nikomatsakis (Oct 22 2018 at 18:29, on Zulip):

translate to this:

nikomatsakis (Oct 22 2018 at 18:29, on Zulip):
trait Foo<P*> {
    type Out;
}

impl<P*> Foo<P*> for () where WF(X) {
    type Out = X;
}
nikomatsakis (Oct 22 2018 at 18:30, on Zulip):

which would be roughly equivalent to today

nikomatsakis (Oct 22 2018 at 18:30, on Zulip):

but principled :)

nikomatsakis (Oct 22 2018 at 18:30, on Zulip):

(this would also almost work in 2015, but that extra bounds would not be enforced)

scalexm (Oct 22 2018 at 18:30, on Zulip):

ok I see

nikomatsakis (Oct 22 2018 at 18:31, on Zulip):

like I said, I'm not sure what I really wanted to ask you

scalexm (Oct 22 2018 at 18:31, on Zulip):

for extra bounds, I guess we would just to change a bit the translation

nikomatsakis (Oct 22 2018 at 18:31, on Zulip):

maybe just to bring up up to date :)

nikomatsakis (Oct 22 2018 at 18:32, on Zulip):

for extra bounds, I guess we would just to change a bit the translation

what do you mean exactly?

scalexm (Oct 22 2018 at 18:32, on Zulip):

mmh no I was thinking about adding those extra bounds on the projection type but that would not work

nikomatsakis (Oct 22 2018 at 18:35, on Zulip):

I mean we could "retcon" the current behavior by saying

nikomatsakis (Oct 22 2018 at 18:35, on Zulip):

"explicit bounds are ignored"

nikomatsakis (Oct 22 2018 at 18:35, on Zulip):

:P

nikomatsakis (Oct 22 2018 at 18:36, on Zulip):

anyway, I'm feeling like this should not be a blocker though — but it's tricky, of course, because it'd be nice to do this right and not have to wait a long time. I guess I would just like to think we can push that through as a "bug fix" sort of change

Jake Goulding (Oct 22 2018 at 19:04, on Zulip):

"retcon" the current behavior

type Foo<T>
where
    T: Into<i32>,
= Option<T>;
warning: where clauses are not enforced in type aliases
 --> src/lib.rs:3:5
  |
3 |     T: Into<i32>,
  |     ^^^^^^^^^^^^
  |
  = note: #[warn(type_alias_bounds)] on by default
  = help: the clause will not be checked when the type alias is used, and should be removed
nikomatsakis (Oct 22 2018 at 19:05, on Zulip):

yes well

nikomatsakis (Oct 22 2018 at 19:05, on Zulip):

first step, remove that lint ;)

nikomatsakis (Oct 22 2018 at 19:05, on Zulip):

although basically it evaluates to what I am proposing

Jake Goulding (Oct 22 2018 at 19:05, on Zulip):

I mean, isn't that what you want to retcon to?

nikomatsakis (Oct 22 2018 at 19:06, on Zulip):

to a certain extent, yes, indeed. This is why we added the lint in the first place, basically, because I expected we'd do some sort of retcon that rationalized the behavior

nikomatsakis (Oct 22 2018 at 19:06, on Zulip):

I .. kinda still think that should be the way to go, just for project mgmt reasons if nothing else, at least to start... I left a comment here on #55222

Jake Goulding (Oct 22 2018 at 19:09, on Zulip):

From the outside, it feels reasonable to go from that warning today to some bounds being applied, even in a regular version bump; no need for edition.

Jake Goulding (Oct 22 2018 at 19:09, on Zulip):

And continue warning for any specific types of bounds that might not be applied.

Last update: Nov 18 2019 at 00:35UTC