Rust: `T: ?Sized` does not work in `where` clauses

Created on 4 Jan 2015  路  15Comments  路  Source: rust-lang/rust

fn foo<T>(x: &T) where T: ?Sized {} // error: unexpected `?`

The RFC states that the syntax should work in where clauses.

A-dst

Most helpful comment

There at least should be some better error message telling one to put ?Sized into the definition instead of the where clause.

All 15 comments

Note that we don't currently accept where Sized? T, so there is no backwards compatibility hazard here. Although we should certainly fix this, it doesn't need to be done for 1.0 (it probably should be though).

@nick29581 I will poke into this.

There are a few edge cases here. In particular, specifying ?Sized in a where clause should probably only be allowed at the type parameter鈥檚 definition site; e.g., the following probably shouldn鈥檛 be allowed:

impl<T> Foo<T> {
    fn foo(&self) where T: ?Sized { ... }
}

Although allowing that could potentially be useful, I suspect it would complicate the implementation and be slightly unclear anyway.

Additionally, specifying ?Sized on an associated type is unnecessary. In general, specifying ?Sized on anything that isn鈥檛 a type parameter is somewhat nonsensical: where Option<T>: ?Sized doesn鈥檛 really make much sense either.

What needs to be done in order to get this working? Is it just a parsing issue?

Triage: still a really annoying problem.

@Gankro I can fix this, probably my fault anyways.

This is still a bit of a wart, and tripped me up the first time I wanted to use a ?Sized bound.

I hit this issue today.

@jroesch although it was a few months ago, do you remember enough context to write a very quick summary of where changes would need to be made to fix this?

Ran into this one today. Is it just a parsing problem?

IIRC this also needs to be handled in astconv

add_unsized_bound would have to take the where-clause of the item into account, but I think the where-clause isn't available there.

There at least should be some better error message telling one to put ?Sized into the definition instead of the where clause.

This is really a papercut issue.

While when I hit I generally remember "Oh yeah, this bug again" and promptly fixes it, it still would be a much smoother experience if I did not have to.

Note that in the same vein, it is not supported in a trait bounds either (eg: trait X: ?Sized does not work).

I tried to fix this but have immediately drowned in philosophical questions.

?Sized at the moment is not a true bound, but a command - "do not implicitly add Sized bound".
I.e.

fn f<FreshParameter: ?Sized + OtherBounds1>() where ExistingType: OtherBounds2 { ... }

is desugared into

// `Sized` bound is not implicitly added
fn f<FreshParameter: OtherBounds1>() where ExistingType: OtherBounds2 { ... }

and

fn f<FreshParameter: OtherBounds1>() where ExistingType: OtherBounds2 { ... }

is desugared into

`Sized` bound is implicitly added
fn f<FreshParameter: Sized + OtherBounds1>() where ExistingType: OtherBounds2 { ... }

A few conclusions from this:

  • where clauses don't implicitly add Sized bounds so the command ?Sized don't do anything on them
  • ?Sized makes sense only when we define some new entity (like type parameter introduction or associated type definition do) and don't make sense when we require some bounds from an already existing entity.

So, how I think the fix should look:

  • TYPE: ?Trait bounds from where clauses are internally moved on parameter definitions if and only if TYPE is a bare type parameter defined in the current item.
  • if TYPE is a type parameter from one of parent items or any other arbitrary type, then error is reported.
  • where (FreshParameter): ?Sized is a questionable case. I'd classify it as "any other arbitrary type" and report an error, but the information about parens is lost in HIR.

Other stuff:

  1. It's not just parsing issue.
  2. @matthieu-m

it is not supported in a trait bounds either (eg: trait X: ?Sized does not work).

traits are ?Sized by default, so trait X: ?Sized doesn't make much sense. It's matter of a better error message (and the error should certainly not be reported in the parser, like now).

Was this page helpful?
0 / 5 - 0 ratings