Skip to content

Commit afe3650

Browse files
Don't structurally resolve during method ambiguity in probe
1 parent 04075b3 commit afe3650

File tree

3 files changed

+71
-5
lines changed

3 files changed

+71
-5
lines changed

compiler/rustc_hir_typeck/src/method/probe.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_hir::def::DefKind;
1212
use rustc_hir_analysis::autoderef::{self, Autoderef};
1313
use rustc_infer::infer::canonical::OriginalQueryValues;
1414
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
15+
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
1516
use rustc_infer::infer::DefineOpaqueTypes;
1617
use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
1718
use rustc_middle::middle::stability;
@@ -448,15 +449,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
448449
);
449450
}
450451
} else {
451-
// Encountered a real ambiguity, so abort the lookup. If `ty` is not
452-
// an `Err`, report the right "type annotations needed" error pointing
453-
// to it.
452+
// Ended up encountering a type variable when doing autoderef,
453+
// but it may not be a type variable after processing obligations
454+
// in our local `FnCtxt`, so don't call `structurally_resolved_type`.
454455
let ty = &bad_ty.ty;
455456
let ty = self
456457
.probe_instantiate_query_response(span, &orig_values, ty)
457458
.unwrap_or_else(|_| span_bug!(span, "instantiating {:?} failed?", ty));
458-
let ty = self.structurally_resolved_type(span, ty.value);
459-
assert!(matches!(ty.kind(), ty::Error(_)));
459+
let ty = self.resolve_vars_if_possible(ty.value);
460+
let guar = match *ty.kind() {
461+
ty::Infer(ty::TyVar(_)) => self
462+
.err_ctxt()
463+
.emit_inference_failure_err(self.body_id, span, ty.into(), E0282, true)
464+
.emit(),
465+
ty::Error(guar) => guar,
466+
_ => bug!("unexpected bad final type in method autoderef"),
467+
};
468+
self.demand_eqtype(span, ty, self.tcx.ty_error(guar));
460469
return Err(MethodError::NoMatch(NoMatchData {
461470
static_candidates: Vec::new(),
462471
unsatisfied_predicates: Vec::new(),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use std::ops::Deref;
2+
use std::rc::Rc;
3+
4+
struct Value<T>(T);
5+
6+
pub trait Wrap<T> {
7+
fn wrap() -> Self;
8+
}
9+
10+
impl<R, A1, A2> Wrap<fn(A1, A2) -> R> for Value<fn(A1, A2) -> R> {
11+
fn wrap() -> Self {
12+
todo!()
13+
}
14+
}
15+
16+
impl<F, R, A1, A2> Wrap<F> for Value<Rc<dyn Fn(A1, A2) -> R>> {
17+
fn wrap() -> Self {
18+
todo!()
19+
}
20+
}
21+
22+
impl<F> Deref for Value<Rc<F>> {
23+
type Target = F;
24+
25+
fn deref(&self) -> &Self::Target {
26+
&*self.0
27+
}
28+
}
29+
30+
fn main() {
31+
let var_fn = Value::wrap();
32+
//~^ ERROR type annotations needed for `Value<Rc<_>>`
33+
34+
// The combination of `Value: Wrap` obligation plus the autoderef steps
35+
// (caused by the `Deref` impl above) actually means that the self type
36+
// of the method fn below is constrained to be `Value<Rc<dyn Fn(?0, ?1) -> ?2>>`.
37+
// However, that's only known to us on the error path -- we still need
38+
// to emit an ambiguity error, though.
39+
let _ = var_fn.clone();
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0282]: type annotations needed for `Value<Rc<_>>`
2+
--> $DIR/deref-ambiguity-becomes-nonambiguous.rs:31:9
3+
|
4+
LL | let var_fn = Value::wrap();
5+
| ^^^^^^
6+
...
7+
LL | let _ = var_fn.clone();
8+
| ----- type must be known at this point
9+
|
10+
help: consider giving `var_fn` an explicit type, where the placeholders `_` are specified
11+
|
12+
LL | let var_fn: Value<Rc<_>> = Value::wrap();
13+
| ++++++++++++++
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0282`.

0 commit comments

Comments
 (0)