From c1437c944c280ff9d761c45912167f1023d0e24c Mon Sep 17 00:00:00 2001 From: lqd Date: Fri, 25 Jan 2019 18:22:44 +0100 Subject: [PATCH 01/16] Make NiceRegionError use the `InferCtxt` instead of its `TyCtxt` Some errors (e.g placeholder errors) have unresolved type vars so this will allow to use `resolve_type_vars_if_possible` when needed. --- .../nice_region_error/different_lifetimes.rs | 6 +++--- .../nice_region_error/find_anon_type.rs | 8 ++++---- .../error_reporting/nice_region_error/mod.rs | 18 ++++++++++------- .../nice_region_error/named_anon_conflict.rs | 10 +++++----- .../nice_region_error/outlives_closure.rs | 4 ++-- .../nice_region_error/placeholder_error.rs | 20 +++++++++---------- .../nice_region_error/static_impl_trait.rs | 10 +++++----- .../error_reporting/nice_region_error/util.rs | 14 ++++++------- .../nll/region_infer/error_reporting/mod.rs | 2 +- 9 files changed, 48 insertions(+), 44 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index bfb5b61d0aa1..8be49b279244 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -46,9 +46,9 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { let (span, sub, sup) = self.get_regions(); // Determine whether the sub and sup consist of both anonymous (elided) regions. - let anon_reg_sup = self.tcx.is_suitable_region(sup)?; + let anon_reg_sup = self.tcx().is_suitable_region(sup)?; - let anon_reg_sub = self.tcx.is_suitable_region(sub)?; + let anon_reg_sub = self.tcx().is_suitable_region(sub)?; let scope_def_id_sup = anon_reg_sup.def_id; let bregion_sup = anon_reg_sup.boundregion; let scope_def_id_sub = anon_reg_sub.def_id; @@ -138,7 +138,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { }; - struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch") + struct_span_err!(self.tcx().sess, span, E0623, "lifetime mismatch") .span_label(span_1, main_label) .span_label(span_2, String::new()) .span_label(span, span_label) diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs index d230ce55471e..eeaa01375ed4 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -26,10 +26,10 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { region: Region<'tcx>, br: &ty::BoundRegion, ) -> Option<(&hir::Ty, &hir::FnDecl)> { - if let Some(anon_reg) = self.tcx.is_suitable_region(region) { + if let Some(anon_reg) = self.tcx().is_suitable_region(region) { let def_id = anon_reg.def_id; - if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { - let fndecl = match self.tcx.hir().get(node_id) { + if let Some(node_id) = self.tcx().hir().as_local_node_id(def_id) { + let fndecl = match self.tcx().hir().get(node_id) { Node::Item(&hir::Item { node: hir::ItemKind::Fn(ref fndecl, ..), .. @@ -64,7 +64,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { br: &ty::BoundRegion, ) -> Option<(&'gcx hir::Ty)> { let mut nested_visitor = FindNestedTypeVisitor { - tcx: self.tcx, + tcx: self.tcx(), bound_region: *br, found_type: None, current_index: ty::INNERMOST, diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc/infer/error_reporting/nice_region_error/mod.rs index f7ba546fa7f3..d34b71c33f4b 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/mod.rs @@ -22,15 +22,15 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { if let Some(tables) = self.in_progress_tables { let tables = tables.borrow(); - NiceRegionError::new(self.tcx, error.clone(), Some(&tables)).try_report().is_some() + NiceRegionError::new(self, error.clone(), Some(&tables)).try_report().is_some() } else { - NiceRegionError::new(self.tcx, error.clone(), None).try_report().is_some() + NiceRegionError::new(self, error.clone(), None).try_report().is_some() } } } pub struct NiceRegionError<'cx, 'gcx: 'tcx, 'tcx: 'cx> { - tcx: TyCtxt<'cx, 'gcx, 'tcx>, + infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, error: Option>, regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>, tables: Option<&'cx ty::TypeckTables<'tcx>>, @@ -38,21 +38,25 @@ pub struct NiceRegionError<'cx, 'gcx: 'tcx, 'tcx: 'cx> { impl<'cx, 'gcx, 'tcx> NiceRegionError<'cx, 'gcx, 'tcx> { pub fn new( - tcx: TyCtxt<'cx, 'gcx, 'tcx>, + infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, error: RegionResolutionError<'tcx>, tables: Option<&'cx ty::TypeckTables<'tcx>>, ) -> Self { - Self { tcx, error: Some(error), regions: None, tables } + Self { infcx, error: Some(error), regions: None, tables } } pub fn new_from_span( - tcx: TyCtxt<'cx, 'gcx, 'tcx>, + infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, span: Span, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, tables: Option<&'cx ty::TypeckTables<'tcx>>, ) -> Self { - Self { tcx, error: None, regions: Some((span, sub, sup)), tables } + Self { infcx, error: None, regions: Some((span, sub, sup)), tables } + } + + fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> { + self.infcx.tcx } pub fn try_report_from_nll(&self) -> Option { diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 918a46aacd04..05333f433733 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -24,23 +24,23 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { // version new_ty of its type where the anonymous region is replaced // with the named one.//scope_def_id let (named, anon, anon_arg_info, region_info) = if self.is_named_region(sub) - && self.tcx.is_suitable_region(sup).is_some() + && self.tcx().is_suitable_region(sup).is_some() && self.find_arg_with_region(sup, sub).is_some() { ( sub, sup, self.find_arg_with_region(sup, sub).unwrap(), - self.tcx.is_suitable_region(sup).unwrap(), + self.tcx().is_suitable_region(sup).unwrap(), ) - } else if self.is_named_region(sup) && self.tcx.is_suitable_region(sub).is_some() + } else if self.is_named_region(sup) && self.tcx().is_suitable_region(sub).is_some() && self.find_arg_with_region(sub, sup).is_some() { ( sup, sub, self.find_arg_with_region(sub, sup).unwrap(), - self.tcx.is_suitable_region(sub).unwrap(), + self.tcx().is_suitable_region(sub).unwrap(), ) } else { return None; // inapplicable @@ -97,7 +97,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { }; struct_span_err!( - self.tcx.sess, + self.tcx().sess, span, E0621, "explicit lifetime required in {}", diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs index c4c71037d8b3..cbd36a8b2db8 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs @@ -47,7 +47,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { // closure, provide a specific message pointing this out. if let (&SubregionOrigin::BindingTypeIsNotValidAtDecl(ref external_span), &RegionKind::ReFree(ref free_region)) = (&sub_origin, sup_region) { - let hir = &self.tcx.hir(); + let hir = &self.tcx().hir(); if let Some(node_id) = hir.as_local_node_id(free_region.scope) { if let Node::Expr(Expr { node: Closure(_, _, _, closure_span, None), @@ -55,7 +55,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { }) = hir.get(node_id) { let sup_sp = sup_origin.span(); let origin_sp = origin.span(); - let mut err = self.tcx.sess.struct_span_err( + let mut err = self.tcx().sess.struct_span_err( sup_sp, "borrowed data cannot be stored outside of its closure"); err.span_label(sup_sp, "cannot be stored outside of its closure"); diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 0dda636a9bd5..7ece3d38a7f3 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -38,7 +38,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { if expected.def_id == found.def_id => { Some(self.try_report_placeholders_trait( - Some(self.tcx.mk_region(ty::ReVar(*vid))), + Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, Some(sub_placeholder), Some(sup_placeholder), @@ -62,7 +62,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { if expected.def_id == found.def_id => { Some(self.try_report_placeholders_trait( - Some(self.tcx.mk_region(ty::ReVar(*vid))), + Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, Some(sub_placeholder), None, @@ -86,7 +86,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { if expected.def_id == found.def_id => { Some(self.try_report_placeholders_trait( - Some(self.tcx.mk_region(ty::ReVar(*vid))), + Some(self.tcx().mk_region(ty::ReVar(*vid))), cause, None, Some(*sup_placeholder), @@ -182,11 +182,11 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { expected_substs: &'tcx Substs<'tcx>, actual_substs: &'tcx Substs<'tcx>, ) -> ErrorReported { - let mut err = self.tcx.sess.struct_span_err( - cause.span(&self.tcx), + let mut err = self.tcx().sess.struct_span_err( + cause.span(&self.tcx()), &format!( "implementation of `{}` is not general enough", - self.tcx.item_path_str(trait_def_id), + self.tcx().item_path_str(trait_def_id), ), ); @@ -194,7 +194,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { ObligationCauseCode::ItemObligation(def_id) => { err.note(&format!( "Due to a where-clause on `{}`,", - self.tcx.item_path_str(def_id), + self.tcx().item_path_str(def_id), )); } _ => (), @@ -220,7 +220,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { let mut has_sup = None; let mut has_vid = None; - self.tcx.for_each_free_region(&expected_trait_ref, |r| { + self.tcx().for_each_free_region(&expected_trait_ref, |r| { if Some(r) == sub_placeholder && has_sub.is_none() { has_sub = Some(counter); counter += 1; @@ -230,7 +230,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { } }); - self.tcx.for_each_free_region(&actual_trait_ref, |r| { + self.tcx().for_each_free_region(&actual_trait_ref, |r| { if Some(r) == vid && has_vid.is_none() { has_vid = Some(counter); counter += 1; @@ -238,7 +238,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { }); let self_ty_has_vid = self - .tcx + .tcx() .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid); RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || { diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs index 7501e2f21088..4331518d403d 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -19,13 +19,13 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { sup_r, ) = error.clone() { - let anon_reg_sup = self.tcx.is_suitable_region(sup_r)?; + let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?; if sub_r == &RegionKind::ReStatic && - self.tcx.return_type_impl_trait(anon_reg_sup.def_id).is_some() + self.tcx().return_type_impl_trait(anon_reg_sup.def_id).is_some() { let sp = var_origin.span(); let return_sp = sub_origin.span(); - let mut err = self.tcx.sess.struct_span_err( + let mut err = self.tcx().sess.struct_span_err( sp, "cannot infer an appropriate lifetime", ); @@ -38,7 +38,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { "...but this borrow...", ); - let (lifetime, lt_sp_opt) = self.tcx.msg_span_from_free_region(sup_r); + let (lifetime, lt_sp_opt) = self.tcx().msg_span_from_free_region(sup_r); if let Some(lifetime_sp) = lt_sp_opt { err.span_note( lifetime_sp, @@ -52,7 +52,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { }) => name.to_string(), _ => "'_".to_owned(), }; - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(return_sp) { + if let Ok(snippet) = self.tcx().sess.source_map().span_to_snippet(return_sp) { err.span_suggestion( return_sp, &format!( diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index 43590a606ae9..dd8a33829eb5 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -44,13 +44,13 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { let (id, bound_region) = match *anon_region { ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), ty::ReEarlyBound(ref ebr) => ( - self.tcx.parent_def_id(ebr.def_id).unwrap(), + self.tcx().parent_def_id(ebr.def_id).unwrap(), ty::BoundRegion::BrNamed(ebr.def_id, ebr.name), ), _ => return None, // not a free region }; - let hir = &self.tcx.hir(); + let hir = &self.tcx().hir(); if let Some(node_id) = hir.as_local_node_id(id) { if let Some(body_id) = hir.maybe_body_owned_by(node_id) { let body = hir.body(body_id); @@ -66,7 +66,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { let arg_ty_span = hir.span(hir.hir_to_node_id(ty_hir_id)); let ty = tables.node_id_to_type_opt(arg.hir_id)?; let mut found_anon_region = false; - let new_arg_ty = self.tcx.fold_regions(&ty, &mut false, |r, _| { + let new_arg_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { if *r == *anon_region { found_anon_region = true; replace_region @@ -108,10 +108,10 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { br: ty::BoundRegion, decl: &hir::FnDecl, ) -> Option { - let ret_ty = self.tcx.type_of(scope_def_id); + let ret_ty = self.tcx().type_of(scope_def_id); if let ty::FnDef(_, _) = ret_ty.sty { - let sig = ret_ty.fn_sig(self.tcx); - let late_bound_regions = self.tcx + let sig = ret_ty.fn_sig(self.tcx()); + let late_bound_regions = self.tcx() .collect_referenced_late_bound_regions(&sig.output()); if late_bound_regions.iter().any(|r| *r == br) { return Some(decl.output.span()); @@ -126,7 +126,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { // enable E0621 for it. pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool { is_first - && self.tcx + && self.tcx() .opt_associated_item(scope_def_id) .map(|i| i.method_has_self_argument) == Some(true) } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index f07880075c10..ec68ddaf3c85 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -243,7 +243,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Check if we can use one of the "nice region errors". if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { let tables = infcx.tcx.typeck_tables_of(mir_def_id); - let nice = NiceRegionError::new_from_span(infcx.tcx, span, o, f, Some(tables)); + let nice = NiceRegionError::new_from_span(infcx, span, o, f, Some(tables)); if let Some(_error_reported) = nice.try_report_from_nll() { return; } From a6028263d2c9c3568f86e57d6b8400e05d3cfe1b Mon Sep 17 00:00:00 2001 From: lqd Date: Fri, 25 Jan 2019 18:35:47 +0100 Subject: [PATCH 02/16] Handle higher-ranked lifetime conflict errors where the subtype is the `sup` region These are happening since the switch to universes, and will now go through the "placeholder error" path, instead of the current fallback of E308 "mismatched types" errors. --- .../nice_region_error/placeholder_error.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 7ece3d38a7f3..636b66bef01c 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -96,6 +96,30 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { )) } + Some(RegionResolutionError::SubSupConflict( + vid, + _, + _, + _, + SubregionOrigin::Subtype(TypeTrace { + cause, + values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), + }), + sup_placeholder @ ty::RePlaceholder(_), + )) + if expected.def_id == found.def_id => + { + Some(self.try_report_placeholders_trait( + Some(self.tcx().mk_region(ty::ReVar(*vid))), + cause, + None, + Some(*sup_placeholder), + expected.def_id, + expected.substs, + found.substs, + )) + } + Some(RegionResolutionError::ConcreteFailure( SubregionOrigin::Subtype(TypeTrace { cause, From 823c888be297230389a25c9e79e39811a6f61537 Mon Sep 17 00:00:00 2001 From: lqd Date: Fri, 25 Jan 2019 18:39:51 +0100 Subject: [PATCH 03/16] Try to resolve type vars in the placeholder errors trait refs These can sometimes be unresolved: some of the rustc UI tests show this. --- .../nice_region_error/placeholder_error.rs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 636b66bef01c..892c56bf834f 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -224,14 +224,18 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { _ => (), } - let expected_trait_ref = ty::TraitRef { - def_id: trait_def_id, - substs: expected_substs, - }; - let actual_trait_ref = ty::TraitRef { - def_id: trait_def_id, - substs: actual_substs, - }; + let expected_trait_ref = self.infcx.resolve_type_vars_if_possible( + &ty::TraitRef { + def_id: trait_def_id, + substs: expected_substs, + } + ); + let actual_trait_ref = self.infcx.resolve_type_vars_if_possible( + &ty::TraitRef { + def_id: trait_def_id, + substs: actual_substs, + } + ); // Search the expected and actual trait references to see (a) // whether the sub/sup placeholders appear in them (sometimes From 55389f9171d3e8e05230ae5ea3d07b9c7e54705d Mon Sep 17 00:00:00 2001 From: lqd Date: Fri, 25 Jan 2019 19:02:38 +0100 Subject: [PATCH 04/16] Try to reword placeholder error messages to make them clearer --- .../nice_region_error/placeholder_error.rs | 76 +++++++++++-------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 892c56bf834f..b5187d2dbb6c 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -246,7 +246,9 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { let mut counter = 0; let mut has_sub = None; let mut has_sup = None; - let mut has_vid = None; + + let mut actual_has_vid = None; + let mut expected_has_vid = None; self.tcx().for_each_free_region(&expected_trait_ref, |r| { if Some(r) == sub_placeholder && has_sub.is_none() { @@ -256,11 +258,16 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { has_sup = Some(counter); counter += 1; } + + if Some(r) == vid && expected_has_vid.is_none() { + expected_has_vid = Some(counter); + counter += 1; + } }); self.tcx().for_each_free_region(&actual_trait_ref, |r| { - if Some(r) == vid && has_vid.is_none() { - has_vid = Some(counter); + if Some(r) == vid && actual_has_vid.is_none() { + actual_has_vid = Some(counter); counter += 1; } }); @@ -274,60 +281,67 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { match (has_sub, has_sup) { (Some(n1), Some(n2)) => { err.note(&format!( - "`{}` must implement `{}` \ - for any two lifetimes `'{}` and `'{}`", - expected_trait_ref.self_ty(), + "`{}` would have to be implemented for the type `{}`, \ + for any two lifetimes `'{}` and `'{}`", expected_trait_ref, + expected_trait_ref.self_ty(), std::cmp::min(n1, n2), std::cmp::max(n1, n2), )); } (Some(n), _) | (_, Some(n)) => { err.note(&format!( - "`{}` must implement `{}` \ - for any lifetime `'{}`", - expected_trait_ref.self_ty(), + "`{}` would have to be implemented for the type `{}`, \ + for any lifetime `'{}`", expected_trait_ref, + expected_trait_ref.self_ty(), n, )); } (None, None) => { err.note(&format!( - "`{}` must implement `{}`", - expected_trait_ref.self_ty(), + "`{}` would have to be implemented for the type `{}`", expected_trait_ref, + expected_trait_ref.self_ty(), )); } } }) }); - RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid { - Some(n) => { - if self_ty_has_vid { + RegionHighlightMode::maybe_highlighting_region( + vid, + actual_has_vid.or(expected_has_vid), + || match actual_has_vid { + Some(n) => { + if self_ty_has_vid { + err.note(&format!( + "but `{}` is actually implemented for the type `{}`, \ + for the specific lifetime `'{}`", + actual_trait_ref, + actual_trait_ref.self_ty(), + n + )); + } else { + err.note(&format!( + "but `{}` is actually implemented for the type `{}`, \ + for some lifetime `'{}`", + actual_trait_ref, + actual_trait_ref.self_ty(), + n + )); + } + } + + _ => { err.note(&format!( - "but `{}` only implements `{}` for the lifetime `'{}`", - actual_trait_ref.self_ty(), + "but `{}` is actually implemented for the type `{}`", actual_trait_ref, - n - )); - } else { - err.note(&format!( - "but `{}` only implements `{}` for some lifetime `'{}`", actual_trait_ref.self_ty(), - actual_trait_ref, - n )); } } - None => { - err.note(&format!( - "but `{}` only implements `{}`", - actual_trait_ref.self_ty(), - actual_trait_ref, - )); - } - }); + ); err.emit(); ErrorReported From ce61b1b9fac1d175e13a5f21ffe93cd76dd64481 Mon Sep 17 00:00:00 2001 From: lqd Date: Fri, 25 Jan 2019 19:04:26 +0100 Subject: [PATCH 05/16] Update two E308 tests to the new placeholder error --- src/test/ui/associated-types/higher-ranked-projection.rs | 2 +- src/test/ui/hrtb/hrtb-perfect-forwarding.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 5b380c982f04..1280c8cb4cb0 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.rs +++ b/src/test/ui/associated-types/higher-ranked-projection.rs @@ -23,5 +23,5 @@ fn foo(_t: T) #[rustc_error] fn main() { //[good]~ ERROR compilation successful foo(()); - //[bad]~^ ERROR E0308 + //[bad]~^ ERROR not general enough } diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs index 7bd89960e42e..0094091c6bd7 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs @@ -43,7 +43,7 @@ fn foo_hrtb_bar_not<'b,T>(mut t: T) // be implemented. Thus to satisfy `&mut T : for<'a> Foo<&'a // isize>`, we require `T : for<'a> Bar<&'a isize>`, but the where // clause only specifies `T : Bar<&'b isize>`. - foo_hrtb_bar_not(&mut t); //~ ERROR E0308 + foo_hrtb_bar_not(&mut t); //~ ERROR not general enough } fn foo_hrtb_bar_hrtb(mut t: T) From a79f135be616588e83d18b4694d97470e986497a Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Fri, 25 Jan 2019 19:17:38 +0100 Subject: [PATCH 06/16] Update test expectations for new placeholder error messages --- .../associated-types-eq-hr.stderr | 12 ++++++------ .../higher-ranked-projection.bad.stderr | 10 +++++----- .../higher-ranked-projection.good.stderr | 2 +- src/test/ui/generator/auto-trait-regions.stderr | 8 ++++---- src/test/ui/hrtb/hrtb-cache-issue-54302.stderr | 4 ++-- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 4 ++-- .../hrtb-exists-forall-trait-invariant.stderr | 4 ++-- src/test/ui/hrtb/hrtb-just-for-static.stderr | 8 ++++---- src/test/ui/hrtb/hrtb-perfect-forwarding.stderr | 12 ++++++------ src/test/ui/issues/issue-54302-cases.stderr | 16 ++++++++-------- src/test/ui/issues/issue-54302.stderr | 4 ++-- .../ui/where-clauses/where-for-self-2.stderr | 4 ++-- 12 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index d3eaa894b504..0e471a78d9ed 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -41,8 +41,8 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `tuple_one`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` + = note: `TheTrait<(&'0 isize, &'1 isize)>` would have to be implemented for the type `Tuple`, for any two lifetimes `'0` and `'1` + = note: but `TheTrait<(&'2 isize, &'2 isize)>` is actually implemented for the type `Tuple`, for some lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 @@ -51,8 +51,8 @@ LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `tuple_two`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` + = note: `TheTrait<(&'0 isize, &'1 isize)>` would have to be implemented for the type `Tuple`, for any two lifetimes `'0` and `'1` + = note: but `TheTrait<(&'2 isize, &'2 isize)>` is actually implemented for the type `Tuple`, for some lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:105:5 @@ -61,8 +61,8 @@ LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `tuple_four`, - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `Tuple` only implements `TheTrait<(&'2 isize, &'2 isize)>` for some lifetime `'2` + = note: `TheTrait<(&'0 isize, &'1 isize)>` would have to be implemented for the type `Tuple`, for any two lifetimes `'0` and `'1` + = note: but `TheTrait<(&'2 isize, &'2 isize)>` is actually implemented for the type `Tuple`, for some lifetime `'2` error: aborting due to 5 previous errors diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index e4704494e149..69fa1ce30aa8 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -1,12 +1,12 @@ -error[E0308]: mismatched types +error: implementation of `Mirror` is not general enough --> $DIR/higher-ranked-projection.rs:25:5 | LL | foo(()); - | ^^^ one type is more general than the other + | ^^^ | - = note: expected type `Mirror` - found type `Mirror` + = note: Due to a where-clause on `foo`, + = note: `Mirror` would have to be implemented for the type `&'0 ()`, for any lifetime `'0` + = note: but `Mirror` is actually implemented for the type `&'1 ()`, for the specific lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/associated-types/higher-ranked-projection.good.stderr b/src/test/ui/associated-types/higher-ranked-projection.good.stderr index db15ec51d87c..c5c8451a5a9d 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.good.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.good.stderr @@ -3,7 +3,7 @@ error: compilation successful | LL | / fn main() { //[good]~ ERROR compilation successful LL | | foo(()); -LL | | //[bad]~^ ERROR E0308 +LL | | //[bad]~^ ERROR not general enough LL | | } | |_^ diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 1b4dfe2df1c0..680a7bbc50e5 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -4,8 +4,8 @@ error: implementation of `Foo` is not general enough LL | assert_foo(gen); | ^^^^^^^^^^ | - = note: `&'0 OnlyFooIfStaticRef` must implement `Foo` for any lifetime `'0` - = note: but `&'1 OnlyFooIfStaticRef` only implements `Foo` for the lifetime `'1` + = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0` + = note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for the specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:48:5 @@ -13,8 +13,8 @@ error: implementation of `Foo` is not general enough LL | assert_foo(gen); | ^^^^^^^^^^ | - = note: `A<'0, '1>` must implement `Foo` for any two lifetimes `'0` and `'1` - = note: but `A<'_, '2>` only implements `Foo` for the lifetime `'2` + = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1` + = note: but `Foo` is actually implemented for the type `A<'_, '2>`, for the specific lifetime `'2` error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr index e82fa51524ef..1aa0a7ca32bd 100644 --- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -4,8 +4,8 @@ error: implementation of `Deserialize` is not general enough LL | assert_deserialize_owned::<&'static str>(); //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `&'static str` must implement `Deserialize<'0>` for any lifetime `'0` - = note: but `&str` only implements `Deserialize<'1>` for some lifetime `'1` + = note: `Deserialize<'0>` would have to be implemented for the type `&'static str`, for any lifetime `'0` + = note: but `Deserialize<'1>` is actually implemented for the type `&str`, for some lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 2ee398e3dd3b..4c4f79798804 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -5,8 +5,8 @@ LL | fn b() { want_foo2::(); } //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `want_foo2`, - = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>` for any two lifetimes `'0` and `'1` - = note: but `SomeStruct` only implements `Foo<(&'2 isize, &'2 isize)>` for some lifetime `'2` + = note: `Foo<(&'0 isize, &'1 isize)>` would have to be implemented for the type `SomeStruct`, for any two lifetimes `'0` and `'1` + = note: but `Foo<(&'2 isize, &'2 isize)>` is actually implemented for the type `SomeStruct`, for some lifetime `'2` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 6a61181e2407..916a524939b6 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -5,8 +5,8 @@ LL | foo::<()>(); //~ ERROR not general enough | ^^^^^^^^^ | = note: Due to a where-clause on `foo`, - = note: `()` must implement `Trait fn(std::cell::Cell<&'b u32>)>` - = note: but `()` only implements `Trait)>` for some lifetime `'0` + = note: `Trait fn(std::cell::Cell<&'b u32>)>` would have to be implemented for the type `()` + = note: but `Trait)>` is actually implemented for the type `()`, for some lifetime `'0` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 094c44980241..bd6e3dbebd2f 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -5,8 +5,8 @@ LL | want_hrtb::() //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `want_hrtb`, - = note: `StaticInt` must implement `Foo<&'0 isize>` for any lifetime `'0` - = note: but `StaticInt` only implements `Foo<&'1 isize>` for some lifetime `'1` + = note: `Foo<&'0 isize>` would have to be implemented for the type `StaticInt`, for any lifetime `'0` + = note: but `Foo<&'1 isize>` is actually implemented for the type `StaticInt`, for some lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 @@ -15,8 +15,8 @@ LL | want_hrtb::<&'a u32>() //~ ERROR | ^^^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `want_hrtb`, - = note: `&'a u32` must implement `Foo<&'0 isize>` for any lifetime `'0` - = note: but `&'1 u32` only implements `Foo<&'1 isize>` for the lifetime `'1` + = note: `Foo<&'0 isize>` would have to be implemented for the type `&'a u32`, for any lifetime `'0` + = note: but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for the specific lifetime `'1` error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index ec3bf8a1a1be..8b71a8a800e5 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -1,12 +1,12 @@ -error[E0308]: mismatched types +error: implementation of `Foo` is not general enough --> $DIR/hrtb-perfect-forwarding.rs:46:5 | -LL | foo_hrtb_bar_not(&mut t); //~ ERROR E0308 - | ^^^^^^^^^^^^^^^^ one type is more general than the other +LL | foo_hrtb_bar_not(&mut t); //~ ERROR not general enough + | ^^^^^^^^^^^^^^^^ | - = note: expected type `Foo<&'a isize>` - found type `Foo<&isize>` + = note: Due to a where-clause on `foo_hrtb_bar_not`, + = note: `Foo<&'0 isize>` would have to be implemented for the type `&mut T`, for any lifetime `'0` + = note: but `Foo<&'1 isize>` is actually implemented for the type `&mut T`, for some lifetime `'1` error: aborting due to previous error -For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index c1329d331a18..377bac3b2452 100644 --- a/src/test/ui/issues/issue-54302-cases.stderr +++ b/src/test/ui/issues/issue-54302-cases.stderr @@ -4,8 +4,8 @@ error: implementation of `Foo` is not general enough LL | >::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `&'0 u32` must implement `Foo<'static, u32>` for any lifetime `'0` - = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` + = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0` + = note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for the specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 @@ -13,8 +13,8 @@ error: implementation of `Foo` is not general enough LL | >::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `&'0 i32` must implement `Foo<'static, i32>` for any lifetime `'0` - = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` + = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0` + = note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for the specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 @@ -22,8 +22,8 @@ error: implementation of `Foo` is not general enough LL | >::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `&'0 u64` must implement `Foo<'static, u64>` for any lifetime `'0` - = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` + = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0` + = note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for the specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 @@ -31,8 +31,8 @@ error: implementation of `Foo` is not general enough LL | >::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `&'0 i64` must implement `Foo<'static, i64>` for any lifetime `'0` - = note: but `&'1 _` only implements `Foo<'_, _>` for the lifetime `'1` + = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0` + = note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for the specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr index 1b255204b6ef..ddf0414faf63 100644 --- a/src/test/ui/issues/issue-54302.stderr +++ b/src/test/ui/issues/issue-54302.stderr @@ -4,8 +4,8 @@ error: implementation of `Deserialize` is not general enough LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `&'static str` must implement `Deserialize<'0>` for any lifetime `'0` - = note: but `&str` only implements `Deserialize<'1>` for some lifetime `'1` + = note: `Deserialize<'0>` would have to be implemented for the type `&'static str`, for any lifetime `'0` + = note: but `Deserialize<'1>` is actually implemented for the type `&str`, for some lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index afc80bf4d8ee..4d827e6ce4fd 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -5,8 +5,8 @@ LL | foo(&X); //~ ERROR implementation of `Bar` is not general enough | ^^^ | = note: Due to a where-clause on `foo`, - = note: `&'0 _` must implement `Bar` for any lifetime `'0` - = note: but `&'1 u32` only implements `Bar` for the lifetime `'1` + = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0` + = note: but `Bar` is actually implemented for the type `&'1 u32`, for the specific lifetime `'1` error: aborting due to previous error From f5a74d40d9ceef0d27d8d60e1b867e6cbf3f6883 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Fri, 25 Jan 2019 19:35:35 +0100 Subject: [PATCH 07/16] Test new placeholder error messages in previously untested combinations --- src/test/ui/issues/issue-57362.rs | 41 +++++++++++++++++++++++++++ src/test/ui/issues/issue-57362.stderr | 20 +++++++++++++ 2 files changed, 61 insertions(+) create mode 100755 src/test/ui/issues/issue-57362.rs create mode 100644 src/test/ui/issues/issue-57362.stderr diff --git a/src/test/ui/issues/issue-57362.rs b/src/test/ui/issues/issue-57362.rs new file mode 100755 index 000000000000..d5b506f3c2c9 --- /dev/null +++ b/src/test/ui/issues/issue-57362.rs @@ -0,0 +1,41 @@ +// Test for issue #57362, ensuring that the self ty is shown in cases of higher-ranked lifetimes +// conflicts: the `expected` and `found` trait refs would otherwise be printed the same, leading +// to confusing notes such as: +// = note: expected type `Trait` +// found type `Trait` + +// from issue #57362 +trait Trait { + fn f(self); +} + +impl Trait for fn(&T) { + fn f(self) { + println!("f"); + } +} + +fn f() { + let a: fn(_) = |_: &u8| {}; + a.f(); //~ ERROR not general enough +} + +// extracted from a similar issue: #57642 +trait X { + type G; + fn make_g() -> Self::G; +} + +impl<'a> X for fn(&'a ()) { + type G = &'a (); + + fn make_g() -> Self::G { + &() + } +} + +fn g() { + let x = ::make_g(); //~ ERROR not general enough +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/issues/issue-57362.stderr b/src/test/ui/issues/issue-57362.stderr new file mode 100644 index 000000000000..d7886e5af271 --- /dev/null +++ b/src/test/ui/issues/issue-57362.stderr @@ -0,0 +1,20 @@ +error: implementation of `Trait` is not general enough + --> $DIR/issue-57362.rs:20:7 + | +LL | a.f(); //~ ERROR not general enough + | ^ + | + = note: `Trait` would have to be implemented for the type `fn(&u8)` + = note: but `Trait` is actually implemented for the type `for<'r> fn(&'r u8)` + +error: implementation of `X` is not general enough + --> $DIR/issue-57362.rs:38:13 + | +LL | let x = ::make_g(); //~ ERROR not general enough + | ^^^^^^^^^^^^^^^^^^ + | + = note: `X` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: but `X` is actually implemented for the type `fn(&'0 ())`, for the specific lifetime `'0` + +error: aborting due to 2 previous errors + From c5dea5753fd1c1a77813b7829573025e28c214b5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 25 Jan 2019 14:53:59 -0500 Subject: [PATCH 08/16] break apart tests --- src/test/ui/issues/issue-57362-1.rs | 23 +++++++++++++++++++ ...ssue-57362.stderr => issue-57362-1.stderr} | 0 .../{issue-57362.rs => issue-57362-2.rs} | 18 +-------------- 3 files changed, 24 insertions(+), 17 deletions(-) create mode 100755 src/test/ui/issues/issue-57362-1.rs rename src/test/ui/issues/{issue-57362.stderr => issue-57362-1.stderr} (100%) rename src/test/ui/issues/{issue-57362.rs => issue-57362-2.rs} (71%) mode change 100755 => 100644 diff --git a/src/test/ui/issues/issue-57362-1.rs b/src/test/ui/issues/issue-57362-1.rs new file mode 100755 index 000000000000..fe6b69f00977 --- /dev/null +++ b/src/test/ui/issues/issue-57362-1.rs @@ -0,0 +1,23 @@ +// Test for issue #57362, ensuring that the self ty is shown in cases of higher-ranked lifetimes +// conflicts: the `expected` and `found` trait refs would otherwise be printed the same, leading +// to confusing notes such as: +// = note: expected type `Trait` +// found type `Trait` + +// from issue #57362 +trait Trait { + fn f(self); +} + +impl Trait for fn(&T) { + fn f(self) { + println!("f"); + } +} + +fn f() { + let a: fn(_) = |_: &u8| {}; + a.f(); //~ ERROR not general enough +} + +fn main() {} diff --git a/src/test/ui/issues/issue-57362.stderr b/src/test/ui/issues/issue-57362-1.stderr similarity index 100% rename from src/test/ui/issues/issue-57362.stderr rename to src/test/ui/issues/issue-57362-1.stderr diff --git a/src/test/ui/issues/issue-57362.rs b/src/test/ui/issues/issue-57362-2.rs old mode 100755 new mode 100644 similarity index 71% rename from src/test/ui/issues/issue-57362.rs rename to src/test/ui/issues/issue-57362-2.rs index d5b506f3c2c9..436a4a904576 --- a/src/test/ui/issues/issue-57362.rs +++ b/src/test/ui/issues/issue-57362-2.rs @@ -4,22 +4,6 @@ // = note: expected type `Trait` // found type `Trait` -// from issue #57362 -trait Trait { - fn f(self); -} - -impl Trait for fn(&T) { - fn f(self) { - println!("f"); - } -} - -fn f() { - let a: fn(_) = |_: &u8| {}; - a.f(); //~ ERROR not general enough -} - // extracted from a similar issue: #57642 trait X { type G; @@ -38,4 +22,4 @@ fn g() { let x = ::make_g(); //~ ERROR not general enough } -fn main() {} \ No newline at end of file +fn main() {} From ab80162e3ffe52ded81917b8f0c032c9bc9d3c58 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 25 Jan 2019 14:54:42 -0500 Subject: [PATCH 09/16] add a lot more `debug!` to `try_report_placeholders_trait` --- .../nice_region_error/placeholder_error.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index b5187d2dbb6c..94e20731bfe7 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -206,6 +206,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { expected_substs: &'tcx Substs<'tcx>, actual_substs: &'tcx Substs<'tcx>, ) -> ErrorReported { + debug!("try_report_placeholders_trait(\ + vid={:?}, \ + sub_placeholder={:?}, \ + sup_placeholder={:?}, \ + trait_def_id={:?}, \ + expected_substs={:?}, \ + actual_substs={:?})", + vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs); + let mut err = self.tcx().sess.struct_span_err( cause.span(&self.tcx()), &format!( @@ -276,6 +285,12 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { .tcx() .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid); + debug!("try_report_placeholders_trait: actual_has_vid={:?}", actual_has_vid); + debug!("try_report_placeholders_trait: expected_has_vid={:?}", expected_has_vid); + debug!("try_report_placeholders_trait: has_sub={:?}", has_sub); + debug!("try_report_placeholders_trait: has_sup={:?}", has_sup); + debug!("try_report_placeholders_trait: self_ty_has_vid={:?}", self_ty_has_vid); + RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || { RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { match (has_sub, has_sup) { From ec6405bccd8b1f0933a3604bdd86c43707350275 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 25 Jan 2019 15:23:13 -0500 Subject: [PATCH 10/16] identify when implemented for "some specific lifetime" --- .../nice_region_error/placeholder_error.rs | 247 +++++++++--------- src/test/ui/issues/issue-57362-1.stderr | 15 +- src/test/ui/issues/issue-57362-2.stderr | 11 + 3 files changed, 134 insertions(+), 139 deletions(-) create mode 100644 src/test/ui/issues/issue-57362-2.stderr diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 94e20731bfe7..f5c51f8ee260 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -34,19 +34,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { sub_placeholder @ ty::RePlaceholder(_), _, sup_placeholder @ ty::RePlaceholder(_), - )) - if expected.def_id == found.def_id => - { - Some(self.try_report_placeholders_trait( - Some(self.tcx().mk_region(ty::ReVar(*vid))), - cause, - Some(sub_placeholder), - Some(sup_placeholder), - expected.def_id, - expected.substs, - found.substs, - )) - } + )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + Some(self.tcx().mk_region(ty::ReVar(*vid))), + cause, + Some(sub_placeholder), + Some(sup_placeholder), + expected.def_id, + expected.substs, + found.substs, + )), Some(RegionResolutionError::SubSupConflict( vid, @@ -58,19 +54,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { sub_placeholder @ ty::RePlaceholder(_), _, _, - )) - if expected.def_id == found.def_id => - { - Some(self.try_report_placeholders_trait( - Some(self.tcx().mk_region(ty::ReVar(*vid))), - cause, - Some(sub_placeholder), - None, - expected.def_id, - expected.substs, - found.substs, - )) - } + )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + Some(self.tcx().mk_region(ty::ReVar(*vid))), + cause, + Some(sub_placeholder), + None, + expected.def_id, + expected.substs, + found.substs, + )), Some(RegionResolutionError::SubSupConflict( vid, @@ -82,19 +74,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { _, _, sup_placeholder @ ty::RePlaceholder(_), - )) - if expected.def_id == found.def_id => - { - Some(self.try_report_placeholders_trait( - Some(self.tcx().mk_region(ty::ReVar(*vid))), - cause, - None, - Some(*sup_placeholder), - expected.def_id, - expected.substs, - found.substs, - )) - } + )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + Some(self.tcx().mk_region(ty::ReVar(*vid))), + cause, + None, + Some(*sup_placeholder), + expected.def_id, + expected.substs, + found.substs, + )), Some(RegionResolutionError::SubSupConflict( vid, @@ -106,19 +94,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { values: ValuePairs::TraitRefs(ExpectedFound { expected, found }), }), sup_placeholder @ ty::RePlaceholder(_), - )) - if expected.def_id == found.def_id => - { - Some(self.try_report_placeholders_trait( - Some(self.tcx().mk_region(ty::ReVar(*vid))), - cause, - None, - Some(*sup_placeholder), - expected.def_id, - expected.substs, - found.substs, - )) - } + )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + Some(self.tcx().mk_region(ty::ReVar(*vid))), + cause, + None, + Some(*sup_placeholder), + expected.def_id, + expected.substs, + found.substs, + )), Some(RegionResolutionError::ConcreteFailure( SubregionOrigin::Subtype(TypeTrace { @@ -127,19 +111,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { }), sub_region @ ty::RePlaceholder(_), sup_region @ ty::RePlaceholder(_), - )) - if expected.def_id == found.def_id => - { - Some(self.try_report_placeholders_trait( - None, - cause, - Some(*sub_region), - Some(*sup_region), - expected.def_id, - expected.substs, - found.substs, - )) - } + )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + None, + cause, + Some(*sub_region), + Some(*sup_region), + expected.def_id, + expected.substs, + found.substs, + )), Some(RegionResolutionError::ConcreteFailure( SubregionOrigin::Subtype(TypeTrace { @@ -148,19 +128,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { }), sub_region @ ty::RePlaceholder(_), sup_region, - )) - if expected.def_id == found.def_id => - { - Some(self.try_report_placeholders_trait( - Some(sup_region), - cause, - Some(*sub_region), - None, - expected.def_id, - expected.substs, - found.substs, - )) - } + )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + Some(sup_region), + cause, + Some(*sub_region), + None, + expected.def_id, + expected.substs, + found.substs, + )), Some(RegionResolutionError::ConcreteFailure( SubregionOrigin::Subtype(TypeTrace { @@ -169,19 +145,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { }), sub_region, sup_region @ ty::RePlaceholder(_), - )) - if expected.def_id == found.def_id => - { - Some(self.try_report_placeholders_trait( - Some(sub_region), - cause, - None, - Some(*sup_region), - expected.def_id, - expected.substs, - found.substs, - )) - } + )) if expected.def_id == found.def_id => Some(self.try_report_placeholders_trait( + Some(sub_region), + cause, + None, + Some(*sup_region), + expected.def_id, + expected.substs, + found.substs, + )), _ => None, } @@ -206,14 +178,16 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { expected_substs: &'tcx Substs<'tcx>, actual_substs: &'tcx Substs<'tcx>, ) -> ErrorReported { - debug!("try_report_placeholders_trait(\ - vid={:?}, \ - sub_placeholder={:?}, \ - sup_placeholder={:?}, \ - trait_def_id={:?}, \ - expected_substs={:?}, \ - actual_substs={:?})", - vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs); + debug!( + "try_report_placeholders_trait(\ + vid={:?}, \ + sub_placeholder={:?}, \ + sup_placeholder={:?}, \ + trait_def_id={:?}, \ + expected_substs={:?}, \ + actual_substs={:?})", + vid, sub_placeholder, sup_placeholder, trait_def_id, expected_substs, actual_substs + ); let mut err = self.tcx().sess.struct_span_err( cause.span(&self.tcx()), @@ -233,18 +207,14 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { _ => (), } - let expected_trait_ref = self.infcx.resolve_type_vars_if_possible( - &ty::TraitRef { - def_id: trait_def_id, - substs: expected_substs, - } - ); - let actual_trait_ref = self.infcx.resolve_type_vars_if_possible( - &ty::TraitRef { - def_id: trait_def_id, - substs: actual_substs, - } - ); + let expected_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef { + def_id: trait_def_id, + substs: expected_substs, + }); + let actual_trait_ref = self.infcx.resolve_type_vars_if_possible(&ty::TraitRef { + def_id: trait_def_id, + substs: actual_substs, + }); // Search the expected and actual trait references to see (a) // whether the sub/sup placeholders appear in them (sometimes @@ -285,11 +255,20 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { .tcx() .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid); - debug!("try_report_placeholders_trait: actual_has_vid={:?}", actual_has_vid); - debug!("try_report_placeholders_trait: expected_has_vid={:?}", expected_has_vid); + debug!( + "try_report_placeholders_trait: actual_has_vid={:?}", + actual_has_vid + ); + debug!( + "try_report_placeholders_trait: expected_has_vid={:?}", + expected_has_vid + ); debug!("try_report_placeholders_trait: has_sub={:?}", has_sub); debug!("try_report_placeholders_trait: has_sup={:?}", has_sup); - debug!("try_report_placeholders_trait: self_ty_has_vid={:?}", self_ty_has_vid); + debug!( + "try_report_placeholders_trait: self_ty_has_vid={:?}", + self_ty_has_vid + ); RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || { RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { @@ -297,7 +276,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { (Some(n1), Some(n2)) => { err.note(&format!( "`{}` would have to be implemented for the type `{}`, \ - for any two lifetimes `'{}` and `'{}`", + for any two lifetimes `'{}` and `'{}`", expected_trait_ref, expected_trait_ref.self_ty(), std::cmp::min(n1, n2), @@ -307,32 +286,46 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { (Some(n), _) | (_, Some(n)) => { err.note(&format!( "`{}` would have to be implemented for the type `{}`, \ - for any lifetime `'{}`", + for any lifetime `'{}`", expected_trait_ref, expected_trait_ref.self_ty(), n, )); } - (None, None) => { - err.note(&format!( - "`{}` would have to be implemented for the type `{}`", - expected_trait_ref, - expected_trait_ref.self_ty(), - )); - } + (None, None) => RegionHighlightMode::maybe_highlighting_region( + vid, + expected_has_vid, + || { + if let Some(n) = expected_has_vid { + err.note(&format!( + "`{}` would have to be implemented for the type `{}`, \ + for some specific lifetime `'{}`", + expected_trait_ref, + expected_trait_ref.self_ty(), + n, + )); + } else { + err.note(&format!( + "`{}` would have to be implemented for the type `{}`", + expected_trait_ref, + expected_trait_ref.self_ty(), + )); + } + }, + ), } }) }); RegionHighlightMode::maybe_highlighting_region( vid, - actual_has_vid.or(expected_has_vid), + actual_has_vid, || match actual_has_vid { Some(n) => { if self_ty_has_vid { err.note(&format!( "but `{}` is actually implemented for the type `{}`, \ - for the specific lifetime `'{}`", + for the specific lifetime `'{}`", actual_trait_ref, actual_trait_ref.self_ty(), n @@ -340,7 +333,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { } else { err.note(&format!( "but `{}` is actually implemented for the type `{}`, \ - for some lifetime `'{}`", + for some lifetime `'{}`", actual_trait_ref, actual_trait_ref.self_ty(), n @@ -355,7 +348,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { actual_trait_ref.self_ty(), )); } - } + }, ); err.emit(); diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index d7886e5af271..06946bcf744a 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -1,20 +1,11 @@ error: implementation of `Trait` is not general enough - --> $DIR/issue-57362.rs:20:7 + --> $DIR/issue-57362-1.rs:20:7 | LL | a.f(); //~ ERROR not general enough | ^ | - = note: `Trait` would have to be implemented for the type `fn(&u8)` + = note: `Trait` would have to be implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0` = note: but `Trait` is actually implemented for the type `for<'r> fn(&'r u8)` -error: implementation of `X` is not general enough - --> $DIR/issue-57362.rs:38:13 - | -LL | let x = ::make_g(); //~ ERROR not general enough - | ^^^^^^^^^^^^^^^^^^ - | - = note: `X` would have to be implemented for the type `for<'r> fn(&'r ())` - = note: but `X` is actually implemented for the type `fn(&'0 ())`, for the specific lifetime `'0` - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr new file mode 100644 index 000000000000..782c78da3a22 --- /dev/null +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -0,0 +1,11 @@ +error: implementation of `X` is not general enough + --> $DIR/issue-57362-2.rs:22:13 + | +LL | let x = ::make_g(); //~ ERROR not general enough + | ^^^^^^^^^^^^^^^^^^ + | + = note: `X` would have to be implemented for the type `for<'r> fn(&'r ())` + = note: but `X` is actually implemented for the type `fn(&'0 ())`, for the specific lifetime `'0` + +error: aborting due to previous error + From 790ed9128ad301806621901e8d82e1d6d21cbff2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 25 Jan 2019 15:43:36 -0500 Subject: [PATCH 11/16] comment the pattern --- .../nice_region_error/placeholder_error.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index f5c51f8ee260..a0ce250d7e97 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -270,6 +270,21 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { self_ty_has_vid ); + // The weird thing here with the `maybe_highlighting_region` calls and the + // the match inside is meant to be like this: + // + // - The match checks whether the given things (placeholders, etc) appear + // in the types are about to print + // - Meanwhile, the `maybe_highlighting_region` calls set up + // highlights so that, if they do appear, we will replace + // them `'0` and whatever. (This replacement takes place + // inside the closure given to `maybe_highlighting_region`.) + // + // There is some duplication between the calls -- i.e., the + // `maybe_highlighting_region` checks if (e.g.) `has_sub` is + // None, an then we check again inside the closure, but this + // setup sort of minimized the number of calls and so form. + RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || { RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { match (has_sub, has_sup) { From 1730ad4d1cbb703be970f8494ec349bf2c38e3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81my=20Rakic?= Date: Fri, 25 Jan 2019 23:37:56 +0100 Subject: [PATCH 12/16] Fix issue-57362-1.rs attributes --- src/test/ui/issues/issue-57362-1.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/test/ui/issues/issue-57362-1.rs diff --git a/src/test/ui/issues/issue-57362-1.rs b/src/test/ui/issues/issue-57362-1.rs old mode 100755 new mode 100644 From 489bc4a2c6ec47eb35dc066247e11f335b278333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81my=20Rakic?= Date: Sat, 26 Jan 2019 20:25:36 +0100 Subject: [PATCH 13/16] When mentioning lifetimes, put either the trait ref or the self type closer to the lifetimes When mentioning lifetimes, only invert wording between the expected trait and the self type when the self type has the vid. This way, the lifetimes always stay close to the self type or trait ref that actually contains them. --- .../nice_region_error/placeholder_error.rs | 89 +++++++++++++------ .../associated-types-eq-hr.stderr | 12 +-- .../ui/hrtb/hrtb-cache-issue-54302.stderr | 4 +- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 4 +- .../hrtb-exists-forall-trait-invariant.stderr | 4 +- src/test/ui/hrtb/hrtb-just-for-static.stderr | 4 +- .../ui/hrtb/hrtb-perfect-forwarding.stderr | 4 +- src/test/ui/issues/issue-54302.stderr | 4 +- 8 files changed, 81 insertions(+), 44 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index a0ce250d7e97..391539b77bc4 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -251,10 +251,16 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { } }); - let self_ty_has_vid = self + let actual_self_ty_has_vid = self .tcx() .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid); + let expected_self_ty_has_vid = self + .tcx() + .any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid); + + let self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid; + debug!( "try_report_placeholders_trait: actual_has_vid={:?}", actual_has_vid @@ -266,8 +272,12 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { debug!("try_report_placeholders_trait: has_sub={:?}", has_sub); debug!("try_report_placeholders_trait: has_sup={:?}", has_sup); debug!( - "try_report_placeholders_trait: self_ty_has_vid={:?}", - self_ty_has_vid + "try_report_placeholders_trait: actual_self_ty_has_vid={:?}", + actual_self_ty_has_vid + ); + debug!( + "try_report_placeholders_trait: expected_self_ty_has_vid={:?}", + expected_self_ty_has_vid ); // The weird thing here with the `maybe_highlighting_region` calls and the @@ -289,23 +299,43 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { match (has_sub, has_sup) { (Some(n1), Some(n2)) => { - err.note(&format!( - "`{}` would have to be implemented for the type `{}`, \ - for any two lifetimes `'{}` and `'{}`", - expected_trait_ref, - expected_trait_ref.self_ty(), - std::cmp::min(n1, n2), - std::cmp::max(n1, n2), - )); + if self_ty_has_vid { + err.note(&format!( + "`{}` would have to be implemented for the type `{}`, \ + for any two lifetimes `'{}` and `'{}`", + expected_trait_ref, + expected_trait_ref.self_ty(), + std::cmp::min(n1, n2), + std::cmp::max(n1, n2), + )); + } else { + err.note(&format!( + "`{}` must implement `{}`, \ + for any two lifetimes `'{}` and `'{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + std::cmp::min(n1, n2), + std::cmp::max(n1, n2), + )); + } } (Some(n), _) | (_, Some(n)) => { - err.note(&format!( - "`{}` would have to be implemented for the type `{}`, \ - for any lifetime `'{}`", - expected_trait_ref, - expected_trait_ref.self_ty(), - n, - )); + if self_ty_has_vid { + err.note(&format!( + "`{}` would have to be implemented for the type `{}`, \ + for any lifetime `'{}`", + expected_trait_ref, + expected_trait_ref.self_ty(), + n, + )); + } else { + err.note(&format!( + "`{}` must implement `{}`, for any lifetime `'{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + n, + )); + } } (None, None) => RegionHighlightMode::maybe_highlighting_region( vid, @@ -320,11 +350,19 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { n, )); } else { - err.note(&format!( - "`{}` would have to be implemented for the type `{}`", - expected_trait_ref, - expected_trait_ref.self_ty(), - )); + if self_ty_has_vid { + err.note(&format!( + "`{}` would have to be implemented for the type `{}`", + expected_trait_ref, + expected_trait_ref.self_ty(), + )); + } else { + err.note(&format!( + "`{}` must implement `{}`", + expected_trait_ref.self_ty(), + expected_trait_ref, + )); + } } }, ), @@ -347,10 +385,9 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { )); } else { err.note(&format!( - "but `{}` is actually implemented for the type `{}`, \ - for some lifetime `'{}`", - actual_trait_ref, + "but `{}` actually implements `{}`, for some lifetime `'{}`", actual_trait_ref.self_ty(), + actual_trait_ref, n )); } diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 0e471a78d9ed..5a074fe34573 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -41,8 +41,8 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `tuple_one`, - = note: `TheTrait<(&'0 isize, &'1 isize)>` would have to be implemented for the type `Tuple`, for any two lifetimes `'0` and `'1` - = note: but `TheTrait<(&'2 isize, &'2 isize)>` is actually implemented for the type `Tuple`, for some lifetime `'2` + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1` + = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 @@ -51,8 +51,8 @@ LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `tuple_two`, - = note: `TheTrait<(&'0 isize, &'1 isize)>` would have to be implemented for the type `Tuple`, for any two lifetimes `'0` and `'1` - = note: but `TheTrait<(&'2 isize, &'2 isize)>` is actually implemented for the type `Tuple`, for some lifetime `'2` + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1` + = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:105:5 @@ -61,8 +61,8 @@ LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `tuple_four`, - = note: `TheTrait<(&'0 isize, &'1 isize)>` would have to be implemented for the type `Tuple`, for any two lifetimes `'0` and `'1` - = note: but `TheTrait<(&'2 isize, &'2 isize)>` is actually implemented for the type `Tuple`, for some lifetime `'2` + = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1` + = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some lifetime `'2` error: aborting due to 5 previous errors diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr index 1aa0a7ca32bd..d0bcebeac4f7 100644 --- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -4,8 +4,8 @@ error: implementation of `Deserialize` is not general enough LL | assert_deserialize_owned::<&'static str>(); //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Deserialize<'0>` would have to be implemented for the type `&'static str`, for any lifetime `'0` - = note: but `Deserialize<'1>` is actually implemented for the type `&str`, for some lifetime `'1` + = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` + = note: but `&str` actually implements `Deserialize<'1>`, for some lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index 4c4f79798804..aa91314b350a 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -5,8 +5,8 @@ LL | fn b() { want_foo2::(); } //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `want_foo2`, - = note: `Foo<(&'0 isize, &'1 isize)>` would have to be implemented for the type `SomeStruct`, for any two lifetimes `'0` and `'1` - = note: but `Foo<(&'2 isize, &'2 isize)>` is actually implemented for the type `SomeStruct`, for some lifetime `'2` + = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1` + = note: but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some lifetime `'2` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 916a524939b6..91b5db6cd664 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -5,8 +5,8 @@ LL | foo::<()>(); //~ ERROR not general enough | ^^^^^^^^^ | = note: Due to a where-clause on `foo`, - = note: `Trait fn(std::cell::Cell<&'b u32>)>` would have to be implemented for the type `()` - = note: but `Trait)>` is actually implemented for the type `()`, for some lifetime `'0` + = note: `()` must implement `Trait fn(std::cell::Cell<&'b u32>)>` + = note: but `()` actually implements `Trait)>`, for some lifetime `'0` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index bd6e3dbebd2f..24edcd910764 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -5,8 +5,8 @@ LL | want_hrtb::() //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `want_hrtb`, - = note: `Foo<&'0 isize>` would have to be implemented for the type `StaticInt`, for any lifetime `'0` - = note: but `Foo<&'1 isize>` is actually implemented for the type `StaticInt`, for some lifetime `'1` + = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0` + = note: but `StaticInt` actually implements `Foo<&'1 isize>`, for some lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index 8b71a8a800e5..a87fa6d3012d 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -5,8 +5,8 @@ LL | foo_hrtb_bar_not(&mut t); //~ ERROR not general enough | ^^^^^^^^^^^^^^^^ | = note: Due to a where-clause on `foo_hrtb_bar_not`, - = note: `Foo<&'0 isize>` would have to be implemented for the type `&mut T`, for any lifetime `'0` - = note: but `Foo<&'1 isize>` is actually implemented for the type `&mut T`, for some lifetime `'1` + = note: `&mut T` must implement `Foo<&'0 isize>`, for any lifetime `'0` + = note: but `&mut T` actually implements `Foo<&'1 isize>`, for some lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr index ddf0414faf63..442d32eb9f1e 100644 --- a/src/test/ui/issues/issue-54302.stderr +++ b/src/test/ui/issues/issue-54302.stderr @@ -4,8 +4,8 @@ error: implementation of `Deserialize` is not general enough LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Deserialize<'0>` would have to be implemented for the type `&'static str`, for any lifetime `'0` - = note: but `Deserialize<'1>` is actually implemented for the type `&str`, for some lifetime `'1` + = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` + = note: but `&str` actually implements `Deserialize<'1>`, for some lifetime `'1` error: aborting due to previous error From 43c0518d5b004f4096e5c3cf3e302322988adcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81my=20Rakic?= Date: Sat, 26 Jan 2019 21:32:09 +0100 Subject: [PATCH 14/16] Extract the notes explaining the placeholder region errors to a helper fn --- .../nice_region_error/placeholder_error.rs | 51 ++++++++++++++++--- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 391539b77bc4..21d6c562e4dc 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -1,3 +1,4 @@ +use errors::DiagnosticBuilder; use hir::def_id::DefId; use infer::error_reporting::nice_region_error::NiceRegionError; use infer::lexical_region_resolve::RegionResolutionError; @@ -259,7 +260,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { .tcx() .any_free_region_meets(&expected_trait_ref.self_ty(), |r| Some(r) == vid); - let self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid; + let any_self_ty_has_vid = actual_self_ty_has_vid || expected_self_ty_has_vid; debug!( "try_report_placeholders_trait: actual_has_vid={:?}", @@ -280,6 +281,43 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { expected_self_ty_has_vid ); + self.explain_actual_impl_that_was_found( + &mut err, + sub_placeholder, + sup_placeholder, + has_sub, + has_sup, + expected_trait_ref, + actual_trait_ref, + vid, + expected_has_vid, + actual_has_vid, + any_self_ty_has_vid, + ); + + err.emit(); + ErrorReported + } + + /// Add notes with details about the expected and actual trait refs, with attention to cases + /// when placeholder regions are involved: either the trait or the self type containing + /// them needs to be mentioned the closest to the placeholders. + /// This makes the error messages read better, however at the cost of some complexity + /// due to the number of combinations we have to deal with. + fn explain_actual_impl_that_was_found( + &self, + err: &mut DiagnosticBuilder<'_>, + sub_placeholder: Option>, + sup_placeholder: Option>, + has_sub: Option, + has_sup: Option, + expected_trait_ref: ty::TraitRef<'_>, + actual_trait_ref: ty::TraitRef<'_>, + vid: Option>, + expected_has_vid: Option, + actual_has_vid: Option, + any_self_ty_has_vid: bool, + ) { // The weird thing here with the `maybe_highlighting_region` calls and the // the match inside is meant to be like this: // @@ -299,7 +337,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { match (has_sub, has_sup) { (Some(n1), Some(n2)) => { - if self_ty_has_vid { + if any_self_ty_has_vid { err.note(&format!( "`{}` would have to be implemented for the type `{}`, \ for any two lifetimes `'{}` and `'{}`", @@ -320,7 +358,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { } } (Some(n), _) | (_, Some(n)) => { - if self_ty_has_vid { + if any_self_ty_has_vid { err.note(&format!( "`{}` would have to be implemented for the type `{}`, \ for any lifetime `'{}`", @@ -350,7 +388,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { n, )); } else { - if self_ty_has_vid { + if any_self_ty_has_vid { err.note(&format!( "`{}` would have to be implemented for the type `{}`", expected_trait_ref, @@ -375,7 +413,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { actual_has_vid, || match actual_has_vid { Some(n) => { - if self_ty_has_vid { + if any_self_ty_has_vid { err.note(&format!( "but `{}` is actually implemented for the type `{}`, \ for the specific lifetime `'{}`", @@ -402,8 +440,5 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { } }, ); - - err.emit(); - ErrorReported } } From e077501b54f175b3cd9947dd032a55196fb6d989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81my=20Rakic?= Date: Sat, 26 Jan 2019 21:39:47 +0100 Subject: [PATCH 15/16] Fix stray typo --- .../error_reporting/nice_region_error/placeholder_error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 21d6c562e4dc..98458796ef4d 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -13,7 +13,7 @@ use util::ppaux::RegionHighlightMode; impl NiceRegionError<'me, 'gcx, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and - /// an anonymous region, emit an descriptive diagnostic error. + /// an anonymous region, emit a descriptive diagnostic error. pub(super) fn try_report_placeholder_conflict(&self) -> Option { match &self.error { /////////////////////////////////////////////////////////////////////////// From c97d13545290c559ac93442ea6dc6a93545302fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81my=20Rakic?= Date: Mon, 28 Jan 2019 23:12:13 +0100 Subject: [PATCH 16/16] Refer to synthetically named lifetimes as "some specific lifetime" rather than "the specific lifetime" --- .../nice_region_error/placeholder_error.rs | 4 ++-- .../ui/associated-types/associated-types-eq-hr.stderr | 6 +++--- .../associated-types/higher-ranked-projection.bad.stderr | 2 +- src/test/ui/generator/auto-trait-regions.stderr | 4 ++-- src/test/ui/hrtb/hrtb-cache-issue-54302.stderr | 2 +- src/test/ui/hrtb/hrtb-conflate-regions.stderr | 2 +- .../ui/hrtb/hrtb-exists-forall-trait-invariant.stderr | 2 +- src/test/ui/hrtb/hrtb-just-for-static.stderr | 4 ++-- src/test/ui/hrtb/hrtb-perfect-forwarding.stderr | 2 +- src/test/ui/issues/issue-54302-cases.stderr | 8 ++++---- src/test/ui/issues/issue-54302.stderr | 2 +- src/test/ui/issues/issue-57362-2.stderr | 2 +- src/test/ui/where-clauses/where-for-self-2.stderr | 2 +- 13 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 98458796ef4d..ebac5a0c2a69 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -416,14 +416,14 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { if any_self_ty_has_vid { err.note(&format!( "but `{}` is actually implemented for the type `{}`, \ - for the specific lifetime `'{}`", + for some specific lifetime `'{}`", actual_trait_ref, actual_trait_ref.self_ty(), n )); } else { err.note(&format!( - "but `{}` actually implements `{}`, for some lifetime `'{}`", + "but `{}` actually implements `{}`, for some specific lifetime `'{}`", actual_trait_ref.self_ty(), actual_trait_ref, n diff --git a/src/test/ui/associated-types/associated-types-eq-hr.stderr b/src/test/ui/associated-types/associated-types-eq-hr.stderr index 5a074fe34573..5299ebbb1ba8 100644 --- a/src/test/ui/associated-types/associated-types-eq-hr.stderr +++ b/src/test/ui/associated-types/associated-types-eq-hr.stderr @@ -42,7 +42,7 @@ LL | tuple_one::(); | = note: Due to a where-clause on `tuple_one`, = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1` - = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some lifetime `'2` + = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 @@ -52,7 +52,7 @@ LL | tuple_two::(); | = note: Due to a where-clause on `tuple_two`, = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1` - = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some lifetime `'2` + = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:105:5 @@ -62,7 +62,7 @@ LL | tuple_four::(); | = note: Due to a where-clause on `tuple_four`, = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1` - = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some lifetime `'2` + = note: but `Tuple` actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors diff --git a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr index 69fa1ce30aa8..3bbf48cb37f5 100644 --- a/src/test/ui/associated-types/higher-ranked-projection.bad.stderr +++ b/src/test/ui/associated-types/higher-ranked-projection.bad.stderr @@ -6,7 +6,7 @@ LL | foo(()); | = note: Due to a where-clause on `foo`, = note: `Mirror` would have to be implemented for the type `&'0 ()`, for any lifetime `'0` - = note: but `Mirror` is actually implemented for the type `&'1 ()`, for the specific lifetime `'1` + = note: but `Mirror` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 680a7bbc50e5..92f92e2a32a3 100644 --- a/src/test/ui/generator/auto-trait-regions.stderr +++ b/src/test/ui/generator/auto-trait-regions.stderr @@ -5,7 +5,7 @@ LL | assert_foo(gen); | ^^^^^^^^^^ | = note: `Foo` would have to be implemented for the type `&'0 OnlyFooIfStaticRef`, for any lifetime `'0` - = note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for the specific lifetime `'1` + = note: but `Foo` is actually implemented for the type `&'1 OnlyFooIfStaticRef`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:48:5 @@ -14,7 +14,7 @@ LL | assert_foo(gen); | ^^^^^^^^^^ | = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1` - = note: but `Foo` is actually implemented for the type `A<'_, '2>`, for the specific lifetime `'2` + = note: but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr index d0bcebeac4f7..21d154eb2316 100644 --- a/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr +++ b/src/test/ui/hrtb/hrtb-cache-issue-54302.stderr @@ -5,7 +5,7 @@ LL | assert_deserialize_owned::<&'static str>(); //~ ERROR | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` - = note: but `&str` actually implements `Deserialize<'1>`, for some lifetime `'1` + = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-conflate-regions.stderr b/src/test/ui/hrtb/hrtb-conflate-regions.stderr index aa91314b350a..630dda2694fd 100644 --- a/src/test/ui/hrtb/hrtb-conflate-regions.stderr +++ b/src/test/ui/hrtb/hrtb-conflate-regions.stderr @@ -6,7 +6,7 @@ LL | fn b() { want_foo2::(); } //~ ERROR | = note: Due to a where-clause on `want_foo2`, = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1` - = note: but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some lifetime `'2` + = note: but `SomeStruct` actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr index 91b5db6cd664..a44837a1e26f 100644 --- a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr +++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr @@ -6,7 +6,7 @@ LL | foo::<()>(); //~ ERROR not general enough | = note: Due to a where-clause on `foo`, = note: `()` must implement `Trait fn(std::cell::Cell<&'b u32>)>` - = note: but `()` actually implements `Trait)>`, for some lifetime `'0` + = note: but `()` actually implements `Trait)>`, for some specific lifetime `'0` error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-just-for-static.stderr b/src/test/ui/hrtb/hrtb-just-for-static.stderr index 24edcd910764..99c87f13672b 100644 --- a/src/test/ui/hrtb/hrtb-just-for-static.stderr +++ b/src/test/ui/hrtb/hrtb-just-for-static.stderr @@ -6,7 +6,7 @@ LL | want_hrtb::() //~ ERROR | = note: Due to a where-clause on `want_hrtb`, = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0` - = note: but `StaticInt` actually implements `Foo<&'1 isize>`, for some lifetime `'1` + = note: but `StaticInt` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:30:5 @@ -16,7 +16,7 @@ LL | want_hrtb::<&'a u32>() //~ ERROR | = note: Due to a where-clause on `want_hrtb`, = note: `Foo<&'0 isize>` would have to be implemented for the type `&'a u32`, for any lifetime `'0` - = note: but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for the specific lifetime `'1` + = note: but `Foo<&'1 isize>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index a87fa6d3012d..c7be3790aa1c 100644 --- a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr +++ b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr @@ -6,7 +6,7 @@ LL | foo_hrtb_bar_not(&mut t); //~ ERROR not general enough | = note: Due to a where-clause on `foo_hrtb_bar_not`, = note: `&mut T` must implement `Foo<&'0 isize>`, for any lifetime `'0` - = note: but `&mut T` actually implements `Foo<&'1 isize>`, for some lifetime `'1` + = note: but `&mut T` actually implements `Foo<&'1 isize>`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index 377bac3b2452..98637611b79f 100644 --- a/src/test/ui/issues/issue-54302-cases.stderr +++ b/src/test/ui/issues/issue-54302-cases.stderr @@ -5,7 +5,7 @@ LL | >::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0` - = note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for the specific lifetime `'1` + = note: but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 @@ -14,7 +14,7 @@ LL | >::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0` - = note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for the specific lifetime `'1` + = note: but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 @@ -23,7 +23,7 @@ LL | >::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0` - = note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for the specific lifetime `'1` + = note: but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 @@ -32,7 +32,7 @@ LL | >::ref_foo(a) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0` - = note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for the specific lifetime `'1` + = note: but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-54302.stderr b/src/test/ui/issues/issue-54302.stderr index 442d32eb9f1e..c6d0805f3ab2 100644 --- a/src/test/ui/issues/issue-54302.stderr +++ b/src/test/ui/issues/issue-54302.stderr @@ -5,7 +5,7 @@ LL | assert_deserialize_owned::<&'static str>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` - = note: but `&str` actually implements `Deserialize<'1>`, for some lifetime `'1` + = note: but `&str` actually implements `Deserialize<'1>`, for some specific lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 782c78da3a22..14b7f52bb879 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -5,7 +5,7 @@ LL | let x = ::make_g(); //~ ERROR not general enough | ^^^^^^^^^^^^^^^^^^ | = note: `X` would have to be implemented for the type `for<'r> fn(&'r ())` - = note: but `X` is actually implemented for the type `fn(&'0 ())`, for the specific lifetime `'0` + = note: but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-for-self-2.stderr b/src/test/ui/where-clauses/where-for-self-2.stderr index 4d827e6ce4fd..342cabfd6bf0 100644 --- a/src/test/ui/where-clauses/where-for-self-2.stderr +++ b/src/test/ui/where-clauses/where-for-self-2.stderr @@ -6,7 +6,7 @@ LL | foo(&X); //~ ERROR implementation of `Bar` is not general enough | = note: Due to a where-clause on `foo`, = note: `Bar` would have to be implemented for the type `&'0 u32`, for any lifetime `'0` - = note: but `Bar` is actually implemented for the type `&'1 u32`, for the specific lifetime `'1` + = note: but `Bar` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to previous error