Skip to content

the type of ProjectionElem::Field is not correct wrt subtyping #96514

@lcnr

Description

@lcnr
struct Foo<T>(T); // `T` is covariant.

fn foo<'b>(x: Foo<for<'a> fn(&'a ())>) {
    let Foo(y): Foo<fn(&'b ())> = x;
}

fn main() {}

should compile but errors with

error[E0308]: mismatched types
 --> src/main.rs:4:13
  |
4 |     let Foo(y): Foo<fn(&'b ())> = x;
  |             ^ one type is more general than the other
  |
  = note: expected fn pointer `for<'a> fn(&'a ())`
             found fn pointer `fn(&())`

looking at the mir of foo it becomes clear why that happens:

fn foo(_1: Foo<for<'a> fn(&'a ())>) -> () {
    debug x => _1;                       // in scope 0 at src/main.rs:3:12: 3:13
    let mut _0: ();                      // return place in scope 0 at src/main.rs:3:40: 3:40
    let _2: fn(&()) as UserTypeProjection { base: UserType(0), projs: [Field(field[0], ())] }; // in scope 0 at src/main.rs:4:13: 4:14
    scope 1 {
        debug y => _2;                   // in scope 1 at src/main.rs:4:13: 4:14
    }

    bb0: {
        AscribeUserType(_1, +, UserTypeProjection { base: UserType(1), projs: [] }); // scope 0 at src/main.rs:4:17: 4:32
        StorageLive(_2);                 // scope 0 at src/main.rs:4:13: 4:14
        _2 = (_1.0: fn(&()));            // scope 0 at src/main.rs:4:13: 4:14
        _0 = const ();                   // scope 0 at src/main.rs:3:40: 5:2
        StorageDead(_2);                 // scope 0 at src/main.rs:5:1: 5:2
        return;                          // scope 0 at src/main.rs:5:2: 5:2
    }
}

notice that in _2 = (_1.0: fn(&())); the type of _1.0 is actually for<'a> fn(&'a ()).

Possible ways to fix this are:

  • correctly deal with subtyping when sanitizing field projections, note that they cannot just always be covariant.
  • change the type of the field to be the actual one during mir building, so that subtyping actually happens at the assignment
  • always lazily recompute the type of the field instead of storing it in the mir

Metadata

Metadata

Assignees

Labels

A-varianceArea: Variance (https://doc.rust-lang.org/nomicon/subtyping.html)C-bugCategory: This is a bug.E-hardCall for participation: Hard difficulty. Experience needed to fix: A lot.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.T-typesRelevant to the types team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions