Skip to content

lazy_type_alias causes lifetime error #114221

Closed

Description

@matthiaskrgr

I tried this code:
tests/ui/regions/regions-scope-chain-example.rs

// run-pass
#![allow(dead_code)]
#![allow(unused_variables)]
// This is an example where the older inference algorithm failed. The
// specifics of why it failed are somewhat, but not entirely, tailed
// to the algorithm. Ultimately the problem is that when computing the
// mutual supertype of both sides of the `if` it would be faced with a
// choice of tightening bounds or unifying variables and it took the
// wrong path. The new algorithm avoids this problem and hence this
// example typechecks correctly.

// pretty-expanded FIXME #23616

enum ScopeChain<'a> {
    Link(Scope<'a>),
    End
}

type Scope<'a> = &'a ScopeChain<'a>;

struct OuterContext;

struct Context<'a> {
    foo: &'a OuterContext
}

impl<'a> Context<'a> {
    fn foo(&mut self, scope: Scope) {
        let link = if 1 < 2 {
            let l = ScopeChain::Link(scope);
            self.take_scope(&l);
            l
        } else {
            ScopeChain::Link(scope)
        };
        self.take_scope(&link);
    }

    fn take_scope(&mut self, x: Scope) {
    }
}

fn main() { }

without `-Zcrate-attr=feature(lazy_type_alias)´: no warnings

with -Zcrate-attr=feature(lazy_type_alias):

error[E0597]: `l` does not live long enough
  --> tests/ui/regions/regions-scope-chain-example.rs:31:29
   |
28 |     fn foo(&mut self, scope: Scope) {
   |                       ----- has type `Scope<'1>`
29 |         let link = if 1 < 2 {
30 |             let l = ScopeChain::Link(scope);
   |                 - binding `l` declared here
31 |             self.take_scope(&l);
   |             ----------------^^-
   |             |               |
   |             |               borrowed value does not live long enough
   |             argument requires that `l` is borrowed for `'1`
32 |             l
33 |         } else {
   |         - `l` dropped here while still borrowed

error[E0505]: cannot move out of `l` because it is borrowed
  --> tests/ui/regions/regions-scope-chain-example.rs:32:13
   |
28 |     fn foo(&mut self, scope: Scope) {
   |                       ----- has type `Scope<'1>`
29 |         let link = if 1 < 2 {
30 |             let l = ScopeChain::Link(scope);
   |                 - binding `l` declared here
31 |             self.take_scope(&l);
   |             -------------------
   |             |               |
   |             |               borrow of `l` occurs here
   |             argument requires that `l` is borrowed for `'1`
32 |             l
   |             ^ move out of `l` occurs here

error[E0597]: `link` does not live long enough
  --> tests/ui/regions/regions-scope-chain-example.rs:36:25
   |
28 |     fn foo(&mut self, scope: Scope) {
   |                       ----- has type `Scope<'1>`
29 |         let link = if 1 < 2 {
   |             ---- binding `link` declared here
...
36 |         self.take_scope(&link);
   |         ----------------^^^^^-
   |         |               |
   |         |               borrowed value does not live long enough
   |         argument requires that `link` is borrowed for `'1`
37 |     }
   |     - `link` dropped here while still borrowed

error: aborting due to 3 previous errors
rustc 1.73.0-nightly (04abc370b 2023-07-28)
binary: rustc
commit-hash: 04abc370b9f3855b28172b65a7f7d5a433f41412
commit-date: 2023-07-28
host: x86_64-unknown-linux-gnu
release: 1.73.0-nightly
LLVM version: 16.0.5

Activity

  1. added
    C-bugCategory: This is a bug.
    E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
    requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.
    F-checked_type_aliases`#![feature(checked_type_aliases)]` (formerly: `lazy_type_alias`)
    on Jul 29, 2023
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 29, 2023
  3. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Jul 29, 2023
  4. matthiaskrgr commented on Jul 29, 2023

    @matthiaskrgr
    MemberAuthor
    #![feature(lazy_type_alias)]
    
    enum ScopeChain<'a> {
        Link(Scope<'a>),
        End,
    }
    
    type Scope<'a> = &'a ScopeChain<'a>;
    
    struct Context<'a> {
        foo: &'a (),
    }
    
    impl<'a> Context<'a> {
        fn foo(&mut self, scope: Scope) {
            let link = if 1 < 2 {
                let l = ScopeChain::Link(scope);
                self.take_scope(&l);
                l
            } else {
                ScopeChain::Link(scope)
            };
        }
    
        fn take_scope(&mut self, x: Scope) {}
    }
  5. removed
    E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
    on Jul 29, 2023
  6. fmease commented on Jul 29, 2023

    @fmease
    Member

    I'm pretty sure this is due a change in variance … the lifetime params of lazy type aliases are currently unconditionally invariant it seems.
    @rustbot label A-variance

  7. added
    A-varianceArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)
    on Jul 29, 2023
  8. fmease commented on Jul 29, 2023

    @fmease
    Member

    Minimal pass→fail reproducers (passes without the feature flag and fails with lazy type aliases enabled):

    contravariant → invariant:

    struct S<'a>(T<'a>);
    
    type T<'a> = fn(&'a ());
    
    fn f<'a>(s: S<'a>) { let _: S<'static> = s; }
    
    fn main() {}

    covariant → invariant:

    struct S<'a>(T<'a>);
    
    type T<'a> = &'a ();
    
    fn f<'a>(s: S<'static>) { let _: S<'a> = s; }
    
    fn main() {}

    @rustbot label S-has-mcve

  9. fmease commented on Jul 29, 2023

    @fmease
    Member

    Not expert enough to know if this can & should be fixed (computing variances) or if this works as intended for lazy type aliases 🤔
    CC @oli-obk

  10. compiler-errors commented on Jul 29, 2023

    @compiler-errors
    Contributor

    We could theoretically compute variances for lazy type aliases.

  11. added
    S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issue
    on Jul 29, 2023
  12. fmease commented on Jul 30, 2023

    @fmease
    Member

    @rustbot claim

  13. added 2 commits that reference this issue on Aug 3, 2023
    056587b
    5ea536b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-varianceArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)C-bugCategory: This is a bug.F-checked_type_aliases`#![feature(checked_type_aliases)]` (formerly: `lazy_type_alias`)S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way. When possible, use a F-* label instead.

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions