about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-24 15:41:13 +0000
committerbors <bors@rust-lang.org>2017-09-24 15:41:13 +0000
commit1ed7d41d8849d930f0622eaf54049f66fff0ca2a (patch)
tree9c7a836c7396376c382ed8aa8c672114b8a65c78
parent647aecc281f0defdd96bc807f2b98ec3090857a2 (diff)
parentb6bce56ac718a6343e44b37110e6c273ab9b6189 (diff)
downloadrust-1ed7d41d8849d930f0622eaf54049f66fff0ca2a.tar.gz
rust-1ed7d41d8849d930f0622eaf54049f66fff0ca2a.zip
Auto merge of #44743 - arielb1:size-rollback, r=eddyb
typeck::check::coercion - roll back failed unsizing type vars

This wraps unsizing coercions within an additional level of
`commit_if_ok`, which rolls back type variables if the unsizing coercion
fails. This prevents a large amount of type-variables from accumulating
while type-checking a large function, e.g. shaving 2GB off one of the
4GB peaks in #36799.

This is a performance-sensitive PR so please don't roll it up.

r? @eddyb
cc @nikomatsakis
-rw-r--r--src/librustc/infer/error_reporting/mod.rs13
-rw-r--r--src/librustc_typeck/check/coercion.rs6
2 files changed, 16 insertions, 3 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index a88e90caee3..b24c9690a46 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -333,11 +333,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             GenericBoundFailure(..) => true,
         };
 
-        if errors.iter().all(|e| is_bound_failure(e)) {
+
+        let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
             errors.clone()
         } else {
             errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
-        }
+        };
+
+        // sort the errors by span, for better error message stability.
+        errors.sort_by_key(|u| match *u {
+            ConcreteFailure(ref sro, _, _) => sro.span(),
+            GenericBoundFailure(ref sro, _, _) => sro.span(),
+            SubSupConflict(ref rvo, _, _, _, _) => rvo.span(),
+        });
+        errors
     }
 
     /// Adds a note if the types come from similarly named crates
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index cfcdbcc1195..94422f93e59 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -187,7 +187,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
         }
 
         // Consider coercing the subtype to a DST
-        let unsize = self.coerce_unsized(a, b);
+        //
+        // NOTE: this is wrapped in a `commit_if_ok` because it creates
+        // a "spurious" type variable, and we don't want to have that
+        // type variable in memory if the coercion fails.
+        let unsize = self.commit_if_ok(|_| self.coerce_unsized(a, b));
         if unsize.is_ok() {
             debug!("coerce: unsize successful");
             return unsize;