@@ -21,6 +21,7 @@ use rustc_middle::ty::{
2121 self , subst:: Subst , suggest_constraining_type_params, EarlyBinder , PredicateKind , Ty ,
2222} ;
2323use rustc_mir_dataflow:: move_paths:: { InitKind , MoveOutIndex , MovePathIndex } ;
24+ use rustc_span:: hygiene:: DesugaringKind ;
2425use rustc_span:: symbol:: sym;
2526use rustc_span:: { BytePos , Span } ;
2627use rustc_trait_selection:: infer:: InferCtxtExt ;
@@ -331,7 +332,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
331332 spans. push ( span) ;
332333 }
333334
334- let ( item_msg , name, desc) =
335+ let ( binding , name, desc) =
335336 match self . describe_place_with_options ( used_place, IncludingDowncast ( true ) ) {
336337 Some ( name) => ( format ! ( "`{name}`" ) , format ! ( "`{name}`" ) , format ! ( "`{name}` " ) ) ,
337338 None => ( "value" . to_string ( ) , "the variable" . to_string ( ) , String :: new ( ) ) ,
@@ -351,20 +352,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
351352 } else {
352353 "initialized in all conditions"
353354 } ;
354- let mut err = struct_span_err ! ( self , span, E0381 , "binding {desc}isn't {initialized}" ) ;
355+ let used = desired_action. as_general_verb_in_past_tense ( ) ;
356+ let mut err =
357+ struct_span_err ! ( self , span, E0381 , "{used} binding {desc}isn't {initialized}" ) ;
355358 use_spans. var_span_label_path_only (
356359 & mut err,
357360 format ! ( "{} occurs due to use{}" , desired_action. as_noun( ) , use_spans. describe( ) ) ,
358361 ) ;
359362
360363 if let InitializationRequiringAction :: PartialAssignment = desired_action {
361364 err. help (
362- "partial initialization isn't supported, fully initialize the binding with \
363- a default value and mutate, or use `std::mem::MaybeUninit`",
365+ "partial initialization isn't supported, fully initialize the binding with a \
366+ default value and mutate it , or use `std::mem::MaybeUninit`",
364367 ) ;
365368 }
366- let verb = desired_action. as_verb_in_past_tense ( ) ;
367- err. span_label ( span, format ! ( "{item_msg} {verb} here but it isn't {initialized}" , ) ) ;
369+ err. span_label ( span, format ! ( "{binding} {used} here but it isn't {initialized}" ) ) ;
368370
369371 // We use the statements were the binding was initialized, and inspect the HIR to look
370372 // for the branching codepaths that aren't covered, to point at them.
@@ -400,7 +402,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
400402 err. span_label ( sp, & label) ;
401403 }
402404 }
403- err. span_label ( decl_span, "variable declared here" ) ;
405+ err. span_label ( decl_span, "binding declared here but left uninitialized " ) ;
404406 err
405407 }
406408
@@ -2559,10 +2561,10 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
25592561 v. visit_expr ( body) ;
25602562 if v. 1 {
25612563 self . errors . push ( (
2562- cond. span ,
2564+ ex . span . to ( cond. span ) ,
25632565 format ! (
2564- "this `if` expression might be missing an `else` arm where {} is \
2565- initialized ",
2566+ "this `if` expression might be missing an `else` arm that initializes \
2567+ {} ",
25662568 self . name,
25672569 ) ,
25682570 ) ) ;
@@ -2578,10 +2580,24 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
25782580 match ( a. 1 , b. 1 ) {
25792581 ( true , true ) | ( false , false ) => { }
25802582 ( true , false ) => {
2581- self . errors . push ( (
2582- cond. span ,
2583- format ! ( "{} is uninitialized if this condition isn't met" , self . name, ) ,
2584- ) ) ;
2583+ if other. span . is_desugaring ( DesugaringKind :: WhileLoop ) {
2584+ self . errors . push ( (
2585+ cond. span ,
2586+ format ! (
2587+ "{} is uninitialized if this condition isn't met and the \
2588+ `while` loop runs 0 times",
2589+ self . name
2590+ ) ,
2591+ ) ) ;
2592+ } else {
2593+ self . errors . push ( (
2594+ body. span . shrink_to_hi ( ) . until ( other. span ) ,
2595+ format ! (
2596+ "{} is uninitialized if this `else` arm is executed" ,
2597+ self . name
2598+ ) ,
2599+ ) ) ;
2600+ }
25852601 }
25862602 ( false , true ) => {
25872603 self . errors . push ( (
@@ -2591,7 +2607,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
25912607 }
25922608 }
25932609 }
2594- hir:: ExprKind :: Match ( _ , arms, _ ) => {
2610+ hir:: ExprKind :: Match ( e , arms, loop_desugar ) => {
25952611 // If the binding is initialized in one of the match arms, then the other match
25962612 // arms might be missing an initialization.
25972613 let results: Vec < bool > = arms
@@ -2605,22 +2621,40 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
26052621 if results. iter ( ) . any ( |x| * x) && !results. iter ( ) . all ( |x| * x) {
26062622 for ( arm, seen) in arms. iter ( ) . zip ( results) {
26072623 if !seen {
2608- self . errors . push ( (
2609- arm. pat . span ,
2610- format ! (
2611- "{} is uninitialized if this pattern is matched" ,
2612- self . name
2613- ) ,
2614- ) ) ;
2624+ if loop_desugar == hir:: MatchSource :: ForLoopDesugar {
2625+ self . errors . push ( (
2626+ e. span ,
2627+ format ! (
2628+ "{} is uninitialized if the `for` loop runs 0 times" ,
2629+ self . name
2630+ ) ,
2631+ ) ) ;
2632+ } else if let Some ( guard) = & arm. guard {
2633+ self . errors . push ( (
2634+ arm. pat . span . to ( guard. body ( ) . span ) ,
2635+ format ! (
2636+ "{} is uninitialized if this pattern and condition are \
2637+ matched",
2638+ self . name
2639+ ) ,
2640+ ) ) ;
2641+ } else {
2642+ self . errors . push ( (
2643+ arm. pat . span ,
2644+ format ! (
2645+ "{} is uninitialized if this pattern is matched" ,
2646+ self . name
2647+ ) ,
2648+ ) ) ;
2649+ }
26152650 }
26162651 }
26172652 }
26182653 }
26192654 // FIXME: should we also account for binops, particularly `&&` and `||`? `try` should
26202655 // also be accounted for. For now it is fine, as if we don't find *any* relevant
26212656 // branching code paths, we point at the places where the binding *is* initialized for
2622- // *some* context. We should also specialize the output for `while` and `for` loops,
2623- // but for now we can rely on their desugaring to provide appropriate output.
2657+ // *some* context.
26242658 _ => { }
26252659 }
26262660 walk_expr ( self , ex) ;
0 commit comments