Skip to content

Commit 3ca1c5d

Browse files
committed
Point at Sized requirements
Make rust-lang#47990 easier to understand
1 parent 06fea92 commit 3ca1c5d

File tree

6 files changed

+32
-12
lines changed

6 files changed

+32
-12
lines changed

src/librustc_typeck/check/method/confirm.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl<'a, 'tcx> Deref for ConfirmContext<'a, 'tcx> {
3232

3333
pub struct ConfirmResult<'tcx> {
3434
pub callee: MethodCallee<'tcx>,
35-
pub illegal_sized_bound: bool,
35+
pub illegal_sized_bound: Option<Span>,
3636
}
3737

3838
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -112,7 +112,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
112112
// Add any trait/regions obligations specified on the method's type parameters.
113113
// We won't add these if we encountered an illegal sized bound, so that we can use
114114
// a custom error in that case.
115-
if !illegal_sized_bound {
115+
if illegal_sized_bound.is_none() {
116116
let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig));
117117
self.add_obligations(method_ty, all_substs, &method_predicates);
118118
}
@@ -561,23 +561,31 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
561561
fn predicates_require_illegal_sized_bound(
562562
&self,
563563
predicates: &ty::InstantiatedPredicates<'tcx>,
564-
) -> bool {
564+
) -> Option<Span> {
565565
let sized_def_id = match self.tcx.lang_items().sized_trait() {
566566
Some(def_id) => def_id,
567-
None => return false,
567+
None => return None,
568568
};
569569

570570
traits::elaborate_predicates(self.tcx, predicates.predicates.clone())
571571
.filter_map(|predicate| match predicate {
572572
ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
573-
Some(trait_pred)
573+
let span = predicates
574+
.predicates
575+
.iter()
576+
.zip(predicates.spans.iter())
577+
.filter_map(|(p, span)| if *p == predicate { Some(*span) } else { None })
578+
.next()
579+
.unwrap_or(rustc_span::DUMMY_SP);
580+
Some((trait_pred, span))
574581
}
575582
_ => None,
576583
})
577-
.any(|trait_pred| match trait_pred.skip_binder().self_ty().kind {
578-
ty::Dynamic(..) => true,
579-
_ => false,
584+
.filter_map(|(trait_pred, span)| match trait_pred.skip_binder().self_ty().kind {
585+
ty::Dynamic(..) => Some(span),
586+
_ => None,
580587
})
588+
.next()
581589
}
582590

583591
fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {

src/librustc_typeck/check/method/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub enum MethodError<'tcx> {
5858

5959
// Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have
6060
// forgotten to import a trait.
61-
IllegalSizedBound(Vec<DefId>, bool),
61+
IllegalSizedBound(Vec<DefId>, bool, Span),
6262

6363
// Found a match, but the return type is wrong
6464
BadReturnType,
@@ -204,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
204204
let result =
205205
self.confirm_method(span, self_expr, call_expr, self_ty, pick.clone(), segment);
206206

207-
if result.illegal_sized_bound {
207+
if let Some(span) = result.illegal_sized_bound {
208208
let mut needs_mut = false;
209209
if let ty::Ref(region, t_type, mutability) = self_ty.kind {
210210
let trait_type = self
@@ -249,7 +249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
249249
_ => Vec::new(),
250250
};
251251

252-
return Err(IllegalSizedBound(candidates, needs_mut));
252+
return Err(IllegalSizedBound(candidates, needs_mut, span));
253253
}
254254

255255
Ok(result.callee)

src/librustc_typeck/check/method/suggest.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -640,9 +640,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
640640
err.emit();
641641
}
642642

643-
MethodError::IllegalSizedBound(candidates, needs_mut) => {
643+
MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
644644
let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
645645
let mut err = self.sess().struct_span_err(span, &msg);
646+
err.span_label(bound_span, "this has a `Sized` requirement");
646647
if !candidates.is_empty() {
647648
let help = format!(
648649
"{an}other candidate{s} {were} found in the following trait{s}, perhaps \

src/test/ui/issues/issue-35976.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error: the `wait` method cannot be invoked on a trait object
22
--> $DIR/issue-35976.rs:14:9
33
|
4+
LL | fn wait(&self) where Self: Sized;
5+
| ----- this has a `Sized` requirement
6+
...
47
LL | arg.wait();
58
| ^^^^
69
|

src/test/ui/suggestions/imm-ref-trait-object.stderr

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ error: the `min` method cannot be invoked on a trait object
33
|
44
LL | t.min().unwrap()
55
| ^^^
6+
|
7+
::: $SRC_DIR/libcore/iter/traits/iterator.rs:LL:COL
8+
|
9+
LL | Self: Sized,
10+
| ----- this has a `Sized` requirement
611
|
712
= note: you need `&mut dyn std::iter::Iterator<Item = &u64>` instead of `&dyn std::iter::Iterator<Item = &u64>`
813

src/test/ui/unsized-locals/by-value-trait-object-safety.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error: the `foo` method cannot be invoked on a trait object
22
--> $DIR/by-value-trait-object-safety.rs:18:7
33
|
4+
LL | fn foo(self) -> String where Self: Sized;
5+
| ----- this has a `Sized` requirement
6+
...
47
LL | x.foo();
58
| ^^^
69

0 commit comments

Comments
 (0)