Skip to content

Commit

Permalink
Rollup merge of #111747 - compiler-errors:structural-probe-side-effec…
Browse files Browse the repository at this point in the history
…ts, 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
  • Loading branch information
matthiaskrgr committed Jun 23, 2023
2 parents fe37f37 + afe3650 commit 01cc9ca
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
19 changes: 14 additions & 5 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
Expand Down
40 changes: 40 additions & 0 deletions tests/ui/autoref-autoderef/deref-ambiguity-becomes-nonambiguous.rs
Original file line number Diff line number Diff line change
@@ -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();
}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 01cc9ca

Please sign in to comment.