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(); }
Metadata
Metadata
Assignees
Labels
Type
Projects
Status