Skip to content

Commit 5fe545c

Browse files
committed
Auto merge of #17805 - ShoyuVanilla:issue-17578, r=Veykril
fix: Panic in path transform with default type parameters Fixes #17578
2 parents 4a99d79 + 0241116 commit 5fe545c

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

crates/ide-assists/src/handlers/add_missing_impl_members.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2280,4 +2280,29 @@ impl b::LocalTrait for B {
22802280
"#,
22812281
)
22822282
}
2283+
2284+
#[test]
2285+
fn impl_with_type_param_with_former_param_as_default() {
2286+
check_assist(
2287+
add_missing_impl_members,
2288+
r#"
2289+
pub trait Test<'a, T, U = T> {
2290+
fn test(item: &'a T) -> U;
2291+
}
2292+
impl<'a> Test<'a, i32> for bool {
2293+
$0
2294+
}
2295+
"#,
2296+
r#"
2297+
pub trait Test<'a, T, U = T> {
2298+
fn test(item: &'a T) -> U;
2299+
}
2300+
impl<'a> Test<'a, i32> for bool {
2301+
fn test(item: &'a i32) -> i32 {
2302+
${0:todo!()}
2303+
}
2304+
}
2305+
"#,
2306+
);
2307+
}
22832308
}

crates/ide-db/src/path_transform.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use itertools::Itertools;
77
use rustc_hash::FxHashMap;
88
use syntax::{
99
ast::{self, make, AstNode, HasGenericArgs},
10-
ted, SyntaxNode,
10+
ted, NodeOrToken, SyntaxNode,
1111
};
1212

1313
#[derive(Default)]
@@ -328,10 +328,26 @@ impl Ctx<'_> {
328328
let qualified = make::path_from_segments(std::iter::once(segment), false);
329329
ted::replace(path.syntax(), qualified.clone_for_update().syntax());
330330
} else if let Some(path_ty) = ast::PathType::cast(parent) {
331-
ted::replace(
332-
path_ty.syntax(),
333-
subst.clone_subtree().clone_for_update().syntax(),
334-
);
331+
let old = path_ty.syntax();
332+
333+
if old.parent().is_some() {
334+
ted::replace(old, subst.clone_subtree().clone_for_update().syntax());
335+
} else {
336+
// Some `path_ty` has no parent, especially ones made for default value
337+
// of type parameters.
338+
// In this case, `ted` cannot replace `path_ty` with `subst` directly.
339+
// So, just replace its children as long as the `subst` is the same type.
340+
let new = subst.clone_subtree().clone_for_update();
341+
if !matches!(new, ast::Type::PathType(..)) {
342+
return None;
343+
}
344+
let start = path_ty.syntax().first_child().map(NodeOrToken::Node)?;
345+
let end = path_ty.syntax().last_child().map(NodeOrToken::Node)?;
346+
ted::replace_all(
347+
start..=end,
348+
new.syntax().children().map(NodeOrToken::Node).collect::<Vec<_>>(),
349+
);
350+
}
335351
} else {
336352
ted::replace(
337353
path.syntax(),

0 commit comments

Comments
 (0)