Fix generic type substitution in impl trait with assoc const
This commit is contained in:
parent
d9b3242bcd
commit
a710b87b1b
@ -1245,6 +1245,62 @@ impl Behavior<u32> for Impl {
|
|||||||
fn reproduce(&self, foo: <u32 as bar::Types2>::Bar) {
|
fn reproduce(&self, foo: <u32 as bar::Types2>::Bar) {
|
||||||
${0:todo!()}
|
${0:todo!()}
|
||||||
}
|
}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_transform_path_in_path_expr() {
|
||||||
|
check_assist(
|
||||||
|
add_missing_default_members,
|
||||||
|
r#"
|
||||||
|
pub trait Const {
|
||||||
|
const FOO: u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Trait<T: Const> {
|
||||||
|
fn foo() -> bool {
|
||||||
|
match T::FOO {
|
||||||
|
0 => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Const for u32 {
|
||||||
|
const FOO: u32 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Impl;
|
||||||
|
|
||||||
|
impl Trait<u32> for Impl { $0 }"#,
|
||||||
|
r#"
|
||||||
|
pub trait Const {
|
||||||
|
const FOO: u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Trait<T: Const> {
|
||||||
|
fn foo() -> bool {
|
||||||
|
match T::FOO {
|
||||||
|
0 => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Const for u32 {
|
||||||
|
const FOO: u32 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Impl;
|
||||||
|
|
||||||
|
impl Trait<u32> for Impl {
|
||||||
|
$0fn foo() -> bool {
|
||||||
|
match <u32 as Const>::FOO {
|
||||||
|
0 => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
}"#,
|
}"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -154,14 +154,14 @@ impl<'a> Ctx<'a> {
|
|||||||
let parent = path.syntax().parent()?;
|
let parent = path.syntax().parent()?;
|
||||||
if let Some(parent) = ast::Path::cast(parent.clone()) {
|
if let Some(parent) = ast::Path::cast(parent.clone()) {
|
||||||
// Path inside path means that there is an associated
|
// Path inside path means that there is an associated
|
||||||
// type on the type parameter. It is necessary to fully
|
// type/constant on the type parameter. It is necessary
|
||||||
// qualify the type with `as Trait`. Even though it
|
// to fully qualify the type with `as Trait`. Even
|
||||||
// might be unnecessary if `subst` is generic type,
|
// though it might be unnecessary if `subst` is generic
|
||||||
// always fully qualifying the path is safer because of
|
// type, always fully qualifying the path is safer
|
||||||
// potential clash of associated types from multiple
|
// because of potential clash of associated types from
|
||||||
// traits
|
// multiple traits
|
||||||
|
|
||||||
let trait_ref = find_trait_for_assoc_type(
|
let trait_ref = find_trait_for_assoc_item(
|
||||||
self.source_scope,
|
self.source_scope,
|
||||||
tp,
|
tp,
|
||||||
parent.segment()?.name_ref()?,
|
parent.segment()?.name_ref()?,
|
||||||
@ -252,24 +252,25 @@ fn get_type_args_from_arg_list(generic_arg_list: ast::GenericArgList) -> Option<
|
|||||||
Some(result)
|
Some(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_trait_for_assoc_type(
|
fn find_trait_for_assoc_item(
|
||||||
scope: &SemanticsScope,
|
scope: &SemanticsScope,
|
||||||
type_param: hir::TypeParam,
|
type_param: hir::TypeParam,
|
||||||
assoc_type: ast::NameRef,
|
assoc_item: ast::NameRef,
|
||||||
) -> Option<hir::Trait> {
|
) -> Option<hir::Trait> {
|
||||||
let db = scope.db;
|
let db = scope.db;
|
||||||
let trait_bounds = type_param.trait_bounds(db);
|
let trait_bounds = type_param.trait_bounds(db);
|
||||||
|
|
||||||
let assoc_type_name = assoc_type.text();
|
let assoc_item_name = assoc_item.text();
|
||||||
|
|
||||||
for trait_ in trait_bounds {
|
for trait_ in trait_bounds {
|
||||||
let type_aliases = trait_.items(db).into_iter().filter_map(|item| match item {
|
let names = trait_.items(db).into_iter().filter_map(|item| match item {
|
||||||
hir::AssocItem::TypeAlias(ta) => Some(ta),
|
hir::AssocItem::TypeAlias(ta) => Some(ta.name(db)),
|
||||||
|
hir::AssocItem::Const(cst) => cst.name(db),
|
||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
for type_alias in type_aliases {
|
for name in names {
|
||||||
if assoc_type_name.as_str() == type_alias.name(db).as_text()?.as_str() {
|
if assoc_item_name.as_str() == name.as_text()?.as_str() {
|
||||||
// It is fine to return the first match because in case of
|
// It is fine to return the first match because in case of
|
||||||
// multiple possibilities, the exact trait must be disambiguated
|
// multiple possibilities, the exact trait must be disambiguated
|
||||||
// in the definition of trait being implemented, so this search
|
// in the definition of trait being implemented, so this search
|
||||||
|
Loading…
x
Reference in New Issue
Block a user