From 19d913bf2563042881306b3969cb43c18fa36838 Mon Sep 17 00:00:00 2001 From: Kiet Tran Date: Sat, 22 Mar 2014 04:24:42 -0400 Subject: [PATCH] Prefer lifetime suggestion over generic error --- .../middle/typeck/infer/error_reporting.rs | 12 ++++++++++- .../typeck/infer/region_inference/mod.rs | 20 +++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index b0fd7d7c55b..83ca7ea7dfb 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -195,6 +195,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> { // failed (so the return value of this method should not be used) fn process_errors(&self, errors: &Vec) -> Vec { + debug!("process_errors()"); let mut var_origins = Vec::new(); let mut trace_origins = Vec::new(); let mut same_regions = Vec::new(); @@ -202,6 +203,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> { for error in errors.iter() { match *error { ConcreteFailure(origin, sub, sup) => { + debug!("processing ConcreteFailure") let trace = match origin { infer::Subtype(trace) => Some(trace), _ => None, @@ -218,6 +220,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> { } } SubSupConflict(var_origin, _, sub_r, _, sup_r) => { + debug!("processing SubSupConflict") match free_regions_from_same_fn(self.tcx, sub_r, sup_r) { Some(ref same_frs) => { var_origins.push(var_origin); @@ -237,10 +240,13 @@ impl<'a> ErrorReporting for InferCtxt<'a> { // declaration, we want to make sure that they are, in fact, // from the same scope if sr.scope_id != common_scope_id { + debug!("returning empty result from process_errors because + {} != {}", sr.scope_id, common_scope_id); return vec!(); } } let pe = ProcessedErrors(var_origins, trace_origins, same_regions); + debug!("errors processed: {:?}", pe); processed_errors.push(pe); } return processed_errors; @@ -256,6 +262,7 @@ impl<'a> ErrorReporting for InferCtxt<'a> { sub: Region, sup: Region) -> Option { + debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup); let (scope_id, fr1, fr2) = match (sub, sup) { (ReFree(fr1), ReFree(fr2)) => { if fr1.scope_id != fr2.scope_id { @@ -284,7 +291,10 @@ impl<'a> ErrorReporting for InferCtxt<'a> { }, _ => None }, - None => None + None => { + debug!("no parent node of scope_id {}", scope_id) + None + } } } diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index 9d271353988..8322612ba8f 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -1117,10 +1117,10 @@ impl<'a> RegionVarBindings<'a> { { // Errors in expanding nodes result from a lower-bound that is // not contained by an upper-bound. - let (lower_bounds, lower_dup) = + let (mut lower_bounds, lower_dup) = self.collect_concrete_regions(graph, var_data, node_idx, graph::Incoming, dup_vec); - let (upper_bounds, upper_dup) = + let (mut upper_bounds, upper_dup) = self.collect_concrete_regions(graph, var_data, node_idx, graph::Outgoing, dup_vec); @@ -1128,6 +1128,22 @@ impl<'a> RegionVarBindings<'a> { return; } + // We place free regions first because we are special casing + // SubSupConflict(ReFree, ReFree) when reporting error, and so + // the user will more likely get a specific suggestion. + fn free_regions_first(a: &RegionAndOrigin, + b: &RegionAndOrigin) + -> Ordering { + match (a.region, b.region) { + (ReFree(..), ReFree(..)) => Equal, + (ReFree(..), _) => Less, + (_, ReFree(..)) => Greater, + (_, _) => Equal, + } + } + lower_bounds.sort_by(|a, b| { free_regions_first(a, b) }); + upper_bounds.sort_by(|a, b| { free_regions_first(a, b) }); + for lower_bound in lower_bounds.iter() { for upper_bound in upper_bounds.iter() { if !self.is_subregion_of(lower_bound.region,