Skip to content
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

Inherent associated type projection does not respect where clauses #104251

Closed
compiler-errors opened this issue Nov 10, 2022 · 2 comments · Fixed by #105961
Closed

Inherent associated type projection does not respect where clauses #104251

compiler-errors opened this issue Nov 10, 2022 · 2 comments · Fixed by #105961
Assignees
Labels
C-bug Category: This is a bug. F-inherent_associated_types `#![feature(inherent_associated_types)]` requires-nightly This issue requires a nightly compiler in some way.

Comments

@compiler-errors
Copy link
Member

compiler-errors commented Nov 10, 2022

I tried this code:

#![feature(inherent_associated_types)]

struct Foo<T: ?Sized>(T);

impl<T> Foo<T> {
    type Bar = i32;
}

fn main() {
    let x: Foo<[u8]>::Bar = 1;
}

I expected to see it fail, since while Foo<[u8]> is WF, it does not satisfy the where-clauses of the impl that it's selecting the associated type Bar from.

@compiler-errors compiler-errors added C-bug Category: This is a bug. requires-nightly This issue requires a nightly compiler in some way. F-inherent_associated_types `#![feature(inherent_associated_types)]` labels Nov 10, 2022
@compiler-errors compiler-errors changed the title Inherent associated type projection does not respect nested obligations Inherent associated type projection does not respect where clauses Nov 10, 2022
@fmease
Copy link
Member

fmease commented Dec 5, 2022

For comparison, the analogous code containing an (inherent) associated constant instead leads to the following error:

error[E0599]: the associated item `BAR` exists for struct `Foo<[u8]>`, but its trait bounds were not satisfied
 --> src/main.rs:8:30
  |
1 | struct Foo<T: ?Sized>(T);
  | --------------------- associated item `BAR` not found for this struct
...
8 |     let _: () = Foo::<[u8]>::BAR;
  |                              ^^^ associated item cannot be called on `Foo<[u8]>` due to unsatisfied trait bounds
  |
  = note: the following trait bounds were not satisfied:
          `[u8]: Sized`

Code:

struct Foo<T: ?Sized>(T);

impl<T> Foo<T> {
    const BAR: () = ();
}

fn main() {
    let _: () = Foo::<[u8]>::BAR;
}

@rustbot claim

(edit: I've just noticed it says associated item cannot be called even though we're not calling anything ^^ well, that's a separate issue & I'm gonna create a GitHub issue for it sometime later)

@fmease
Copy link
Member

fmease commented Dec 6, 2022

Ah 😅 what's more, we don't actually take the concrete Self type into consideration during probing / resolution:

#![feature(inherent_associated_types)]

struct S<T>(T);

impl S<u8> {
    type P = ();
}

impl S<String> {
    type P = bool;
}

fn main() {
    let _: S<String>::P = false;
    //                    ^^^^^ expected `()`, found `bool` // <- this is incorrect!
    //                                                            the code should pass tycheck
}

I consider this to be part of this issue or at least strongly related to it. In any case, I am already looking into fixing this. Let's see if I can actually manage to do so!

Edit: I already have a working patch locally for which I am gonna open a PR after the weekend :)

@bors bors closed this as completed in 7b55296 Feb 20, 2023
RalfJung pushed a commit to RalfJung/miri that referenced this issue Feb 20, 2023
Type-directed probing for inherent associated types

When probing for inherent associated types (IATs), equate the Self-type found in the projection with the Self-type of the relevant inherent impl blocks and check if all predicates are satisfied.
Previously, we didn't look at the Self-type or at the bounds and just picked the first inherent impl block containing an associated type with the name we were searching for which is obviously incorrect.

Regarding the implementation, I basically copied what we do during method probing (`assemble_inherent_impl_probe`, `consider_probe`). Unfortunately, I had to duplicate a lot of the diagnostic code found in `rustc_hir_typeck::method::suggest` which we don't have access to in `rustc_hir_analysis`. Not sure if there is a simple way to unify the error handling. Note that in the future, `rustc_hir_analysis::astconv` might not actually be the place where we resolve inherent associated types (see rust-lang/rust#103621 (comment)) but `rustc_hir_typeck` (?) in which case the duplication may naturally just disappear. While inherent associated *constants* are currently resolved during "method" probing, I did not find a straightforward way to incorporate IAT lookup into it as types and values (functions & constants) are two separate entities for which distinct code paths are taken.

Fixes #104251 (incl. rust-lang/rust#104251 (comment)).
Fixes #105305.
Fixes #107468.

`@rustbot` label T-types F-inherent_associated_types
r? types
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. F-inherent_associated_types `#![feature(inherent_associated_types)]` requires-nightly This issue requires a nightly compiler in some way.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants