Skip to content

Associated types bug related to trait objects #30833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
defyrlt opened this issue Jan 12, 2016 · 10 comments
Closed

Associated types bug related to trait objects #30833

defyrlt opened this issue Jan 12, 2016 · 10 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one.

Comments

@defyrlt
Copy link

defyrlt commented Jan 12, 2016

Playpen
Relevant code (note that DoesStuff is a trait):

impl Deref for Foobar {
    type Target = DoesStuff;

    fn deref(&self) -> &Self::Target {
        match self {
            &Foobar::Foo(ref e) => {
                let newref = e.clone();
                newref as &DoesStuff // error here
                // newref as &Self::Target // just works..
                // newref // returning without `as` works (code below works too)
            }
            &Foobar::Bar(ref e) => e,
        }
    }
}

Error text:

<anon>:26:26: 26:31 error: cannot infer an appropriate lifetime for pattern due to conflicting requirements [E0495]
<anon>:26             &Foobar::Foo(ref e) => {
                                   ^~~~~
<anon>:27:30: 27:39 note: first, the lifetime cannot outlive the method call at 27:29...
<anon>:27                 let newref = e.clone();
                                       ^~~~~~~~~
<anon>:27:30: 27:31 note: ...so that method receiver is valid for the method call
<anon>:27                 let newref = e.clone();
                                       ^
<anon>:24:38: 34:6 note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the block at 24:37...
<anon>:24     fn deref(&self) -> &Self::Target {
<anon>:25         match self {
<anon>:26             &Foobar::Foo(ref e) => {
<anon>:27                 let newref = e.clone();
<anon>:28                 newref as &DoesStuff // error here
<anon>:29                 // newref as &Self::Target // just works..
          ...
<anon>:28:17: 28:37 note: ...so that trait type parameters matches those specified on the impl (expected `core::ops::CoerceUnsized<&DoesStuff + 'static>`, found `core::ops::CoerceUnsized<&DoesStuff + 'static>`)
<anon>:28                 newref as &DoesStuff // error here
                          ^~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
playpen: application terminated with error code 101

cc @mbrubeck since on the IRC you've told me that it's worthy filing an issue :)

@defyrlt
Copy link
Author

defyrlt commented Jan 12, 2016

I've discovered something alike on the same code sample.
Relevant code:

impl Deref for Foobar {
    type Target = DoesStuff;

    fn deref(&self) -> &DoesStuff {
        self as &DoesStuff
    }
}

fails with

<anon>:22:5: 24:6 error: method `deref` has an incompatible type for trait:
 expected bound lifetime parameter ,
    found concrete lifetime [E0053]
<anon>:22     fn deref(&self) -> &DoesStuff {
<anon>:23         self as &DoesStuff
<anon>:24     }
<anon>:22:5: 24:6 help: see the detailed explanation for E0053
error: aborting due to previous error
playpen: application terminated with error code 101

Note the space before the comma here - expected bound lifetime parameter , - it's interesting.
Changing function signature to fn deref(&self) -> &Self::Target does the trick - the error that is produced is correct.
Playpen

@defyrlt defyrlt changed the title Associated types bug Associated types bug related to trait objects Jan 12, 2016
@arielb1
Copy link
Contributor

arielb1 commented Jan 12, 2016

This is caused by the implicit lifetime bound in trait objects: DoesStuff is DoesStuff+'static while &DoesStuff is &'a DoesStuff+'a.

@defyrlt
Copy link
Author

defyrlt commented Jan 13, 2016

The second one, right? The first one does not seem to be related to implicit lifetime bound.

@arielb1
Copy link
Contributor

arielb1 commented Jan 13, 2016

DoesStuff+'a is a distinct type from DoesStuff+'static, so you have a type mismatch.

@defyrlt
Copy link
Author

defyrlt commented Jan 14, 2016

The first one says

<anon>:28:17: 28:37 note: ...so that trait type parameters matches those specified on the impl (expected `core::ops::CoerceUnsized<&DoesStuff + 'static>`, found `core::ops::CoerceUnsized<&DoesStuff + 'static>`)

so I don't see type mismatch here.
Don't you agree that it's a bug?

@arielb1
Copy link
Contributor

arielb1 commented Jan 14, 2016

It is not a bug.

The type on the trait is &'a DoesStuff + 'static. The type on your impl is &'s DoesStuff + 's for some lifetime 's, which is not the same (because 'a != 'static). Therefore the error.

We might want to improve the diagnostics (especially, the "bound lifetime parameter ," sucks), but the compile error is for real.

@arielb1 arielb1 added the A-diagnostics Area: Messages for errors, warnings, and lints label Jan 14, 2016
@steveklabnik steveklabnik removed the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Mar 9, 2017
@Mark-Simulacrum Mark-Simulacrum added C-bug Category: This is a bug. C-enhancement Category: An issue proposing an enhancement or a PR with one. and removed C-bug Category: This is a bug. labels Jul 24, 2017
@memoryruins
Copy link
Contributor

Triage: the first example currently compiles. Checking godbolt, it has compiled since 1.16

The second playground link, posted by defyrlt, has an error that now looks like the following:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
  --> src/main.rs:22:5
   |
22 |     fn deref(&self) -> &DoesStuff {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:5...
  --> src/main.rs:22:5
   |
22 | /     fn deref(&self) -> &DoesStuff {
23 | |     // fn deref(&self) -> &Self::Target {
24 | |         self as &DoesStuff
25 | |     }
   | |_____^
   = note: ...but the lifetime must also be valid for the static lifetime...
   = note: ...so that the method type is compatible with trait:
           expected fn(&Foobar) -> &(dyn DoesStuff + 'static)
              found fn(&Foobar) -> &dyn DoesStuff

error: aborting due to previous error

rust version 1.34.0-nightly (c1c3c4e95 2019-01-29)

@arielb1 arielb1 added E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. and removed E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. labels Feb 2, 2019
@arielb1
Copy link
Contributor

arielb1 commented Feb 2, 2019

The first bug was fixed in rustc 1.16, the second (diagnostic bug, which I thought was the only bug) was fixed in 1.11.

It might be worth seeing whether the first bug is covered by our test-suite and which PR fixed it.

@arielb1 arielb1 added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Feb 2, 2019
@arielb1
Copy link
Contributor

arielb1 commented Feb 2, 2019

That appears to be #38624

@arielb1 arielb1 removed the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Feb 2, 2019
@arielb1
Copy link
Contributor

arielb1 commented Feb 2, 2019

So the first bug was that &Foo used to be treated as &'$0 Foo + '$0 instead of as &'$0 Foo + '$1 - it started to mean the second interpretation in #39305, which has a test for the new behavior.

The diagnostics bug is probably covered by quite a few diagnostics tests, so there isn't much more to check. Closing.

@arielb1 arielb1 closed this as completed Feb 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints C-enhancement Category: An issue proposing an enhancement or a PR with one.
Projects
None yet
Development

No branches or pull requests

5 participants