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

lazy_type_alias causes lifetime error #114221

Closed
matthiaskrgr opened this issue Jul 29, 2023 · 6 comments · Fixed by #114253
Closed

lazy_type_alias causes lifetime error #114221

matthiaskrgr opened this issue Jul 29, 2023 · 6 comments · Fixed by #114253
Assignees
Labels
A-variance Area: Variance (https://doc.rust-lang.org/nomicon/subtyping.html) C-bug Category: This is a bug. F-lazy_type_alias `#![feature(lazy_type_alias)]` requires-nightly This issue requires a nightly compiler in some way. S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@matthiaskrgr
Copy link
Member

matthiaskrgr commented Jul 29, 2023

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
@matthiaskrgr matthiaskrgr added C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example requires-nightly This issue requires a nightly compiler in some way. F-lazy_type_alias `#![feature(lazy_type_alias)]` labels Jul 29, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jul 29, 2023
@compiler-errors compiler-errors added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jul 29, 2023
@matthiaskrgr
Copy link
Member Author

#![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) {}
}

@compiler-errors compiler-errors removed the E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example label Jul 29, 2023
@fmease
Copy link
Member

fmease commented Jul 29, 2023

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

@rustbot rustbot added the A-variance Area: Variance (https://doc.rust-lang.org/nomicon/subtyping.html) label Jul 29, 2023
@fmease
Copy link
Member

fmease commented Jul 29, 2023

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

@fmease
Copy link
Member

fmease commented Jul 29, 2023

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

@compiler-errors
Copy link
Member

We could theoretically compute variances for lazy type aliases.

@rustbot rustbot added the S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue label Jul 29, 2023
@fmease
Copy link
Member

fmease commented Jul 30, 2023

@rustbot claim

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 3, 2023
…ty-aliases, r=oli-obk

Compute variances for lazy type aliases

Fixes rust-lang#114221.

CC `@oli-obk`
r? types
@bors bors closed this as completed in 5ea536b Aug 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-variance Area: Variance (https://doc.rust-lang.org/nomicon/subtyping.html) C-bug Category: This is a bug. F-lazy_type_alias `#![feature(lazy_type_alias)]` requires-nightly This issue requires a nightly compiler in some way. S-has-mcve Status: A Minimal Complete and Verifiable Example has been found for this issue T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants