Skip to content

Spurious (?) "trait bound not satisfied" with associated type constructors #34834

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
SimonSapin opened this issue Jul 15, 2016 · 4 comments · Fixed by #139778
Closed

Spurious (?) "trait bound not satisfied" with associated type constructors #34834

SimonSapin opened this issue Jul 15, 2016 · 4 comments · Fixed by #139778
Assignees
Labels
A-type-system Area: Type system C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@SimonSapin
Copy link
Contributor

SimonSapin commented Jul 15, 2016

I’m using the technique mentioned at https://github.com/rust-lang/rfcs/pull/1598/files/8e922c0cede49b0b07ac6fcf29ea736aab29acb9#r68995241 and used at https://github.com/nikomatsakis/nll/blob/master/graph-algorithms/src/lib.rs to have in a trait an associated type constructor that takes a lifetime parameter.

rustc 1.12.0-nightly (7ad125c 2016-07-11)

pub trait TypeConstructor<'a> {
    type BorrowedNamespace;
}

pub trait SelectorImpl
where Self: for<'a> TypeConstructor<'a> {
    // These two definitions should be equivalent (for `ExampleImpl`), but only the latter compiles.
    type Namespace: PartialEq + for<'a> PartialEq<<Self as TypeConstructor<'a>>::BorrowedNamespace>;
//  type Namespace: PartialEq + for<'a> PartialEq<&'a str>;

    // For illustration:
    fn get_namespace<'a>(&'a self) -> <Self as TypeConstructor<'a>>::BorrowedNamespace;
}


pub struct ExampleImpl;

impl<'a> TypeConstructor<'a> for ExampleImpl {
    type BorrowedNamespace = &'a str;
}

impl SelectorImpl for ExampleImpl {
    type Namespace = String;

    fn get_namespace<'a>(&'a self) -> &'a str { unimplemented!() }
}
error: the trait bound `for<'a> std::string::String: std::cmp::PartialEq<<ExampleImpl as TypeConstructor<'a>>::BorrowedNamespace>` is not satisfied [--explain E0277]
  --> a.rs:22:6
   |>
22 |> impl SelectorImpl for ExampleImpl {
   |>      ^^^^^^^^^^^^
help: the following implementations were found:
help:   <std::string::String as std::cmp::PartialEq>
help:   <std::string::String as std::cmp::PartialEq<str>>
help:   <std::string::String as std::cmp::PartialEq<&'a str>>
help:   <std::string::String as std::cmp::PartialEq<std::borrow::Cow<'a, str>>>
note: required by `SelectorImpl`

error: aborting due to previous error

Since<ExampleImpl as TypeConstructor<'a>>::BorrowedNamespace is &'a str for any 'a, I believe the bound for<'a> std::string::String: std::cmp::PartialEq<<ExampleImpl as TypeConstructor<'a>>::BorrowedNamespace> is equivalent to for<'a> std::string::String: std::cmp::PartialEq<&'a str>, which is the third bound that was found.

@eddyb
Copy link
Member

eddyb commented Jul 15, 2016

I believe this is #30472, although I'm not sure that is the canonical version, and that @soltanmm and @nikomatsakis have been pushing for "lazy normalization" to solve this.

@Mark-Simulacrum Mark-Simulacrum added A-type-system Area: Type system T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 23, 2017
@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 25, 2017
@steveklabnik
Copy link
Member

Triage: different error today

error[E0277]: can't compare `std::string::String` with `<ExampleImpl as TypeConstructor<'a>>::BorrowedNamespace`
  --> src/lib.rs:23:5
   |
8  |     type Namespace: PartialEq + for<'a> PartialEq<<Self as TypeConstructor<'a>>::BorrowedNamespace>;
   |          --------- associated type defined here
...
22 | impl SelectorImpl for ExampleImpl {
   | --------------------------------- in this `impl` item
23 |     type Namespace = String;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `std::string::String == <ExampleImpl as TypeConstructor<'a>>::BorrowedNamespace`
   |
   = help: the trait `for<'a> std::cmp::PartialEq<<ExampleImpl as TypeConstructor<'a>>::BorrowedNamespace>` is not implemented for `std::string::String`

error: aborting due to previous error

@fmease
Copy link
Member

fmease commented Sep 3, 2024

Triage: It now compiles. We might want to add a test before closing it.

@fmease fmease added E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-types Relevant to the types team, which will review and decide on the PR/issue. labels Sep 3, 2024
@fmease fmease added A-type-system Area: Type system and removed A-type-system Area: Type system labels Dec 21, 2024
@reddevilmidzy
Copy link
Contributor

I'd like to work on this issue!

@rustbot claim

Zalathar added a commit to Zalathar/rust that referenced this issue Apr 15, 2025
…lcnr

Add test for issue 34834

closes: rust-lang#34834

This PR adds a UI test for a case where a trait with an associated type using a higher-ranked trait bound (HRTB) failed to compile in Rust 1.55.0 but succeeded starting from 1.56.0.

```rust
pub trait Provides<'a> {
    type Item;
}

pub trait Selector: for<'a> Provides<'a> {
    type Namespace: PartialEq + for<'a> PartialEq<<Self as Provides<'a>>::Item>;

    fn get_namespace(&self) -> <Self as Provides>::Item;
}

pub struct MySelector;

impl<'a> Provides<'a> for MySelector {
    type Item = &'a str;
}

impl Selector for MySelector {
    type Namespace = String;

    fn get_namespace(&self) -> &str {
        unimplemented!()
    }
}

fn main() {}
```

* ❌ [compile fail (rustc: 1.55.0)](https://godbolt.org/z/T1jY1Ebo6)
* ⭕ [compile pass (rustc: 1.56.0)](https://godbolt.org/z/e4jo11Ma7)
jieyouxu added a commit to jieyouxu/rust that referenced this issue Apr 15, 2025
…lcnr

Add test for issue 34834

closes: rust-lang#34834

This PR adds a UI test for a case where a trait with an associated type using a higher-ranked trait bound (HRTB) failed to compile in Rust 1.55.0 but succeeded starting from 1.56.0.

```rust
pub trait Provides<'a> {
    type Item;
}

pub trait Selector: for<'a> Provides<'a> {
    type Namespace: PartialEq + for<'a> PartialEq<<Self as Provides<'a>>::Item>;

    fn get_namespace(&self) -> <Self as Provides>::Item;
}

pub struct MySelector;

impl<'a> Provides<'a> for MySelector {
    type Item = &'a str;
}

impl Selector for MySelector {
    type Namespace = String;

    fn get_namespace(&self) -> &str {
        unimplemented!()
    }
}

fn main() {}
```

* ❌ [compile fail (rustc: 1.55.0)](https://godbolt.org/z/T1jY1Ebo6)
* ⭕ [compile pass (rustc: 1.56.0)](https://godbolt.org/z/e4jo11Ma7)
@bors bors closed this as completed in bf247c7 Apr 15, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Apr 15, 2025
Rollup merge of rust-lang#139778 - reddevilmidzy:add-success-test, r=lcnr

Add test for issue 34834

closes: rust-lang#34834

This PR adds a UI test for a case where a trait with an associated type using a higher-ranked trait bound (HRTB) failed to compile in Rust 1.55.0 but succeeded starting from 1.56.0.

```rust
pub trait Provides<'a> {
    type Item;
}

pub trait Selector: for<'a> Provides<'a> {
    type Namespace: PartialEq + for<'a> PartialEq<<Self as Provides<'a>>::Item>;

    fn get_namespace(&self) -> <Self as Provides>::Item;
}

pub struct MySelector;

impl<'a> Provides<'a> for MySelector {
    type Item = &'a str;
}

impl Selector for MySelector {
    type Namespace = String;

    fn get_namespace(&self) -> &str {
        unimplemented!()
    }
}

fn main() {}
```

* ❌ [compile fail (rustc: 1.55.0)](https://godbolt.org/z/T1jY1Ebo6)
* ⭕ [compile pass (rustc: 1.56.0)](https://godbolt.org/z/e4jo11Ma7)
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-type-system Area: Type system C-bug Category: This is a bug. E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants