Open jendrikw opened 2 years ago
I think it gets evaluated as an expression because you are missing a ::
. If you add them, then you get a new error message (play):
trait MyIterator : Iterator {}
fn main() {
let _ = MyIterator::<Item=()>::next;
}
error[E0783]: trait objects without an explicit `dyn` are deprecated
--> src/main.rs:4:13
|
4 | let _ = MyIterator::<Item=()>::next;
| ^^^^^^^^^^^^^^^^^^^^^ help: use `dyn`: `<dyn MyIterator::<Item=()>>`
I see, let me rephrase the issue:
The suggestion is "help: specify the associated type: MyIterator<Item = Type>
" where "help: specify the associated type: MyIterator::<Item = Type>
" with a double colon would be correct.
Triage: Suggestion is correct for code using dyn
(which all code written in Rust >=2021 uses).
For code written without dyn
in Rust <2021: No change. As mentioned, the suggestion should use an expression-style path (i.e., one with turbofishes).
@rustbot claim
Working on tests before creating a PR. Multiple tests exist already that have an odd hardcoded expectation for error output, so I'll be double checking those make sense with these changes, and adding a few tests of my own. Otherwise, this really does seem like it was a simple two character fix, unless I missed something somewhere.
Otherwise, this really does seem like it was a simple two character fix, unless I missed something somewhere.
Yeah, it's a pretty easy one. Adding ::
before <...>
is always correct — not only in expression contexts but also in type contexts since turbofish is also possible in type positions (e.g., fn f(_: Option::<u32>) {}
) — albeit redundant.
https://github.com/rust-lang/rust/issues/91997#issuecomment-2168508882:
As mentioned, the suggestion should use an expression-style path
Omitting ::
before <...>
in type contexts would be a possible "optimization". However, it really isn't worth doing here. Consider the following code which is ill-formed even after specifying the assoc ty.
//@ edition: 2015
trait MyIterator: Iterator {}
fn main() {
let _: MyIterator::Item;
}
MyIterator<Item = ()>::Item
(<dyn MyIterator<Item = ()>>::Item
) would only be well-formed if we defined an inherent associated type Item
(#8995) on dyn MyIterator
which doesn't work yet anyway (#106719) and is pretty niche) or once™ we support arbitrary shorthand projections (#22519).
Given the following code: [play](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=trait%20MyIterator%20%3A%20Iterator%20%7B%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20let%20_%20%3D%20MyIterator%3A%3Anext%3B%0A%20%20%20%20%2F%2Flet%20_%20%3D%20MyIterator%3CItem%3D()%3E%3A%3Anext%3B%0A%7D)
The current output is:
But when when I write
let _ = MyIterator<Item=()>::next;
, it gets interpreted as comparison expressions like(MyIterator < Item) = (() > ::next)
and it fails to compile with a lot of "cannot find valueItem
in this scope" and "cannot find cratenext
in the list of imported crates". The suggestion is confusing because it is unclear how to apply it.The error goes away if you use
Iterator
directly:let _ = Iterator::next;
produces the error one would expect: