Skip to content

Commit

Permalink
Don't structurally resolve during method ambiguity in probe
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jun 22, 2023
1 parent 04075b3 commit afe3650
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 afe3650

Please sign in to comment.