From ef26f1756c88fe75bc869a0c5f78496aa445b914 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 1 Jul 2017 15:41:49 +0200 Subject: [PATCH 1/2] Clean up some code --- src/librustc/diagnostics.rs | 29 +++++----- src/librustc/infer/error_reporting/mod.rs | 56 +++++++++---------- .../error_reporting/named_anon_conflict.rs | 9 +-- src/librustc/infer/mod.rs | 1 + src/librustc/ty/sty.rs | 1 - 5 files changed, 41 insertions(+), 55 deletions(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 08184d62679e..cc4d0f7e4c75 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1947,27 +1947,25 @@ Either way, try to update/remove it in order to fix the error. "##, E0621: r##" -This error code indicates a mismatch between the function signature (i.e., -the parameter types and the return type) and the function body. Most of -the time, this indicates that the function signature needs to be changed to -match the body, but it may be that the body needs to be changed to match -the signature. +This error code indicates a mismatch between the lifetimes appearing in the +function signature (i.e., the parameter types and the return type) and the +data-flow found in the function body. -Specifically, one or more of the parameters contain borrowed data that -needs to have a named lifetime in order for the body to type-check. Most of -the time, this is because the borrowed data is being returned from the -function, as in this example: +Erroneous code example: ```compile_fail,E0621 -fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // explicit lifetime required - // in the type of `y` +fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { // error: explicit lifetime + // required in the type of + // `y` if x > y { x } else { y } } ``` -Here, the function is returning data borrowed from either x or y, but the -'a annotation indicates that it is returning data only from x. We can make -the signature match the body by changing the type of y to &'a i32, like so: +In the code above, the function is returning data borrowed from either `x` or +`y`, but the `'a` annotation indicates that it is returning data only from `x`. +To fix the error, the signature and the body must be made to match. Typically, +this is done by updating the function signature. So, in this case, we change +the type of `y` to `&'a i32`, like so: ``` fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { @@ -1975,7 +1973,8 @@ fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { } ``` -Alternatively, you could change the body not to return data from y: +Now the signature indicates that the function data borrowed from either `x` or +`y`. Alternatively, you could change the body not to return data from y: ``` fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 { diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 82bbb4a1bf51..278ec03c7530 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -72,12 +72,12 @@ use ty::error::TypeError; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use errors::{DiagnosticBuilder, DiagnosticStyledString}; + mod note; mod need_type_info; mod named_anon_conflict; - impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn note_and_explain_region(self, err: &mut DiagnosticBuilder, @@ -265,40 +265,34 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // together into a `ProcessedErrors` group: let errors = self.process_errors(errors); - debug!("report_region_errors: {} errors after preprocessing", - errors.len()); + debug!("report_region_errors: {} errors after preprocessing", errors.len()); for error in errors { - debug!("report_region_errors: error = {:?}", error); - if !self.try_report_named_anon_conflict(&error){ - - match error.clone() { - // These errors could indicate all manner of different - // problems with many different solutions. Rather - // than generate a "one size fits all" error, what we - // attempt to do is go through a number of specific - // scenarios and try to find the best way to present - // the error. If all of these fails, we fall back to a rather - // general bit of code that displays the error information - ConcreteFailure(origin, sub, sup) => { - - self.report_concrete_failure(origin, sub, sup).emit(); - } - - GenericBoundFailure(kind, param_ty, sub) => { - self.report_generic_bound_failure(kind, param_ty, sub); - } - - SubSupConflict(var_origin, - sub_origin, sub_r, - sup_origin, sup_r) => { - self.report_sub_sup_conflict(var_origin, - sub_origin, sub_r, - sup_origin, sup_r); - } - } + if !self.try_report_named_anon_conflict(&error) { + match error.clone() { + // These errors could indicate all manner of different + // problems with many different solutions. Rather + // than generate a "one size fits all" error, what we + // attempt to do is go through a number of specific + // scenarios and try to find the best way to present + // the error. If all of these fails, we fall back to a rather + // general bit of code that displays the error information + ConcreteFailure(origin, sub, sup) => { + self.report_concrete_failure(origin, sub, sup).emit(); + } + GenericBoundFailure(kind, param_ty, sub) => { + self.report_generic_bound_failure(kind, param_ty, sub); + } + SubSupConflict(var_origin, + sub_origin, sub_r, + sup_origin, sup_r) => { + self.report_sub_sup_conflict(var_origin, + sub_origin, sub_r, + sup_origin, sup_r); + } + } } } } diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index ccbc5cdb862f..48f39ac5b3e5 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -37,7 +37,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match *anon_region { ty::ReFree(ref free_region) => { - let id = free_region.scope; let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); let body_id = self.tcx.hir.maybe_body_owned_by(node_id).unwrap(); @@ -69,7 +68,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } _ => None, - } } @@ -77,7 +75,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // the function arguments consist of a named region and an anonymous // region and corresponds to `ConcreteFailure(..)` pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { - let (span, sub, sup) = match *error { ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), _ => return false, // inapplicable @@ -113,7 +110,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .collect_referenced_late_bound_regions(&sig.output()); if late_bound_regions.iter().any(|r| *r == br) { return false; - } else { } } _ => {} @@ -134,10 +130,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() { (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name)) } else { - (format!("parameter type"), format!("type")) + ("parameter type".to_owned(), "type".to_owned()) }; - struct_span_err!(self.tcx.sess, span, E0621, @@ -149,13 +144,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .emit(); return true; - } // This method returns whether the given Region is Anonymous // and returns the DefId corresponding to the region. pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option { - match *region { ty::ReFree(ref free_region) => { match free_region.bound_region { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index a70a4248cb75..228481e85302 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -38,6 +38,7 @@ use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; use util::nodemap::FxHashMap; use arena::DroplessArena; + use self::combine::CombineFields; use self::higher_ranked::HrMatchResult; use self::region_inference::{RegionVarBindings, RegionSnapshot}; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 737e69b65834..ee6c7576aa27 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -993,7 +993,6 @@ impl RegionKind { // This method returns whether the given Region is Named pub fn is_named_region(&self) -> bool { - match *self { ty::ReFree(ref free_region) => { match free_region.bound_region { From 24a5ceab525a0f43d9553f3246516800be4931a9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 10 Jul 2017 13:45:10 -0400 Subject: [PATCH 2/2] tweak word ordering --- src/librustc/diagnostics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index cc4d0f7e4c75..cef1be5cee23 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -1974,7 +1974,7 @@ fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { ``` Now the signature indicates that the function data borrowed from either `x` or -`y`. Alternatively, you could change the body not to return data from y: +`y`. Alternatively, you could change the body to not return data from `y`: ``` fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32 {