Skip to content

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

New issue

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

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

Already on GitHub? Sign in 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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