Rollup merge of #126295 - linyihai:uninitalized-in-match-arm, r=pnkfelix

No uninitalized report in a pre-returned match arm

This is a attemp to address https://github.com/rust-lang/rust/issues/126133
This commit is contained in:
Guillaume Gomez 2024-06-12 15:45:01 +02:00 committed by GitHub
commit 876ef7f021
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 4 deletions

View File

@ -557,8 +557,8 @@ fn report_use_of_uninitialized(
// for the branching codepaths that aren't covered, to point at them.
let map = self.infcx.tcx.hir();
let body = map.body_owned_by(self.mir_def_id());
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
let mut visitor =
ConditionVisitor { tcx: self.infcx.tcx, spans: &spans, name: &name, errors: vec![] };
visitor.visit_body(&body);
let mut show_assign_sugg = false;
@ -4372,13 +4372,14 @@ fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
/// Given a set of spans representing statements initializing the relevant binding, visit all the
/// function expressions looking for branching code paths that *do not* initialize the binding.
struct ConditionVisitor<'b> {
struct ConditionVisitor<'b, 'tcx> {
tcx: TyCtxt<'tcx>,
spans: &'b [Span],
name: &'b str,
errors: Vec<(Span, String)>,
}
impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
impl<'b, 'v, 'tcx> Visitor<'v> for ConditionVisitor<'b, 'tcx> {
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
match ex.kind {
hir::ExprKind::If(cond, body, None) => {
@ -4464,6 +4465,12 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
),
));
} else if let Some(guard) = &arm.guard {
if matches!(
self.tcx.hir_node(arm.body.hir_id),
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
) {
continue;
}
self.errors.push((
arm.pat.span.to(guard.span),
format!(
@ -4473,6 +4480,12 @@ fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
),
));
} else {
if matches!(
self.tcx.hir_node(arm.body.hir_id),
hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Ret(_), .. })
) {
continue;
}
self.errors.push((
arm.pat.span,
format!(

View File

@ -0,0 +1,22 @@
enum E {
A,
B,
C,
}
fn foo(e: E) {
let bar;
match e {
E::A if true => return,
E::A => return,
E::B => {}
E::C => {
bar = 5;
}
}
let _baz = bar; //~ ERROR E0381
}
fn main() {}

View File

@ -0,0 +1,15 @@
error[E0381]: used binding `bar` is possibly-uninitialized
--> $DIR/uninitalized-in-match-arm-issue-126133.rs:19:16
|
LL | let bar;
| --- binding declared here but left uninitialized
...
LL | E::B => {}
| ---- if this pattern is matched, `bar` is not initialized
...
LL | let _baz = bar;
| ^^^ `bar` used here but it is possibly-uninitialized
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0381`.