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 bfb5b61d0aa1f..8be49b2792441 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 d230ce55471e9..eeaa01375ed4d 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 f7ba546fa7f3b..d34b71c33f4b4 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 918a46aacd041..05333f4337336 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 c4c71037d8b35..cbd36a8b2db8a 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 0dda636a9bd53..ebac5a0c2a69e 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; @@ -12,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 { /////////////////////////////////////////////////////////////////////////// @@ -34,19 +35,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 +55,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 +75,35 @@ 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))), + )) 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, + _, + _, + _, + SubregionOrigin::Subtype(TypeTrace { cause, - None, - Some(*sup_placeholder), - expected.def_id, - expected.substs, - found.substs, - )) - } + 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 { @@ -103,19 +112,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 { @@ -124,19 +129,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 { @@ -145,19 +146,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, } @@ -182,11 +179,22 @@ 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), + 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!( "implementation of `{}` is not general enough", - self.tcx.item_path_str(trait_def_id), + self.tcx().item_path_str(trait_def_id), ), ); @@ -194,20 +202,20 @@ 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), )); } _ => (), } - let expected_trait_ref = ty::TraitRef { + 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 = ty::TraitRef { + }); + 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 @@ -218,9 +226,11 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { let mut counter = 0; let mut has_sub = None; let mut has_sup = None; - let mut has_vid = None; - self.tcx.for_each_free_region(&expected_trait_ref, |r| { + 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() { has_sub = Some(counter); counter += 1; @@ -228,80 +238,207 @@ 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); + self.tcx().for_each_free_region(&actual_trait_ref, |r| { + if Some(r) == vid && actual_has_vid.is_none() { + actual_has_vid = Some(counter); counter += 1; } }); - let self_ty_has_vid = self - .tcx + 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 any_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 + ); + 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: 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 + ); + + 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: + // + // - 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) { (Some(n1), Some(n2)) => { - 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), - )); + if any_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)) => { + if any_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, + 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 { + if any_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, + )); + } + } + }, + ), + } + }) + }); + + RegionHighlightMode::maybe_highlighting_region( + vid, + actual_has_vid, + || match actual_has_vid { + Some(n) => { + if any_self_ty_has_vid { err.note(&format!( - "`{}` must implement `{}` \ - for any lifetime `'{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - n, + "but `{}` is actually implemented for the type `{}`, \ + for some specific lifetime `'{}`", + actual_trait_ref, + actual_trait_ref.self_ty(), + n )); - } - (None, None) => { + } else { err.note(&format!( - "`{}` must implement `{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, + "but `{}` actually implements `{}`, for some specific lifetime `'{}`", + actual_trait_ref.self_ty(), + actual_trait_ref, + n )); } } - }) - }); - RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid { - Some(n) => { - if self_ty_has_vid { + _ => { 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 + }, + ); } } 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 7501e2f210888..4331518d403dd 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 43590a606ae90..dd8a33829eb53 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 f07880075c100..ec68ddaf3c852 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; } 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 d3eaa894b5043..5299ebbb1ba8a 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: `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 specific 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: `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 specific 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: `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 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 e4704494e1492..3bbf48cb37f58 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 some 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 db15ec51d87c6..c5c8451a5a9db 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/associated-types/higher-ranked-projection.rs b/src/test/ui/associated-types/higher-ranked-projection.rs index 5b380c982f041..1280c8cb4cb09 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/generator/auto-trait-regions.stderr b/src/test/ui/generator/auto-trait-regions.stderr index 1b4dfe2df1c0c..92f92e2a32a36 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 some 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 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 e82fa51524ef1..21d154eb2316c 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: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` + = 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 2ee398e3dd3b2..630dda2694fde 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: `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 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 6a61181e2407c..a44837a1e26fd 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 `()` only 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 094c449802415..99c87f13672b1 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: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0` + = 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 @@ -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 some specific lifetime `'1` error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.rs b/src/test/ui/hrtb/hrtb-perfect-forwarding.rs index 7bd89960e42e5..0094091c6bd76 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) diff --git a/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr b/src/test/ui/hrtb/hrtb-perfect-forwarding.stderr index ec3bf8a1a1be3..c7be3790aa1c8 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: `&mut T` must implement `Foo<&'0 isize>`, for any lifetime `'0` + = note: but `&mut T` actually implements `Foo<&'1 isize>`, for some 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/issues/issue-54302-cases.stderr b/src/test/ui/issues/issue-54302-cases.stderr index c1329d331a181..98637611b79fe 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 some 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 some 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 some 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 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 1b255204b6ef7..c6d0805f3ab2a 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: `&'static str` must implement `Deserialize<'0>`, for any lifetime `'0` + = 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-1.rs b/src/test/ui/issues/issue-57362-1.rs new file mode 100644 index 0000000000000..fe6b69f00977d --- /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-1.stderr b/src/test/ui/issues/issue-57362-1.stderr new file mode 100644 index 0000000000000..06946bcf744a7 --- /dev/null +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -0,0 +1,11 @@ +error: implementation of `Trait` is not general enough + --> $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(&'0 u8)`, for some specific lifetime `'0` + = note: but `Trait` is actually implemented for the type `for<'r> fn(&'r u8)` + +error: aborting due to previous error + diff --git a/src/test/ui/issues/issue-57362-2.rs b/src/test/ui/issues/issue-57362-2.rs new file mode 100644 index 0000000000000..436a4a904576d --- /dev/null +++ b/src/test/ui/issues/issue-57362-2.rs @@ -0,0 +1,25 @@ +// 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` + +// 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() {} 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 0000000000000..14b7f52bb8799 --- /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 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 afc80bf4d8ee6..342cabfd6bf0a 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 some specific lifetime `'1` error: aborting due to previous error