about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-07-11 22:39:09 +0200
committerGitHub <noreply@github.com>2022-07-11 22:39:09 +0200
commit5e223dc7b9b541e12514efeb05b915af9b6e508c (patch)
treec2a2f772f58b7e7076179859d9f9baf06d11dc63
parent1679d1c6223aaf0e946291aca66f5dbf1396ab08 (diff)
parent88f2140d8736329610a4c0bd8000e164c9170537 (diff)
downloadrust-5e223dc7b9b541e12514efeb05b915af9b6e508c.tar.gz
rust-5e223dc7b9b541e12514efeb05b915af9b6e508c.zip
Rollup merge of #99146 - compiler-errors:issue-61525, r=lcnr
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.
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs26
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs5
-rw-r--r--src/test/ui/issues/issue-35976.stderr5
-rw-r--r--src/test/ui/methods/issues/issue-61525.rs20
-rw-r--r--src/test/ui/methods/issues/issue-61525.stderr39
5 files changed, 77 insertions, 18 deletions
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index d8cdc9275f4..b14f3d6de4e 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -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
@@ -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.
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index e29f0275bf4..c0b3a23fde4 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -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;
@@ -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,
@@ -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));
         }
diff --git a/src/test/ui/issues/issue-35976.stderr b/src/test/ui/issues/issue-35976.stderr
index f9b9b7dbd34..fe16f97b9d0 100644
--- a/src/test/ui/issues/issue-35976.stderr
+++ b/src/test/ui/issues/issue-35976.stderr
@@ -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
 
diff --git a/src/test/ui/methods/issues/issue-61525.rs b/src/test/ui/methods/issues/issue-61525.rs
new file mode 100644
index 00000000000..c5ca0326e43
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-61525.rs
@@ -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() {}
diff --git a/src/test/ui/methods/issues/issue-61525.stderr b/src/test/ui/methods/issues/issue-61525.stderr
new file mode 100644
index 00000000000..aec968d7c44
--- /dev/null
+++ b/src/test/ui/methods/issues/issue-61525.stderr
@@ -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`.