Skip to content

Don't structurally resolve during method ambiguity in probe #111747

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