Skip to content

nightly: Trait resolution picks the wrong trait impl with higher ranked bounds #126006

Closed
@konnorandrews

Description

@konnorandrews

Code

I tried this code:

fn main() {
    
}

type Bound<'lt, 'ctx> = &'lt &'ctx ();

trait Raise{
    type Higher<'lt, 'ctx, B>: for<'a, 'b> Lower<'a, 'b, Bound<'a, 'b>> + Lower<'lt, 'ctx, B, T = Self>;
}

trait Lower<'lt, 'ctx, B> {
    type T: Raise<Higher<'lt, 'ctx, B> = Self>;
}

fn use_lower<'a, 'ctx: 'a, T: Raise>(x: T) {
    use_higher::<<T as Raise>::Higher::<'a, 'ctx, Bound<'a, 'ctx>>>(x);
}

fn use_higher<'a, 'ctx, H: for<'b, 'c> Lower<'b, 'c, Bound<'b, 'c>>>(x: <H as Lower<'a, 'ctx, Bound<'a, 'ctx>>>::T) {
    use_lower(x)
}

type T<'lt, 'ctx, __> = <__ as Lower<'lt, 'ctx, Bound<'lt, 'ctx>>>::T;
type HigherRanked<'lt, 'ctx, __> = <__ as Raise>::Higher::<'lt, 'ctx, Bound<'lt, 'ctx>>;

fn is_bijective_raise<'a, 'ctx: 'a, U>(
    x: &T<'a, 'ctx, HigherRanked<'a, 'ctx, U>>,
) where
    U: Raise,
{
    let _y: &U = x;
}

fn is_bijective_lower<'a, 'ctx: 'a, U>(
    x: &HigherRanked<'a, 'ctx, T<'a, 'ctx, U>>,
) where
    U: Lower<'a, 'ctx, Bound<'a, 'ctx>>,
{
    let _y: &U = x;
}

I expected to see this happen: For it to compile (based on rustc previously accepting this code)
I am not 100% sure this code is supposed to be allowed.

Instead, this happened: A compiler error

error: lifetime may not live long enough
  --> src/main.rs:16:5
   |
15 | fn use_lower<'a, 'ctx: 'a, T: Raise>(x: T) {
   |              -- lifetime `'a` defined here
16 |     use_higher::<<T as Raise>::Higher::<'a, 'ctx, Bound<'a, 'ctx>>>(x);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
   |
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
  --> src/main.rs:19:28
   |
19 | fn use_higher<'a, 'ctx, H: for<'b, 'c> Lower<'b, 'c, Bound<'b, 'c>>>(x: <H as Lower<'a, 'ctx, Bound<'a, 'ctx>>>:...
   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: lifetime may not live long enough
  --> src/main.rs:16:5
   |
15 | fn use_lower<'a, 'ctx: 'a, T: Raise>(x: T) {
   |                  ---- lifetime `'ctx` defined here
16 |     use_higher::<<T as Raise>::Higher::<'a, 'ctx, Bound<'a, 'ctx>>>(x);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'ctx` must outlive `'static`
   |
note: due to current limitations in the borrow checker, this implies a `'static` lifetime
  --> src/main.rs:19:28
   |
19 | fn use_higher<'a, 'ctx, H: for<'b, 'c> Lower<'b, 'c, Bound<'b, 'c>>>(x: <H as Lower<'a, 'ctx, Bound<'a, 'ctx>>>:...
   |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: implementation of `Lower` is not general enough
  --> src/main.rs:16:5
   |
16 |     use_higher::<<T as Raise>::Higher::<'a, 'ctx, Bound<'a, 'ctx>>>(x);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Lower` is not general enough
   |
   = note: `<T as Raise>::Higher<'2, '_, &'2 &()>` must implement `Lower<'1, 'c, &'1 &'c ()>`, for any lifetime `'1`...
   = note: ...but it actually implements `Lower<'2, '_, &'2 &()>`, for some specific lifetime `'2`

error: implementation of `Lower` is not general enough
  --> src/main.rs:16:5
   |
16 |     use_higher::<<T as Raise>::Higher::<'a, 'ctx, Bound<'a, 'ctx>>>(x);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Lower` is not general enough
   |
   = note: `<T as Raise>::Higher<'_, '2, &&'2 ()>` must implement `Lower<'b, '1, &'b &'1 ()>`, for any lifetime `'1`...
   = note: ...but it actually implements `Lower<'_, '2, &&'2 ()>`, for some specific lifetime `'2`

help: the following changes may resolve your lifetime errors
  |
  = help: replace `'a` with `'static`
  = help: replace `'ctx` with `'static`

error: could not compile `rustc_bisect_sandbox` (bin "rustc_bisect_sandbox") due to 4 previous errors

Version it worked on

It most recently worked on: Rust 1.78.0

Version with regression

Rust 1.79.0 and later. Bisected to commit 43f4f2a

@rustbot modify labels: +regression-from-stable-to-beta -regression-untriaged

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-higher-rankedArea: Higher-ranked things (e.g., lifetimes, types, trait bounds aka HRTBs)C-bugCategory: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions