Skip to content
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

Unused trait bound with lifetime causes compile error #53156

Open
lo48576 opened this issue Aug 7, 2018 · 4 comments
Open

Unused trait bound with lifetime causes compile error #53156

lo48576 opened this issue Aug 7, 2018 · 4 comments
Labels
A-trait-system Area: Trait system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@lo48576
Copy link
Contributor

lo48576 commented Aug 7, 2018

Summary

What happens

  • Unused trait bound causes compile error.
    • In non-(3c) case, Into::<Arc<B>>::into() is completely unused, but &'a B: Into<Arc<B>> causes compile error.
    • I think this may be a compiler issue.
  • With either of these small modifications, they successfully compile.
    • Changing &a B: Into<Arc<B>> to for<'b> &'b B: Into<Arc<B>>.
    • Changing &self to &'a self (or wrap: &OwnedWrap<B> to wrap: &'a OwnedWrap<B>).

Expected behavior

  • Unused trait bound does not cause compile error.
  • With where B: 'a + ToOwned + ?Sized, &'a B: Into<Arc<B>>,
    let b: &B = owned.borrow(); successfully compiles.
    • I think let b: &B = owned.borrow(); does not require b to outlive lifetime of &self nor 'a,
      so it should not be error.
    • owned.borrow().into() might be error though, but I think it is OK because owned.borrow() does not outlive 'a but Into<Arc<B>> requires 'a &B.

Meta

  • Compiler version: 1.28.0 (stable)

Code to reproduce

Simplified cases 1: in impl

Basic code: https://play.rust-lang.org/?gist=40cb0fa71f3bd32091fbc3e144db2de1&version=stable&mode=debug&edition=2015

//#![feature(nll)]

use std::borrow::Borrow;
use std::sync::Arc;

struct OwnedWrap<B: ToOwned + ?Sized>(<B as ToOwned>::Owned);

impl<'a, B> OwnedWrap<B>
where
    B: 'a + ToOwned + ?Sized,
    &'a B: Into<Arc<B>>, // (1a) does not compile.
    //for<'b> &'b B: Into<Arc<B>>, // (1b) successfully compiles.
{
    pub fn to_arc(&self) -> Arc<B> { // (2a) does not compile.
    //pub fn to_shared(&'a self) -> Arc<B> { // (2b) `successfully compiles.
        let OwnedWrap(ref owned) = *self;
        let b: &B = owned.borrow(); // (3a) does not compile.
        //let _: &B = owned.borrow(); // (3b) error with NLL, compiles without NLL.

        //owned.borrow().into() // (3c) What I want to do.
        unimplemented!() // comment in when using 3c.
    }
}

fn main() {}

Error for (1a-2a-3a) without NLL:

   Compiling playground v0.0.1 (file:///playground)
error[E0495]: cannot infer an appropriate lifetime for pattern due to conflicting requirements
  --> src/main.rs:16:23
   |
16 |         let OwnedWrap(ref owned) = *self;
   |                       ^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 14:5...
  --> src/main.rs:14:5
   |
14 | /     pub fn to_arc(&self) -> Arc<B> { // (2a) does not compile.
15 | |     //pub fn to_shared(&'a self) -> Arc<B> { // (2b) `successfully compiles.
16 | |         let OwnedWrap(ref owned) = *self;
17 | |         let b: &B = owned.borrow(); // (3a) does not compile.
...  |
21 | |         unimplemented!() // comment in when using 3c.
22 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:16:23
   |
16 |         let OwnedWrap(ref owned) = *self;
   |                       ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 8:1...
  --> src/main.rs:8:1
   |
8  | / impl<'a, B> OwnedWrap<B>
9  | | where
10 | |     B: 'a + ToOwned + ?Sized,
11 | |     &'a B: Into<Arc<B>>, // (1a) does not compile.
...  |
22 | |     }
23 | | }
   | |_^
   = note: ...so that the types are compatible:
           expected std::marker::Sized
              found std::marker::Sized

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
error: Could not compile `playground`.

Error for (1a2a-3a) with NLL:

   Compiling playground v0.0.1 (file:///playground)
warning: unused variable: `b`
  --> src/main.rs:17:13
   |
17 |         let b: &B = owned.borrow(); // (3a) does not compile.
   |             ^ help: consider using `_b` instead
   |
   = note: #[warn(unused_variables)] on by default

error: unsatisfied lifetime constraints
  --> src/main.rs:17:21
   |
8  | impl<'a, B> OwnedWrap<B>
   |      -- lifetime `'a` defined here
...
14 |     pub fn to_arc(&self) -> Arc<B> { // (2a) does not compile.
   |                   - let's call the lifetime of this reference `'1`
...
17 |         let b: &B = owned.borrow(); // (3a) does not compile.
   |                     ^^^^^^^^^^^^^^ requires that `'1` must outlive `'a`

error: aborting due to previous error

error: Could not compile `playground`.

Simplified cases 2: toplevel fn

Basic code: https://play.rust-lang.org/?gist=649f1a00835b68d4b51ef4a78a5ac857&version=stable&mode=debug&edition=2015

//#![feature(nll)]

use std::borrow::Borrow;
use std::sync::Arc;

struct OwnedWrap<B: ToOwned + ?Sized>(<B as ToOwned>::Owned);

fn to_arc<'a, B>(wrap: &OwnedWrap<B>) -> Arc<B> // (2a) does not compile.
//fn to_arc<'a, B>(wrap: &'a OwnedWrap<B>) -> Arc<B> // (2b) successfully compiles.
where
    B: 'a + ToOwned + ?Sized,
    &'a B: Into<Arc<B>>, // (1a) does not compile.
    //for<'b> &'b B: Into<Arc<B>>, // (1b) successfully compiles.
{
        let OwnedWrap(ref owned) = wrap;
        let b: &B = owned.borrow(); // (3a) does not compile.
        //let _: &B = owned.borrow(); // (3b) error with NLL, compiles without NLL.

        //owned.borrow().into() // (3c) What I want to do.
        unimplemented!() // comment out when using 3c.

}

fn main() {}

FYI: What I've wanted to do

This code is more meaningful than simplified cases.
https://play.rust-lang.org/?gist=2b304fda2af1102dff60b72b5681a945&version=nightly&mode=debug&edition=2015

@nikomatsakis
Copy link
Contributor

This is basically #21974, I believe. We may want to close as a duplicate.

@nikomatsakis
Copy link
Contributor

But maybe it's useful to keep this specific case around.

@nikomatsakis
Copy link
Contributor

I'm not really sure how to fix this — I think that chalk integration is a sort of pre-requisite.

@nikomatsakis nikomatsakis added A-trait-system Area: Trait system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 7, 2018
@istankovic
Copy link
Contributor

Both examples from the description compile successfully (with unused code warnings, though) with

rustc 1.75.0-nightly (0039d739d 2023-10-18)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants