about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-06-23 13:18:12 +0200
committerGitHub <noreply@github.com>2023-06-23 13:18:12 +0200
commit01cc9caffe0ae3e16059d93881d42ce5a952839a (patch)
tree4307b2b384c77c2c2ff1fcf3ac0dc592f8505fbb
parentfe37f37e4b764bb82fc0eb8c727842746de7c93f (diff)
parentafe36507e84e8b7805717bc1c5054dcf4346df92 (diff)
Rollup merge of #111747 - compiler-errors:structural-probe-side-effects, r=fee1-dead
Don't structurally resolve during method ambiguity in probe

See comment in UI test for reason for the failure. This is all on the error path anyways, not really sure what the assertion is there to achieve anyways...

Fixes #111739
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs19
-rw-r--r--tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs40
-rw-r--r--tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr17
3 files changed, 71 insertions, 5 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index e759fd6bc94..762176ecfc7 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -12,6 +12,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir_analysis::autoderef::{self, Autoderef};
 use rustc_infer::infer::canonical::OriginalQueryValues;
 use rustc_infer::infer::canonical::{Canonical, QueryResponse};
+use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
 use rustc_middle::middle::stability;
@@ -448,15 +449,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                 }
             } else {
-                // Encountered a real ambiguity, so abort the lookup. If `ty` is not
-                // an `Err`, report the right "type annotations needed" error pointing
-                // to it.
+                // Ended up encountering a type variable when doing autoderef,
+                // but it may not be a type variable after processing obligations
+                // in our local `FnCtxt`, so don't call `structurally_resolved_type`.
                 let ty = &bad_ty.ty;
                 let ty = self
                     .probe_instantiate_query_response(span, &orig_values, ty)
                     .unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
-                let ty = self.structurally_resolved_type(span, ty.value);
-                assert!(matches!(ty.kind(), ty::Error(_)));
+                let ty = self.resolve_vars_if_possible(ty.value);
+                let guar = match *ty.kind() {
+                    ty::Infer(ty::TyVar(_)) => self
+                        .err_ctxt()
+                        .emit_inference_failure_err(self.body_id, span, ty.into(), E0282, true)
+                        .emit(),
+                    ty::Error(guar) => guar,
+                    _ => bug!("unexpected bad final type in method autoderef"),
+                };
+                self.demand_eqtype(span, ty, self.tcx.ty_error(guar));
                 return Err(MethodError::NoMatch(NoMatchData {
                     static_candidates: Vec::new(),
                     unsatisfied_predicates: Vec::new(),
diff --git a/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs
new file mode 100644
index 00000000000..d8034d57e8d
--- /dev/null
+++ b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs
@@ -0,0 +1,40 @@
+use std::ops::Deref;
+use std::rc::Rc;
+
+struct Value<T>(T);
+
+pub trait Wrap<T> {
+    fn wrap() -> Self;
+}
+
+impl<R, A1, A2> Wrap<fn(A1, A2) -> R> for Value<fn(A1, A2) -> R> {
+    fn wrap() -> Self {
+        todo!()
+    }
+}
+
+impl<F, R, A1, A2> Wrap<F> for Value<Rc<dyn Fn(A1, A2) -> R>> {
+    fn wrap() -> Self {
+        todo!()
+    }
+}
+
+impl<F> Deref for Value<Rc<F>> {
+    type Target = F;
+
+    fn deref(&self) -> &Self::Target {
+        &*self.0
+    }
+}
+
+fn main() {
+    let var_fn = Value::wrap();
+    //~^ ERROR type annotations needed for `Value<Rc<_>>`
+
+    // The combination of `Value: Wrap` obligation plus the autoderef steps
+    // (caused by the `Deref` impl above) actually means that the self type
+    // of the method fn below is constrained to be `Value<Rc<dyn Fn(?0, ?1) -> ?2>>`.
+    // However, that's only known to us on the error path -- we still need
+    // to emit an ambiguity error, though.
+    let _ = var_fn.clone();
+}
diff --git a/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr
new file mode 100644
index 00000000000..06a7e90858c
--- /dev/null
+++ b/tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.stderr
@@ -0,0 +1,17 @@
+error[E0282]: type annotations needed for `Value<Rc<_>>`
+  --> $DIR/deref-ambiguity-becomes-nonambiguous.rs:31:9
+   |
+LL |     let var_fn = Value::wrap();
+   |         ^^^^^^
+...
+LL |     let _ = var_fn.clone();
+   |                    ----- type must be known at this point
+   |
+help: consider giving `var_fn` an explicit type, where the placeholders `_` are specified
+   |
+LL |     let var_fn: Value<Rc<_>> = Value::wrap();
+   |               ++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.