parent
06fea92356
commit
3ca1c5d5b5
6 changed files with 32 additions and 12 deletions
|
@ -32,7 +32,7 @@ impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> {
|
||||||
|
|
||||||
pub struct ConfirmResult<'tcx> {
|
pub struct ConfirmResult<'tcx> {
|
||||||
pub callee: MethodCallee<'tcx>,
|
pub callee: MethodCallee<'tcx>,
|
||||||
pub illegal_sized_bound: bool,
|
pub illegal_sized_bound: Option<Span>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
|
@ -112,7 +112,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
// Add any trait/regions obligations specified on the method's type parameters.
|
// 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
|
// We won't add these if we encountered an illegal sized bound, so that we can use
|
||||||
// a custom error in that case.
|
// 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));
|
let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig));
|
||||||
self.add_obligations(method_ty, all_substs, &method_predicates);
|
self.add_obligations(method_ty, all_substs, &method_predicates);
|
||||||
}
|
}
|
||||||
|
@ -561,23 +561,31 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
fn predicates_require_illegal_sized_bound(
|
fn predicates_require_illegal_sized_bound(
|
||||||
&self,
|
&self,
|
||||||
predicates: &ty::InstantiatedPredicates<'tcx>,
|
predicates: &ty::InstantiatedPredicates<'tcx>,
|
||||||
) -> bool {
|
) -> Option<Span> {
|
||||||
let sized_def_id = match self.tcx.lang_items().sized_trait() {
|
let sized_def_id = match self.tcx.lang_items().sized_trait() {
|
||||||
Some(def_id) => def_id,
|
Some(def_id) => def_id,
|
||||||
None => return false,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
traits::elaborate_predicates(self.tcx, predicates.predicates.clone())
|
traits::elaborate_predicates(self.tcx, predicates.predicates.clone())
|
||||||
.filter_map(|predicate| match predicate {
|
.filter_map(|predicate| match predicate {
|
||||||
ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
|
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,
|
_ => None,
|
||||||
})
|
})
|
||||||
.any(|trait_pred| match trait_pred.skip_binder().self_ty().kind {
|
.filter_map(|(trait_pred, span)| match trait_pred.skip_binder().self_ty().kind {
|
||||||
ty::Dynamic(..) => true,
|
ty::Dynamic(..) => Some(span),
|
||||||
_ => false,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
|
fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
|
||||||
|
|
|
@ -58,7 +58,7 @@ pub enum MethodError<'tcx> {
|
||||||
|
|
||||||
// Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
|
// Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
|
||||||
// forgotten to import a trait.
|
// forgotten to import a trait.
|
||||||
IllegalSizedBound(Vec<DefId>, bool),
|
IllegalSizedBound(Vec<DefId>, bool, Span),
|
||||||
|
|
||||||
// Found a match, but the return type is wrong
|
// Found a match, but the return type is wrong
|
||||||
BadReturnType,
|
BadReturnType,
|
||||||
|
@ -204,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let result =
|
let result =
|
||||||
self.confirm_method(span, self_expr, call_expr, self_ty, pick.clone(), segment);
|
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;
|
let mut needs_mut = false;
|
||||||
if let ty::Ref(region, t_type, mutability) = self_ty.kind {
|
if let ty::Ref(region, t_type, mutability) = self_ty.kind {
|
||||||
let trait_type = self
|
let trait_type = self
|
||||||
|
@ -249,7 +249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
_ => Vec::new(),
|
_ => Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return Err(IllegalSizedBound(candidates, needs_mut));
|
return Err(IllegalSizedBound(candidates, needs_mut, span));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result.callee)
|
Ok(result.callee)
|
||||||
|
|
|
@ -640,9 +640,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
err.emit();
|
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 msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
|
||||||
let mut err = self.sess().struct_span_err(span, &msg);
|
let mut err = self.sess().struct_span_err(span, &msg);
|
||||||
|
err.span_label(bound_span, "this has a `Sized` requirement");
|
||||||
if !candidates.is_empty() {
|
if !candidates.is_empty() {
|
||||||
let help = format!(
|
let help = format!(
|
||||||
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \
|
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error: the `wait` method cannot be invoked on a trait object
|
error: the `wait` method cannot be invoked on a trait object
|
||||||
--> $DIR/issue-35976.rs:14:9
|
--> $DIR/issue-35976.rs:14:9
|
||||||
|
|
|
|
||||||
|
LL | fn wait(&self) where Self: Sized;
|
||||||
|
| ----- this has a `Sized` requirement
|
||||||
|
...
|
||||||
LL | arg.wait();
|
LL | arg.wait();
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
|
|
||||||
|
|
|
@ -3,6 +3,11 @@ error: the `min` method cannot be invoked on a trait object
|
||||||
|
|
|
|
||||||
LL | t.min().unwrap()
|
LL | t.min().unwrap()
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
|
||||||
|
::: $SRC_DIR/libcore/iter/traits/iterator.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | Self: Sized,
|
||||||
|
| ----- this has a `Sized` requirement
|
||||||
|
|
|
|
||||||
= note: you need `&mut dyn std::iter::Iterator<Item = &u64>` instead of `&dyn std::iter::Iterator<Item = &u64>`
|
= note: you need `&mut dyn std::iter::Iterator<Item = &u64>` instead of `&dyn std::iter::Iterator<Item = &u64>`
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error: the `foo` method cannot be invoked on a trait object
|
error: the `foo` method cannot be invoked on a trait object
|
||||||
--> $DIR/by-value-trait-object-safety.rs:18:7
|
--> $DIR/by-value-trait-object-safety.rs:18:7
|
||||||
|
|
|
|
||||||
|
LL | fn foo(self) -> String where Self: Sized;
|
||||||
|
| ----- this has a `Sized` requirement
|
||||||
|
...
|
||||||
LL | x.foo();
|
LL | x.foo();
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue