about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-02-08 05:44:15 -0800
committerEsteban Küber <esteban@kuber.com.ar>2019-02-08 06:37:29 -0800
commit802c897eb3c95e6643bd4e2cd85052786458e3d8 (patch)
treead478fe0cbcb25fa8ec6be0cf7da2b995a101ffc
parent7eb6a2a9729dd0f948fc30e391e32c0a51d3d0a7 (diff)
downloadrust-802c897eb3c95e6643bd4e2cd85052786458e3d8.tar.gz
rust-802c897eb3c95e6643bd4e2cd85052786458e3d8.zip
review comments: (marginally) reduce memory consumtion
-rw-r--r--src/librustc/infer/error_reporting/mod.rs14
-rw-r--r--src/librustc/traits/mod.rs3
-rw-r--r--src/librustc/traits/structural_impls.rs13
-rw-r--r--src/librustc_typeck/check/_match.rs8
-rw-r--r--src/test/ui/match/match-type-err-first-arm.rs18
-rw-r--r--src/test/ui/match/match-type-err-first-arm.stderr24
6 files changed, 68 insertions, 12 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 361aee4405b..82e9a1e3c89 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -512,6 +512,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             ObligationCauseCode::MatchExpressionArm {
                 source,
                 ref prior_arms,
+                last_ty,
                 ..
             } => match source {
                 hir::MatchSource::IfLetDesugar { .. } => {
@@ -522,13 +523,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 _ => {
                     let msg = "`match` arms have incompatible types";
                     err.span_label(cause.span, msg);
-                    if prior_arms.len() < 4 {
-                        for (sp, ty) in prior_arms {
-                            err.span_label(*sp, format!("this is found to be of type `{}`", ty));
+                    if prior_arms.len() <= 4 {
+                        for sp in prior_arms {
+                            err.span_label(*sp, format!(
+                                "this is found to be of type `{}`",
+                                last_ty,
+                            ));
                         }
-                    } else if let Some((sp, ty)) = prior_arms.last() {
+                    } else if let Some(sp) = prior_arms.last() {
                         err.span_label(*sp, format!(
-                            "this and all prior arms are found to be of type `{}`", ty,
+                            "this and all prior arms are found to be of type `{}`", last_ty,
                         ));
                     }
                 }
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 9824ff8f397..7fc27ba735e 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -224,7 +224,8 @@ pub enum ObligationCauseCode<'tcx> {
     MatchExpressionArm {
         arm_span: Span,
         source: hir::MatchSource,
-        prior_arms: Vec<(Span, Ty<'tcx>)>,
+        prior_arms: Vec<Span>,
+        last_ty: Ty<'tcx>,
     },
 
     /// Computing common supertype in the pattern guard for the arms of a match expression
diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs
index c0e00cf291b..8bbeec0b8ac 100644
--- a/src/librustc/traits/structural_impls.rs
+++ b/src/librustc/traits/structural_impls.rs
@@ -517,11 +517,16 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
                 arm_span,
                 source,
                 ref prior_arms,
+                last_ty,
             } => {
-                let prior_arms = prior_arms.iter().filter_map(|(sp, ty)| {
-                    tcx.lift(ty).map(|ty| (*sp, ty))
-                }).collect();
-                Some(super::MatchExpressionArm { arm_span, source, prior_arms })
+                tcx.lift(&last_ty).map(|last_ty| {
+                    super::MatchExpressionArm {
+                        arm_span,
+                        source,
+                        prior_arms: prior_arms.clone(),
+                        last_ty,
+                    }
+                })
             }
             super::MatchExpressionArmPattern { span, ty } => {
                 tcx.lift(&ty).map(|ty| super::MatchExpressionArmPattern { span, ty })
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index c662a49abf9..cfc7cedc5e3 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -690,6 +690,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
         };
 
         let mut other_arms = vec![];  // used only for diagnostics
+        let mut prior_arm_ty = None;
         for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
             if let Some(ref g) = arm.guard {
                 self.diverges.set(pats_diverge);
@@ -730,11 +731,16 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
                         arm_span,
                         source: match_src,
                         prior_arms: other_arms.clone(),
+                        last_ty: prior_arm_ty.unwrap(),
                     })
                 };
                 coercion.coerce(self, &cause, &arm.body, arm_ty);
             }
-            other_arms.push((arm_span, arm_ty));
+            other_arms.push(arm_span);
+            if other_arms.len() > 5 {
+                other_arms.remove(0);
+            }
+            prior_arm_ty = Some(arm_ty);
         }
 
         // We won't diverge unless the discriminant or all arms diverge.
diff --git a/src/test/ui/match/match-type-err-first-arm.rs b/src/test/ui/match/match-type-err-first-arm.rs
index 31fa50d2b45..b4b84ef8f1c 100644
--- a/src/test/ui/match/match-type-err-first-arm.rs
+++ b/src/test/ui/match/match-type-err-first-arm.rs
@@ -25,3 +25,21 @@ fn test_func2(n: i32) -> i32 {
     };
     x
 }
+
+fn test_func3(n: i32) -> i32 {
+    let x = match n {
+    //~^ NOTE `match` arms have incompatible types
+        1 => 'b',
+        2 => 'b',
+        3 => 'b',
+        4 => 'b',
+        5 => 'b',
+        6 => 'b',
+        //~^ NOTE this and all prior arms are found to be of type `char`
+        _ => 42,
+        //~^ ERROR match arms have incompatible types
+        //~| NOTE expected char, found integer
+        //~| NOTE expected type `char`
+    };
+    x
+}
diff --git a/src/test/ui/match/match-type-err-first-arm.stderr b/src/test/ui/match/match-type-err-first-arm.stderr
index 8f722343a58..db8bef8dc77 100644
--- a/src/test/ui/match/match-type-err-first-arm.stderr
+++ b/src/test/ui/match/match-type-err-first-arm.stderr
@@ -26,6 +26,28 @@ LL | |     };
    = note: expected type `char`
               found type `{integer}`
 
-error: aborting due to 2 previous errors
+error[E0308]: match arms have incompatible types
+  --> $DIR/match-type-err-first-arm.rs:39:14
+   |
+LL |       let x = match n {
+   |  _____________-
+LL | |     //~^ NOTE `match` arms have incompatible types
+LL | |         1 => 'b',
+LL | |         2 => 'b',
+...  |
+LL | |         6 => 'b',
+   | |              --- this and all prior arms are found to be of type `char`
+LL | |         //~^ NOTE this and all prior arms are found to be of type `char`
+LL | |         _ => 42,
+   | |              ^^ expected char, found integer
+...  |
+LL | |         //~| NOTE expected type `char`
+LL | |     };
+   | |_____- `match` arms have incompatible types
+   |
+   = note: expected type `char`
+              found type `{integer}`
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.