Skip to content

Commit

Permalink
Auto merge of rust-lang#17805 - ShoyuVanilla:issue-17578, r=Veykril
Browse files Browse the repository at this point in the history
fix: Panic in path transform with default type parameters

Fixes rust-lang#17578
  • Loading branch information
bors committed Aug 6, 2024
2 parents 37f7569 + ad4e815 commit 54362ca
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2280,4 +2280,29 @@ impl b::LocalTrait for B {
"#,
)
}

#[test]
fn impl_with_type_param_with_former_param_as_default() {
check_assist(
add_missing_impl_members,
r#"
pub trait Test<'a, T, U = T> {
fn test(item: &'a T) -> U;
}
impl<'a> Test<'a, i32> for bool {
$0
}
"#,
r#"
pub trait Test<'a, T, U = T> {
fn test(item: &'a T) -> U;
}
impl<'a> Test<'a, i32> for bool {
fn test(item: &'a i32) -> i32 {
${0:todo!()}
}
}
"#,
);
}
}
26 changes: 21 additions & 5 deletions src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use itertools::Itertools;
use rustc_hash::FxHashMap;
use syntax::{
ast::{self, make, AstNode, HasGenericArgs},
ted, SyntaxNode,
ted, NodeOrToken, SyntaxNode,
};

#[derive(Default)]
Expand Down Expand Up @@ -328,10 +328,26 @@ impl Ctx<'_> {
let qualified = make::path_from_segments(std::iter::once(segment), false);
ted::replace(path.syntax(), qualified.clone_for_update().syntax());
} else if let Some(path_ty) = ast::PathType::cast(parent) {
ted::replace(
path_ty.syntax(),
subst.clone_subtree().clone_for_update().syntax(),
);
let old = path_ty.syntax();

if old.parent().is_some() {
ted::replace(old, subst.clone_subtree().clone_for_update().syntax());
} else {
// Some `path_ty` has no parent, especially ones made for default value
// of type parameters.
// In this case, `ted` cannot replace `path_ty` with `subst` directly.
// So, just replace its children as long as the `subst` is the same type.
let new = subst.clone_subtree().clone_for_update();
if !matches!(new, ast::Type::PathType(..)) {
return None;
}
let start = path_ty.syntax().first_child().map(NodeOrToken::Node)?;
let end = path_ty.syntax().last_child().map(NodeOrToken::Node)?;
ted::replace_all(
start..=end,
new.syntax().children().map(NodeOrToken::Node).collect::<Vec<_>>(),
);
}
} else {
ted::replace(
path.syntax(),
Expand Down

0 comments on commit 54362ca

Please sign in to comment.