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 bfb5b61d0aa..8be49b27924 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 d230ce55471..eeaa01375ed 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 f7ba546fa7f..d34b71c33f4 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 918a46aacd0..05333f43373 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 c4c71037d8b..cbd36a8b2db 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 0dda636a9bd..7ece3d38a7f 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 7501e2f2108..4331518d403 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 43590a606ae..dd8a33829eb 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 f07880075c1..ec68ddaf3c8 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 7ece3d38a7f..636b66bef01 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 636b66bef01..892c56bf834 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 892c56bf834..b5187d2dbb6 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 5b380c982f0..1280c8cb4cb 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 7bd89960e42..0094091c6bd 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 d3eaa894b50..0e471a78d9e 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 e4704494e14..69fa1ce30aa 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 db15ec51d87..c5c8451a5a9 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 1b4dfe2df1c..680a7bbc50e 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 e82fa51524e..1aa0a7ca32b 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 2ee398e3dd3..4c4f7979880 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 6a61181e240..916a524939b 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 094c4498024..bd6e3dbebd2 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 ec3bf8a1a1b..8b71a8a800e 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 c1329d331a1..377bac3b245 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 1b255204b6e..ddf0414faf6 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 afc80bf4d8e..4d827e6ce4f 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 00000000000..d5b506f3c2c --- /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 00000000000..d7886e5af27 --- /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 00000000000..fe6b69f0097 --- /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 d5b506f3c2c..436a4a90457 --- 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 b5187d2dbb6..94e20731bfe 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 94e20731bfe..f5c51f8ee26 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 d7886e5af27..06946bcf744 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 00000000000..782c78da3a2 --- /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 f5c51f8ee26..a0ce250d7e9 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 a0ce250d7e9..391539b77bc 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 0e471a78d9e..5a074fe3457 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 1aa0a7ca32b..d0bcebeac4f 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 4c4f7979880..aa91314b350 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 916a524939b..91b5db6cd66 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 bd6e3dbebd2..24edcd91076 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 8b71a8a800e..a87fa6d3012 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 ddf0414faf6..442d32eb9f1 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 391539b77bc..21d6c562e4d 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 21d6c562e4d..98458796ef4 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 98458796ef4..ebac5a0c2a6 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 5a074fe3457..5299ebbb1ba 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 69fa1ce30aa..3bbf48cb37f 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 680a7bbc50e..92f92e2a32a 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 d0bcebeac4f..21d154eb231 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 aa91314b350..630dda2694f 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 91b5db6cd66..a44837a1e26 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 24edcd91076..99c87f13672 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 a87fa6d3012..c7be3790aa1 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 377bac3b245..98637611b79 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 442d32eb9f1..c6d0805f3ab 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 782c78da3a2..14b7f52bb87 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 4d827e6ce4f..342cabfd6bf 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