Skip to content

alias-bounds consider non_self_assumptions for the alias self type #149

Closed
rust-lang/rust
#135902
@lcnr

Description

@lcnr

affected test

  • tests/ui/associated-type-bounds/cant-see-copy-bound-from-child-rigid.rs
trait Id {
    type This: ?Sized;
}

trait Trait {
    type Assoc: Id<This: Copy>;
}

fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc)
where 
    T::Assoc: Id<This = T::Assoc>,
{
    (x, x)
}

This passes with the new solver, but not the old.

The reason is annoying subtle!

In the new solver computing alias bounds looks at all item bounds of the alias: https://github.com/rust-lang/rust/blob/cd805f09ffbfa3896c8f50a619de9b67e1d9f3c3/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs#L583-L593

In the old solver computing alias bounds only looks at item_super_predicates in the first step: https://github.com/rust-lang/rust/blob/cd805f09ffbfa3896c8f50a619de9b67e1d9f3c3/compiler/rustc_trait_selection/src/traits/select/mod.rs#L1617-L1625

When proving T::Assoc: Copy only the new solver therefore considers the item bound <T::Assoc as Id>::This: Copy. It is then able to normalize <T::Assoc as Id>::This to T::Assoc, allowing us to prove the goal.

We're only able to do this, if there's a projection clause in the ParamEnv or in the item bounds of our associated type:

trait Id {
    type This: ?Sized;
}
impl<T: ?Sized> Id for T {
    type This = T;
}

trait Normalize: Id<This = Self> {}
trait Trait {
    type Assoc: Id<This: Copy> + Normalize;
}

fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc) {
    (x, x)
}

fn main() {}

As we can definitely use the item bound to prove T::Assoc: Id, we cannot use an impl to normalize the <T::Assoc as Id>::This, instead treating this associated type as rigid. The following does not compile:

trait Id {
    type This: ?Sized;
}
impl<T: ?Sized> Id for T {
    type This = T;
}

trait Trait {
    type Assoc: Id<This: Copy>;
}

fn foo<T: Trait>(x: T::Assoc) -> (T::Assoc, T::Assoc) {
    (x, x) //~ERROR use of moved value: `x`
}

fn main() {}

Metadata

Metadata

Type

No type

Projects

Status

done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions