Skip to content

Commit

Permalink
Rollup merge of #99146 - compiler-errors:issue-61525, r=lcnr
Browse files Browse the repository at this point in the history
Do not error during method probe on `Sized` predicates for types that aren't the method receiver

Fixes #61525

This is safe even though we're skipping an error because we end up confirming the method, which means we're still checking the `Sized` predicate in the end. It just means that we don't emit an erroneous message as below:

```
error: the `query` method cannot be invoked on a trait object
  --> src/lib.rs:14:11
   |
14 |         1.query::<dyn ToString>("")
   |           ^^^^^
   |
   = note: another candidate was found in the following trait, perhaps add a `use` for it:
           `use crate::Example;`
```

Also fixes erroneously suggesting the same trait over again, as seen in the `issue-35976.rs` UI test.
  • Loading branch information
matthiaskrgr committed Jul 11, 2022
2 parents 8e51b53 + 88f2140 commit a75ec28
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 18 deletions.
26 changes: 15 additions & 11 deletions compiler/rustc_typeck/src/check/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,25 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
let rcvr_substs = self.fresh_receiver_substs(self_ty, &pick);
let all_substs = self.instantiate_method_substs(&pick, segment, rcvr_substs);

debug!("all_substs={:?}", all_substs);
debug!("rcvr_substs={rcvr_substs:?}, all_substs={all_substs:?}");

// Create the final signature for the method, replacing late-bound regions.
let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_substs);

// If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that
// something which derefs to `Self` actually implements the trait and the caller
// wanted to make a static dispatch on it but forgot to import the trait.
// See test `src/test/ui/issue-35976.rs`.
//
// In that case, we'll error anyway, but we'll also re-run the search with all traits
// in scope, and if we find another method which can be used, we'll output an
// appropriate hint suggesting to import the trait.
let filler_substs = rcvr_substs
.extend_to(self.tcx, pick.item.def_id, |def, _| self.tcx.mk_param_from_def(def));
let illegal_sized_bound = self.predicates_require_illegal_sized_bound(
&self.tcx.predicates_of(pick.item.def_id).instantiate(self.tcx, filler_substs),
);

// Unify the (adjusted) self type with what the method expects.
//
// SUBTLE: if we want good error messages, because of "guessing" while matching
Expand All @@ -106,16 +120,6 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
// Make sure nobody calls `drop()` explicitly.
self.enforce_illegal_method_limitations(&pick);

// If there is a `Self: Sized` bound and `Self` is a trait object, it is possible that
// something which derefs to `Self` actually implements the trait and the caller
// wanted to make a static dispatch on it but forgot to import the trait.
// See test `src/test/ui/issue-35976.rs`.
//
// In that case, we'll error anyway, but we'll also re-run the search with all traits
// in scope, and if we find another method which can be used, we'll output an
// appropriate hint suggesting to import the trait.
let illegal_sized_bound = self.predicates_require_illegal_sized_bound(&method_predicates);

// 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.
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_typeck/src/check/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use rustc_hir::def_id::DefId;
use rustc_infer::infer::{self, InferOk};
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable};
use rustc_middle::ty::{DefIdTree, GenericParamDefKind};
use rustc_span::symbol::Ident;
use rustc_span::Span;
use rustc_trait_selection::traits;
Expand Down Expand Up @@ -221,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

// We probe again, taking all traits into account (not only those in scope).
let candidates = match self.lookup_probe(
let mut candidates = match self.lookup_probe(
span,
segment.ident,
self_ty,
Expand All @@ -243,6 +243,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.collect(),
_ => Vec::new(),
};
candidates.retain(|candidate| *candidate != self.tcx.parent(result.callee.def_id));

return Err(IllegalSizedBound(candidates, needs_mut, span));
}
Expand Down
5 changes: 0 additions & 5 deletions src/test/ui/issues/issue-35976.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,6 @@ LL | fn wait(&self) where Self: Sized;
...
LL | arg.wait();
| ^^^^
|
help: another candidate was found in the following trait, perhaps add a `use` for it:
|
LL | use private::Future;
|

error: aborting due to previous error

20 changes: 20 additions & 0 deletions src/test/ui/methods/issues/issue-61525.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
pub trait Example {
fn query<Q>(self, q: Q);
}

impl Example for i32 {
fn query<Q>(self, _: Q) {
unimplemented!()
}
}

mod nested {
use super::Example;
fn example() {
1.query::<dyn ToString>("")
//~^ ERROR the size for values of type `dyn ToString` cannot be known at compilation time
//~| ERROR mismatched types
}
}

fn main() {}
39 changes: 39 additions & 0 deletions src/test/ui/methods/issues/issue-61525.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
error[E0277]: the size for values of type `dyn ToString` cannot be known at compilation time
--> $DIR/issue-61525.rs:14:33
|
LL | 1.query::<dyn ToString>("")
| ----- ^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn ToString`
note: required by a bound in `Example::query`
--> $DIR/issue-61525.rs:2:14
|
LL | fn query<Q>(self, q: Q);
| ^ required by this bound in `Example::query`
help: consider relaxing the implicit `Sized` restriction
|
LL | fn query<Q: ?Sized>(self, q: Q);
| ++++++++

error[E0308]: mismatched types
--> $DIR/issue-61525.rs:14:33
|
LL | 1.query::<dyn ToString>("")
| --------------------- ^^ expected trait object `dyn ToString`, found `&str`
| |
| arguments to this function are incorrect
|
= note: expected trait object `dyn ToString`
found reference `&'static str`
note: associated function defined here
--> $DIR/issue-61525.rs:2:8
|
LL | fn query<Q>(self, q: Q);
| ^^^^^

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.

0 comments on commit a75ec28

Please sign in to comment.