Rust: impl dyn for AnyType fails to compile

Created on 3 May 2018  Â·  18Comments  Â·  Source: rust-lang/rust

Playpen

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.

A-edition-2018-lints A-parser T-compiler WG-epoch regression-from-stable-to-stable

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. 😛

All 18 comments

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 require trait 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. =)

Was this page helpful?
0 / 5 - 0 ratings