Skip to content

Commit f4c695a

Browse files
Don't autoderef infinitely on ambiguity
1 parent a62ecba commit f4c695a

File tree

4 files changed

+56
-32
lines changed

4 files changed

+56
-32
lines changed

compiler/rustc_hir_analysis/src/autoderef.rs

+30-9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::errors::AutoDerefReachedRecursionLimit;
22
use crate::traits::query::evaluate_obligation::InferCtxtExt;
33
use crate::traits::NormalizeExt;
44
use crate::traits::{self, TraitEngine, TraitEngineExt};
5+
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
56
use rustc_infer::infer::InferCtxt;
67
use rustc_middle::ty::TypeVisitableExt;
78
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -138,22 +139,42 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
138139
return None;
139140
}
140141

141-
let normalized_ty = self
142-
.infcx
143-
.at(&cause, self.param_env)
144-
.normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
145-
let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
146-
let normalized_ty =
147-
normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx);
148-
let errors = fulfillcx.select_where_possible(&self.infcx);
142+
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
143+
let normalized_ty = if tcx.trait_solver_next() {
144+
let ty_var = self.infcx.next_ty_var(TypeVariableOrigin {
145+
span: self.span,
146+
kind: TypeVariableOriginKind::NormalizeProjectionType,
147+
});
148+
fulfill_cx.register_predicate_obligation(
149+
self.infcx,
150+
traits::Obligation::new(
151+
tcx,
152+
cause.clone(),
153+
self.param_env,
154+
ty::Binder::dummy(ty::ProjectionPredicate {
155+
projection_ty: tcx.mk_alias_ty(tcx.lang_items().deref_target()?, [ty]),
156+
term: ty_var.into(),
157+
}),
158+
),
159+
);
160+
ty_var
161+
} else {
162+
let normalized_ty = self
163+
.infcx
164+
.at(&cause, self.param_env)
165+
.normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
166+
normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfill_cx)
167+
};
168+
169+
let errors = fulfill_cx.select_where_possible(&self.infcx);
149170
if !errors.is_empty() {
150171
// This shouldn't happen, except for evaluate/fulfill mismatches,
151172
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
152173
// by design).
153174
debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
154175
return None;
155176
}
156-
let obligations = fulfillcx.pending_obligations();
177+
let obligations = fulfill_cx.pending_obligations();
157178
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
158179
self.state.obligations.extend(obligations);
159180

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// compile-flags: -Ztrait-solver=next
2+
3+
fn main() {
4+
let y = [Default::default()];
5+
y[0].method();
6+
//~^ ERROR type annotations needed
7+
//~| ERROR no method named `method` found
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0282]: type annotations needed
2+
--> $DIR/autoderef-infinite.rs:5:10
3+
|
4+
LL | y[0].method();
5+
| ^^^^^^ cannot infer type
6+
7+
error[E0599]: no method named `method` found for associated type `<usize as SliceIndex<[_]>>::Output` in the current scope
8+
--> $DIR/autoderef-infinite.rs:5:10
9+
|
10+
LL | y[0].method();
11+
| ^^^^^^ method not found in `<usize as SliceIndex<[_]>>::Output`
12+
13+
error: aborting due to 2 previous errors
14+
15+
Some errors have detailed explanations: E0282, E0599.
16+
For more information about an error, try `rustc --explain E0282`.
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,3 @@
1-
error[E0055]: reached the recursion limit while auto-dereferencing `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<_ as Test>::Assoc as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target`
2-
|
3-
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`equating_projection_cyclically`)
4-
5-
error[E0055]: reached the recursion limit while auto-dereferencing `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<_ as Test>::Assoc as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target`
6-
--> $DIR/equating-projection-cyclically.rs:22:9
7-
|
8-
LL | x = transform(x);
9-
| ^^^^^^^^^^^^ deref recursion limit reached
10-
|
11-
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`equating_projection_cyclically`)
12-
13-
error[E0055]: reached the recursion limit while auto-dereferencing `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<_ as Test>::Assoc as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target as Deref>::Target`
14-
--> $DIR/equating-projection-cyclically.rs:22:9
15-
|
16-
LL | x = transform(x);
17-
| ^^^^^^^^^^^^ deref recursion limit reached
18-
|
19-
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`equating_projection_cyclically`)
20-
211
error[E0308]: mismatched types
222
--> $DIR/equating-projection-cyclically.rs:22:9
233
|
@@ -26,7 +6,6 @@ LL | x = transform(x);
266
| |
277
| cyclic type of infinite size
288

29-
error: aborting due to 4 previous errors
9+
error: aborting due to previous error
3010

31-
Some errors have detailed explanations: E0055, E0308.
32-
For more information about an error, try `rustc --explain E0055`.
11+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)