mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-28 05:53:45 +00:00
fix: Panic in path transform with default type parameters
This commit is contained in:
parent
fbed308ebe
commit
0241116462
2 changed files with 46 additions and 5 deletions
|
@ -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!()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use itertools::Itertools;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, make, AstNode, HasGenericArgs},
|
ast::{self, make, AstNode, HasGenericArgs},
|
||||||
ted, SyntaxNode,
|
ted, NodeOrToken, SyntaxNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -328,10 +328,26 @@ impl Ctx<'_> {
|
||||||
let qualified = make::path_from_segments(std::iter::once(segment), false);
|
let qualified = make::path_from_segments(std::iter::once(segment), false);
|
||||||
ted::replace(path.syntax(), qualified.clone_for_update().syntax());
|
ted::replace(path.syntax(), qualified.clone_for_update().syntax());
|
||||||
} else if let Some(path_ty) = ast::PathType::cast(parent) {
|
} else if let Some(path_ty) = ast::PathType::cast(parent) {
|
||||||
ted::replace(
|
let old = path_ty.syntax();
|
||||||
path_ty.syntax(),
|
|
||||||
subst.clone_subtree().clone_for_update().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 {
|
} else {
|
||||||
ted::replace(
|
ted::replace(
|
||||||
path.syntax(),
|
path.syntax(),
|
||||||
|
|
Loading…
Reference in a new issue