Skip to content

old solver doesn't check normalization constraints in compare_impl_item #166

@lcnr

Description

@lcnr
trait Trait {
    type Assoc<'a>
    where
        Self: 'a;
}
impl<'b> Trait for &'b u32 {
    type Assoc<'a> = &'a u32
    where
        Self: 'a; 
}

trait Bound<T> {}
trait Entailment<T: Trait> {
    fn method()
    where
        Self: for<'a> Bound<<T as Trait>::Assoc<'a>>;
}

impl<'b, T> Entailment<&'b u32> for T {
    // Instantiates trait where-clauses with `&'b u32` and then normalizes
    // `T: for<'a> Bound<<&'b u32 as Trait>::Assoc<'a>>` in a separate infcx
    // without checking region constraints.
    //
    // It normalizes to `T: Bound<&'a u32>`, dropping the `&'b u32: 'a` constraint.
    fn method()
    where
        Self: for<'a> Bound<&'a u32>
    {}
}

fn main() {}

https://github.com/rust-lang/rust/blob/aaa861493456e8a10e552dd208f85486de772007/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs#L238-L239

The new solver doesn't eagerly normalize the hybrid env in compare_impl_item, so it actually ends up normalizing <&'b u32 as Trait>::Assoc<'a> in the 'main' infcx, checking the resulting region constraints

This requires the associated type to be rigid in the trait method and normalizeable in the hybrid env. To do that, the trait bound proving T: Trait needs to be on the trait instead of the method. Alternatively, we could probably use a where-bound which ends up global after instantiating with the impl args.

affected tests

  • tests/ui/higher-ranked/trait-bounds/issue-102899.rs
  • tests/ui/higher-ranked/trait-bounds/issue-100689.rs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    has mentoring instructions

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions