fn main() {
let s = Box::new(S);
let d = s as Box<dyn dyn>;
d.say();
}
trait dyn {
fn say(&self) -> &'static str;
}
struct S;
impl dyn for S {
fn say(&self) -> &'static str { "I'm S!" }
}
Expected: Program outputs "I'm S!" (missed a println) compiles.
Actual:
Compiling playground v0.0.1 (file:///playground)
error: expected `<`, found `S`
--> src/main.rs:13:14
|
13 | impl dyn for S {
| ^ expected `<` here
error: aborting due to previous error
error: Could not compile `playground`.
Since dyn
is a contextual keyword and still allowed as an identifier, I expect to still be able to implement a trait named "dyn" for various structs. And indeed, if I change the trait name to "dyna", it works.
You could use impl dyn<> for S { }
as workaround.
Actually, this is failing on stable as well? Uhh....
It's failing in Rust 1.24 (on my computer) and Rust 1.25 (playpen). I don't have older versions of Rust to test with.
Update: Using Godbolt, it compiles on Rust 1.22 and fails to compile on Rust 1.23.
triage: P-high
Parsing regression. @petrochenkov seems to be on it =)
Also, @Havvy, you are a bad, bad person for trying to do this. 😛
We need to increase lookahead to at least 2 tokens to disambiguate (I'll submit a PR soon-ish).
for
alone looks too much like a bound start for a poly-trait bound dyn for<'a> Trait<'a>
.
But it would still be not enough for precise disambiguation, because impl dyn for <Type as Trait>::AssocTy { ... }
is not a dyn Trait
.
So we'd need to 3 tokens, but that would be not enough too because impl dyn for <'a + Trait1 as Trait2>::AssocTy { ... }
is not a dyn Trait
either.
So maybe we shouldn't even start increasing lookahead and keep breakage as is?
Nominating for lang team discussion.
AFAICT this needs infinite look-ahead to work as a contextual keyword.
What was the outcome of the lang team discussion?
Oops! I'll try to leave a more polished comment later :) but the TL;DR was we felt like it was not necessarily worth fixing this.
Argh. I'm slow. The basic conclusion was that we felt like it was not worth trying to fix this, given the complications that it induces, and given that (as far as we know) no real code in the wild is relying on being able to name a trait dyn
(if that last assumption is false, I would like to know). Even if there were such code, presumably it can be rewritten to use r#dyn
— a shame to force a rewrite, but it's really an edge case.
However, it occurs to me now in we might want to at least make it a hard error to declare such a trait for clarity. That is, we should not parse trait dyn { }
successfully either (and require trait r#dyn
).
Thoughts on this @rust-lang/lang or @petrochenkov ?
However, it occurs to me now in we might want to at least make it a hard error to declare such a trait for clarity. That is, we should not parse
trait dyn { }
successfully either (and requiretrait r#dyn
).
Nominating again both to double check on this final point (lang) and to try and assess a priority (compiler or lang).
I agree that it makes sense to disallow trait dyn
if you can't impl dyn
.
We discussed in the @rust-lang/lang meeting and decided that we should prohibit traits named dyn
, full stop, pending any further complications.
My sense is that this is high priority because of back-compat, hence I am going to mark as P-high
. I may or may not prep the PR =) — @petrochenkov maybe you would like to do it?
OK, we've made no progress here. Assigning to myself, I'll try to whip up a patch.
Almost got this PR prepared. Sorry, kept putting this off. I wound up just banning dyn
from being used for the name of any type, for consistency.
OK, on the PR discussion, we decided to take a somewhat different tack.
Basically: you can name traits as dyn
, but to implement them, you should write impl self::dyn
or impl r#dyn
. Seems fine.
I'm going to close this issue then. Thanks to @Havvy for bringing it to our attention. =)
Most helpful comment
triage: P-high
Parsing regression. @petrochenkov seems to be on it =)
Also, @Havvy, you are a bad, bad person for trying to do this. 😛