Skip to content

Commit 4545f28

Browse files
committed
Handle type args
1 parent 5cb1f71 commit 4545f28

File tree

2 files changed

+19
-9
lines changed

2 files changed

+19
-9
lines changed

crates/ra_assists/src/assists/add_missing_impl_members.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,13 @@ fn add_missing_impl_members_inner(
156156
.collect();
157157
let items = missing_items
158158
.into_iter()
159+
.map(|it| {
160+
substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param)
161+
})
159162
.map(|it| match module {
160163
Some(module) => qualify_paths(db, hir::InFile::new(file_id.into(), it), module),
161164
None => it,
162165
})
163-
.map(|it| {
164-
substitute_type_params(db, hir::InFile::new(file_id.into(), it), &substs_by_param)
165-
})
166166
.map(|it| match it {
167167
ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)),
168168
_ => it,
@@ -239,11 +239,9 @@ fn substitute_type_params<N: AstNode>(
239239

240240
use hir::PathResolution;
241241

242-
// TODO handle generic args
243-
// TODO handle associated item paths
244-
// TODO handle value ns?
245-
246242
// FIXME extract this to a general utility as well
243+
// FIXME handle value ns?
244+
// FIXME this doesn't 'commute' with `substitute_type_params`, since type params in newly generated type arg lists don't resolve. Currently we can avoid this problem, but it's worth thinking about a solution
247245
fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from: hir::Module) -> N {
248246
let path_replacements = node
249247
.value
@@ -255,12 +253,17 @@ fn qualify_paths<N: AstNode>(db: &impl HirDatabase, node: hir::InFile<N>, from:
255253
// don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
256254
return None;
257255
}
256+
// FIXME check if some ancestor is already being replaced, if so skip this
258257
let analyzer = hir::SourceAnalyzer::new(db, node.with_value(p.syntax()), None);
259258
let resolution = analyzer.resolve_path(db, &p)?;
260259
match resolution {
261260
PathResolution::Def(def) => {
262261
let found_path = from.find_path(db, def)?;
263-
Some((p, found_path.to_ast()))
262+
let args = p
263+
.segment()
264+
.and_then(|s| s.type_arg_list())
265+
.map(|arg_list| qualify_paths(db, node.with_value(arg_list), from));
266+
Some((p, make::path_with_type_arg_list(found_path.to_ast(), args)))
264267
}
265268
PathResolution::Local(_)
266269
| PathResolution::TypeParam(_)
@@ -535,7 +538,7 @@ impl foo::Foo for S { <|> }",
535538
"
536539
mod foo {
537540
pub struct Bar<T>;
538-
impl Bar { type Assoc = u32; }
541+
impl Bar<T> { type Assoc = u32; }
539542
trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
540543
}
541544
struct S;

crates/ra_syntax/src/ast/make.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ pub fn path_qualified(qual: ast::Path, name_ref: ast::NameRef) -> ast::Path {
2121
fn path_from_text(text: &str) -> ast::Path {
2222
ast_from_text(text)
2323
}
24+
pub fn path_with_type_arg_list(path: ast::Path, args: Option<ast::TypeArgList>) -> ast::Path {
25+
if let Some(args) = args {
26+
ast_from_text(&format!("const X: {}{}", path.syntax(), args.syntax()))
27+
} else {
28+
path
29+
}
30+
}
2431

2532
pub fn record_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordField {
2633
return match expr {

0 commit comments

Comments
 (0)