If inherent associated type selection fails, we should still consider trait associated type candidates as a fallback
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
For context, applicable inherent associated item candidates shadow trait associated item ones (where applicable means the self type of the candidate impl unifies and its predicates hold). IAT selection does respect that which is good as it follows the behavior of associated functions and constants (in bodies).
However, contrary to inherent associated functions and constants (in bodies), we currently bail out early with a hard error if we fail to select an applicable IAT! Moreover assuming PR #140247 gets merged in its current form, this will extend to candidates in general. Meaning, we'll error early if there are no candidates whatsoever! (See my separate comment for an example).
Ideally, we'd only fail overall if we also failed to find a suitable trait associated type candidate (by means of resolve_type_relative_path). Rephrased, inapplicable IAT candidates should not shadow trait assoc ty candidates.
Examples
Inherent Associated Types
These should compile but currently don't for the reason mentioned above.
#![feature(inherent_associated_types)]
struct Type;
trait Trait { type AssocTy; fn scope(); }
impl Type // *inapplicable* impl candidate (predicate `<String as Copy>` is unsatisfied)
where
for<'_delay> String: Copy,
{
type AssocTy = i32; // the IAT
}
impl Trait for Type {
type AssocTy = ();
fn scope() {
let (): Self::AssocTy; //~ ERROR the associated type `AssocTy` exists for `Type`, but its trait bounds were not satisfied
// ^^^^^^^^^^^^^ Ideally, this would resolve to the *trait* associated type
// `<Self as Trait>::AssocTy` (via resolve_type_relative_path/SelfTyAlias)
// given the fact that the IAT candidate is *inapplicable*!
}
}
fn main() { <Type as Trait>::scope(); }
#![feature(inherent_associated_types)]
struct Type<T>(T);
trait Trait { type AssocTy; fn scope(); }
impl Type<u128> { // *inapplicable* impl candidate (`u128` doesn't unify with `()`)
type AssocTy = i32; // the IAT
}
impl Trait for Type<()> {
type AssocTy = ();
fn scope() {
let (): Self::AssocTy; //~ ERROR associated type `AssocTy` not found for `Type<()>` in the current scope
// ^^^^^^^^^^^^^ Ideally, this would resolve to the *trait* associated type
// `<Self as Trait>::AssocTy` (via resolve_type_relative_path/SelfTyAlias)
// given the fact that the IAT candidate is *inapplicable*!
}
}
fn main() { <Type<()> as Trait>::scope(); }
Inherent Associated Functions & Constants
When resolving associated functions and constants (in bodies), inapplicable inherent candidates do not shadow trait candidates, so the following cases pass compilation as expected and exit with 0 when executed.
Example | IAC&IAF inapplicable (unsatisfied predicate)
//@ run-pass
struct Type;
trait Trait {
const C: i32; fn f() -> i32;
fn scope();
}
impl Type // *inapplicable* impl candidate
where
for<'_delay> String: Copy,
{
const C: i32 = 0; fn f() -> i32 { 0 }
}
impl Trait for Type {
const C: i32 = 1; fn f() -> i32 { 1 }
fn scope() {
assert_eq!((Self::C, Self::f()), (1, 1)); // OK!
}
}
fn main() { <Type as Trait>::scope(); }
Example | IAC&IAF inapplicable (ununifiable self ty)
//@ run-pass
struct Type<T>(T);
trait Trait { const C: i32; fn f() -> i32; fn scope(); }
impl Type<u128> { // *inapplicable* impl candidate
const C: i32 = 0; fn f() -> i32 { 0 }
}
impl Trait for Type<()> {
const C: i32 = 1; fn f() -> i32 { 1 }
fn scope() {
assert_eq!((Self::C, Self::f()), (1, 1)); // OK!
}
}
fn main() { <Type<()> as Trait>::scope(); }
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by comparing inherent associated type selection with the associated function and constant behavior described in the issue. Trace resolve_type_relative_path and SelfTyAlias, then use the provided IAT examples to verify that an inapplicable inherent candidate allows the trait associated type candidate to resolve.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100