Skip to content

Commit 894d6a2

Browse files
committed
Auto merge of rust-lang#12832 - lowr:fix/impl-default-members-no-codegen, r=Veykril
fix: don't replace default members' body cc rust-lang#12779, rust-lang#12821 addresses rust-lang/rust-analyzer#12821 (comment) `gen_trait_fn_body()` only attempts to implement required trait member functions, so we shouldn't call it for `Implement default members` assist. This patch also documents the precondition of `gen_trait_fn_body()` and inserts `debug_assert!`, but I'm not entirely sure if the assertions are appropriate.
2 parents 977e12a + 7e0bd37 commit 894d6a2

File tree

2 files changed

+16
-12
lines changed

2 files changed

+16
-12
lines changed

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

+10-7
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,16 @@ fn add_missing_impl_members_inner(
145145
Some(cap) => {
146146
let mut cursor = Cursor::Before(first_new_item.syntax());
147147
let placeholder;
148-
if let ast::AssocItem::Fn(func) = &first_new_item {
149-
if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
150-
if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
151-
{
152-
if m.syntax().text() == "todo!()" {
153-
placeholder = m;
154-
cursor = Cursor::Replace(placeholder.syntax());
148+
if let DefaultMethods::No = mode {
149+
if let ast::AssocItem::Fn(func) = &first_new_item {
150+
if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
151+
if let Some(m) =
152+
func.syntax().descendants().find_map(ast::MacroCall::cast)
153+
{
154+
if m.syntax().text() == "todo!()" {
155+
placeholder = m;
156+
cursor = Cursor::Replace(placeholder.syntax());
157+
}
155158
}
156159
}
157160
}

crates/ide-assists/src/utils/gen_trait_fn_body.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use syntax::{
55
ted,
66
};
77

8-
/// Generate custom trait bodies where possible.
8+
/// Generate custom trait bodies without default implementation where possible.
99
///
1010
/// Returns `Option` so that we can use `?` rather than `if let Some`. Returning
1111
/// `None` means that generating a custom trait body failed, and the body will remain
@@ -28,6 +28,7 @@ pub(crate) fn gen_trait_fn_body(
2828

2929
/// Generate a `Clone` impl based on the fields and members of the target type.
3030
fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
31+
debug_assert!(func.name().map_or(false, |name| name.text() == "clone"));
3132
fn gen_clone_call(target: ast::Expr) -> ast::Expr {
3233
let method = make::name_ref("clone");
3334
make::expr_method_call(target, method, make::arg_list(None))
@@ -339,6 +340,7 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
339340

340341
/// Generate a `Hash` impl based on the fields and members of the target type.
341342
fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
343+
debug_assert!(func.name().map_or(false, |name| name.text() == "hash"));
342344
fn gen_hash_call(target: ast::Expr) -> ast::Stmt {
343345
let method = make::name_ref("hash");
344346
let arg = make::expr_path(make::ext::ident_path("state"));
@@ -394,9 +396,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
394396

395397
/// Generate a `PartialEq` impl based on the fields and members of the target type.
396398
fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
397-
if func.name().map_or(false, |name| name.text() == "ne") {
398-
return None;
399-
}
399+
debug_assert!(func.name().map_or(false, |name| name.text() == "eq"));
400400
fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> {
401401
match expr {
402402
Some(expr) => Some(make::expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)),
@@ -573,6 +573,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
573573
}
574574

575575
fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
576+
debug_assert!(func.name().map_or(false, |name| name.text() == "partial_cmp"));
576577
fn gen_partial_eq_match(match_target: ast::Expr) -> Option<ast::Stmt> {
577578
let mut arms = vec![];
578579

@@ -643,7 +644,7 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
643644
make::block_expr(stmts.into_iter(), tail).indent(ast::edit::IndentLevel(1))
644645
}
645646

646-
// No fields in the body means there's nothing to hash.
647+
// No fields in the body means there's nothing to compare.
647648
None => {
648649
let expr = make::expr_literal("true").into();
649650
make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1))

0 commit comments

Comments
 (0)