Suggest copying trait associated type bounds on lifetime error
This commit is contained in:
parent
30b3f35c42
commit
3d19c8defd
12 changed files with 163 additions and 28 deletions
|
@ -64,7 +64,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
|
|||
.or_else(|| self.try_report_mismatched_static_lifetime())
|
||||
}
|
||||
|
||||
pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
|
||||
pub(super) fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
|
||||
match (&self.error, self.regions) {
|
||||
(Some(ConcreteFailure(origin, sub, sup)), None) => Some((origin.span(), *sub, *sup)),
|
||||
(Some(SubSupConflict(_, _, origin, sub, _, sup, _)), None) => {
|
||||
|
|
|
@ -102,6 +102,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
"...so that the definition in impl matches the definition from the trait",
|
||||
);
|
||||
}
|
||||
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
|
||||
self.note_region_origin(err, &parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,6 +348,55 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
trait_item_def_id,
|
||||
&format!("`{}: {}`", sup, sub),
|
||||
),
|
||||
infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
|
||||
let mut err = self.report_concrete_failure(*parent, sub, sup);
|
||||
|
||||
let trait_item_span = self.tcx.def_span(trait_item_def_id);
|
||||
let item_name = self.tcx.item_name(impl_item_def_id);
|
||||
err.span_label(
|
||||
trait_item_span,
|
||||
format!("definition of `{}` from trait", item_name),
|
||||
);
|
||||
|
||||
let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
|
||||
let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
|
||||
|
||||
let impl_predicates: rustc_data_structures::stable_set::FxHashSet<_> =
|
||||
impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
|
||||
let clauses: Vec<_> = trait_predicates
|
||||
.predicates
|
||||
.into_iter()
|
||||
.filter(|&(pred, _)| !impl_predicates.contains(pred))
|
||||
.map(|(pred, _)| format!("{}", pred))
|
||||
.collect();
|
||||
|
||||
if !clauses.is_empty() {
|
||||
let where_clause_span = self
|
||||
.tcx
|
||||
.hir()
|
||||
.get_generics(impl_item_def_id.expect_local())
|
||||
.unwrap()
|
||||
.where_clause
|
||||
.tail_span_for_suggestion();
|
||||
|
||||
let suggestion = format!(
|
||||
"{} {}",
|
||||
if !impl_predicates.is_empty() { "," } else { " where" },
|
||||
clauses.join(", "),
|
||||
);
|
||||
err.span_suggestion(
|
||||
where_clause_span,
|
||||
&format!(
|
||||
"try copying {} from the trait",
|
||||
if clauses.len() > 1 { "these clauses" } else { "this clause" }
|
||||
),
|
||||
suggestion,
|
||||
rustc_errors::Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -438,6 +438,13 @@ pub enum SubregionOrigin<'tcx> {
|
|||
/// Comparing the signature and requirements of an impl associated type
|
||||
/// against the containing trait
|
||||
CompareImplTypeObligation { span: Span, impl_item_def_id: DefId, trait_item_def_id: DefId },
|
||||
|
||||
/// Checking that the bounds of a trait's associated type hold for a given impl
|
||||
CheckAssociatedTypeBounds {
|
||||
parent: Box<SubregionOrigin<'tcx>>,
|
||||
impl_item_def_id: DefId,
|
||||
trait_item_def_id: DefId,
|
||||
},
|
||||
}
|
||||
|
||||
// `SubregionOrigin` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
|
@ -1832,6 +1839,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
|||
ReferenceOutlivesReferent(_, a) => a,
|
||||
CompareImplMethodObligation { span, .. } => span,
|
||||
CompareImplTypeObligation { span, .. } => span,
|
||||
CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1862,6 +1870,15 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
|||
trait_item_def_id,
|
||||
},
|
||||
|
||||
traits::ObligationCauseCode::CheckAssociatedTypeBounds {
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
} => SubregionOrigin::CheckAssociatedTypeBounds {
|
||||
impl_item_def_id,
|
||||
trait_item_def_id,
|
||||
parent: Box::new(default()),
|
||||
},
|
||||
|
||||
_ => default(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue