Skip to content

Do not error during method probe on Sized predicates for types that aren't the method receiver #99146

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:?}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this the same as

debug!(?rcvr_substs, ?all_substs);

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, you're right. not super familiar with the tracing macros, sorry😅


// 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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error is actually more verbose than what it used to (erroneously) say before, but it's more consistent with an error you'd get if you, for example, passed any other DST as a generic arg. It also makes the second error, the mismatched types ("" against dyn ToString) not be suppressed any longer, which IMO is better.

--> $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`.