pub struct ConfirmResult<'tcx> {
pub callee: MethodCallee<'tcx>,
- pub illegal_sized_bound: bool,
+ pub illegal_sized_bound: Option<Span>,
}
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Add any trait/regions obligations specified on the method's type parameters.
// We won't add these if we encountered an illegal sized bound, so that we can use
// a custom error in that case.
- if !illegal_sized_bound {
+ if illegal_sized_bound.is_none() {
let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig));
self.add_obligations(method_ty, all_substs, &method_predicates);
}
fn predicates_require_illegal_sized_bound(
&self,
predicates: &ty::InstantiatedPredicates<'tcx>,
- ) -> bool {
+ ) -> Option<Span> {
let sized_def_id = match self.tcx.lang_items().sized_trait() {
Some(def_id) => def_id,
- None => return false,
+ None => return None,
};
traits::elaborate_predicates(self.tcx, predicates.predicates.clone())
.filter_map(|predicate| match predicate {
ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
- Some(trait_pred)
+ let span = predicates
+ .predicates
+ .iter()
+ .zip(predicates.spans.iter())
+ .filter_map(|(p, span)| if *p == predicate { Some(*span) } else { None })
+ .next()
+ .unwrap_or(rustc_span::DUMMY_SP);
+ Some((trait_pred, span))
}
_ => None,
})
- .any(|trait_pred| match trait_pred.skip_binder().self_ty().kind {
- ty::Dynamic(..) => true,
- _ => false,
+ .filter_map(|(trait_pred, span)| match trait_pred.skip_binder().self_ty().kind {
+ ty::Dynamic(..) => Some(span),
+ _ => None,
})
+ .next()
}
fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
// Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
// forgotten to import a trait.
- IllegalSizedBound(Vec<DefId>, bool),
+ IllegalSizedBound(Vec<DefId>, bool, Span),
// Found a match, but the return type is wrong
BadReturnType,
let result =
self.confirm_method(span, self_expr, call_expr, self_ty, pick.clone(), segment);
- if result.illegal_sized_bound {
+ if let Some(span) = result.illegal_sized_bound {
let mut needs_mut = false;
if let ty::Ref(region, t_type, mutability) = self_ty.kind {
let trait_type = self
_ => Vec::new(),
};
- return Err(IllegalSizedBound(candidates, needs_mut));
+ return Err(IllegalSizedBound(candidates, needs_mut, span));
}
Ok(result.callee)
err.emit();
}
- MethodError::IllegalSizedBound(candidates, needs_mut) => {
+ MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
let mut err = self.sess().struct_span_err(span, &msg);
+ err.span_label(bound_span, "this has a `Sized` requirement");
if !candidates.is_empty() {
let help = format!(
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \