Skip to content

Commit 672e3f4

Browse files
committed
fix #102087, Suggest Default::default() when binding isn't initialized
1 parent 11bb80a commit 672e3f4

38 files changed

+514
-0
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+70
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
369369
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
370370
visitor.visit_body(&body);
371371

372+
let mut show_assign_sugg = false;
372373
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
373374
| InitializationRequiringAction::Assignment = desired_action
374375
{
@@ -396,6 +397,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
396397
.count()
397398
== 0
398399
{
400+
show_assign_sugg = true;
399401
"isn't initialized"
400402
} else {
401403
"is possibly-uninitialized"
@@ -446,10 +448,78 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
446448
}
447449
}
448450
}
451+
449452
err.span_label(decl_span, "binding declared here but left uninitialized");
453+
if show_assign_sugg {
454+
struct LetVisitor {
455+
decl_span: Span,
456+
sugg_span: Option<Span>,
457+
}
458+
459+
impl<'v> Visitor<'v> for LetVisitor {
460+
fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
461+
if self.sugg_span.is_some() {
462+
return;
463+
}
464+
if let hir::StmtKind::Local(hir::Local {
465+
span, ty, init: None, ..
466+
}) = &ex.kind && span.contains(self.decl_span) {
467+
self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span));
468+
}
469+
hir::intravisit::walk_stmt(self, ex);
470+
}
471+
}
472+
473+
let mut visitor = LetVisitor { decl_span, sugg_span: None };
474+
visitor.visit_body(&body);
475+
if let Some(span) = visitor.sugg_span {
476+
self.suggest_assign_value(&mut err, moved_place, span);
477+
}
478+
}
450479
err
451480
}
452481

482+
fn suggest_assign_value(
483+
&self,
484+
err: &mut Diagnostic,
485+
moved_place: PlaceRef<'tcx>,
486+
sugg_span: Span,
487+
) {
488+
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
489+
debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
490+
491+
let tcx = self.infcx.tcx;
492+
let implements_default = |ty, param_env| {
493+
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
494+
return false;
495+
};
496+
tcx.infer_ctxt().enter(|infcx| {
497+
infcx
498+
.type_implements_trait(default_trait, ty, ty::List::empty(), param_env)
499+
.may_apply()
500+
})
501+
};
502+
503+
let assign_value = match ty.kind() {
504+
ty::Bool => "false",
505+
ty::Float(_) => "0.0",
506+
ty::Int(_) | ty::Uint(_) => "0",
507+
ty::Never | ty::Error(_) => "",
508+
ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]",
509+
ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()",
510+
_ => "todo!()",
511+
};
512+
513+
if !assign_value.is_empty() {
514+
err.span_suggestion_verbose(
515+
sugg_span.shrink_to_hi(),
516+
format!("consider assigning a value"),
517+
format!(" = {}", assign_value),
518+
Applicability::MaybeIncorrect,
519+
);
520+
}
521+
}
522+
453523
fn suggest_borrow_fn_like(
454524
&self,
455525
err: &mut Diagnostic,

src/test/ui/asm/aarch64/type-check-2-2.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let x: u64;
55
| - binding declared here but left uninitialized
66
LL | asm!("{}", in(reg) x);
77
| ^ `x` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let x: u64 = 0;
12+
| +++
813

914
error[E0381]: used binding `y` isn't initialized
1015
--> $DIR/type-check-2-2.rs:22:9
@@ -13,6 +18,11 @@ LL | let mut y: u64;
1318
| ----- binding declared here but left uninitialized
1419
LL | asm!("{}", inout(reg) y);
1520
| ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized
21+
|
22+
help: consider assigning a value
23+
|
24+
LL | let mut y: u64 = 0;
25+
| +++
1626

1727
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
1828
--> $DIR/type-check-2-2.rs:30:29

src/test/ui/asm/x86_64/type-check-5.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let x: u64;
55
| - binding declared here but left uninitialized
66
LL | asm!("{}", in(reg) x);
77
| ^ `x` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let x: u64 = 0;
12+
| +++
813

914
error[E0381]: used binding `y` isn't initialized
1015
--> $DIR/type-check-5.rs:18:9
@@ -13,6 +18,11 @@ LL | let mut y: u64;
1318
| ----- binding declared here but left uninitialized
1419
LL | asm!("{}", inout(reg) y);
1520
| ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized
21+
|
22+
help: consider assigning a value
23+
|
24+
LL | let mut y: u64 = 0;
25+
| +++
1626

1727
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
1828
--> $DIR/type-check-5.rs:26:29

src/test/ui/borrowck/borrowck-block-unint.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ LL | force(|| {
77
| ^^ `x` used here but it isn't initialized
88
LL | println!("{}", x);
99
| - borrow occurs due to use in closure
10+
|
11+
help: consider assigning a value
12+
|
13+
LL | let x: isize = 0;
14+
| +++
1015

1116
error: aborting due to previous error
1217

src/test/ui/borrowck/borrowck-break-uninit-2.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | println!("{}", x);
88
| ^ `x` used here but it isn't initialized
99
|
1010
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider assigning a value
12+
|
13+
LL | let x: isize = 0;
14+
| +++
1115

1216
error: aborting due to previous error
1317

src/test/ui/borrowck/borrowck-break-uninit.stderr

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ LL | println!("{}", x);
88
| ^ `x` used here but it isn't initialized
99
|
1010
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider assigning a value
12+
|
13+
LL | let x: isize = 0;
14+
| +++
1115

1216
error: aborting due to previous error
1317

src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let i: isize;
55
| - binding declared here but left uninitialized
66
LL | i
77
| ^ `i` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let i: isize = 0;
12+
| +++
813

914
error: aborting due to previous error
1015

src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let i: isize;
55
| - binding declared here but left uninitialized
66
LL | i
77
| ^ `i` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let i: isize = 0;
12+
| +++
813

914
error: aborting due to previous error
1015

src/test/ui/borrowck/borrowck-init-in-fru.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let mut origin: Point;
55
| ---------- binding declared here but left uninitialized
66
LL | origin = Point { x: 10, ..origin };
77
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `origin.y` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let mut origin: Point = todo!();
12+
| +++++++++
813

914
error: aborting due to previous error
1015

src/test/ui/borrowck/borrowck-init-op-equal.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let v: isize;
55
| - binding declared here but left uninitialized
66
LL | v += 1;
77
| ^^^^^^ `v` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let v: isize = 0;
12+
| +++
813

914
error: aborting due to previous error
1015

src/test/ui/borrowck/borrowck-init-plus-equal.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let mut v: isize;
55
| ----- binding declared here but left uninitialized
66
LL | v = v + 1;
77
| ^ `v` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let mut v: isize = 0;
12+
| +++
813

914
error: aborting due to previous error
1015

src/test/ui/borrowck/borrowck-return.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let x: isize;
55
| - binding declared here but left uninitialized
66
LL | return x;
77
| ^ `x` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let x: isize = 0;
12+
| +++
813

914
error: aborting due to previous error
1015

src/test/ui/borrowck/borrowck-storage-dead.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let x: i32;
55
| - binding declared here but left uninitialized
66
LL | let _ = x + 1;
77
| ^ `x` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let x: i32 = 0;
12+
| +++
813

914
error: aborting due to previous error
1015

src/test/ui/borrowck/borrowck-uninit-after-item.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ LL | let bar;
66
LL | fn baz(_x: isize) { }
77
LL | baz(bar);
88
| ^^^ `bar` used here but it isn't initialized
9+
|
10+
help: consider assigning a value
11+
|
12+
LL | let bar = 0;
13+
| +++
914

1015
error: aborting due to previous error
1116

src/test/ui/borrowck/borrowck-uninit-field-access.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | let mut a: Point;
55
| ----- binding declared here but left uninitialized
66
LL | let _ = a.x + 1;
77
| ^^^ `a.x` used here but it isn't initialized
8+
|
9+
help: consider assigning a value
10+
|
11+
LL | let mut a: Point = Default::default();
12+
| ++++++++++++++++++++
813

914
error[E0382]: use of moved value: `line1.origin`
1015
--> $DIR/borrowck-uninit-field-access.rs:25:13

0 commit comments

Comments
 (0)