Skip to content

Commit

Permalink
Don't autoderef infinitely on ambiguity
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Apr 12, 2023
1 parent a62ecba commit f4c695a
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 32 deletions.
39 changes: 30 additions & 9 deletions compiler/rustc_hir_analysis/src/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::errors::AutoDerefReachedRecursionLimit;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::NormalizeExt;
use crate::traits::{self, TraitEngine, TraitEngineExt};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::TypeVisitableExt;
use rustc_middle::ty::{self, Ty, TyCtxt};
Expand Down Expand Up @@ -138,22 +139,42 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
return None;
}

let normalized_ty = self
.infcx
.at(&cause, self.param_env)
.normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
let mut fulfillcx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
let normalized_ty =
normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfillcx);
let errors = fulfillcx.select_where_possible(&self.infcx);
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
let normalized_ty = if tcx.trait_solver_next() {
let ty_var = self.infcx.next_ty_var(TypeVariableOrigin {
span: self.span,
kind: TypeVariableOriginKind::NormalizeProjectionType,
});
fulfill_cx.register_predicate_obligation(
self.infcx,
traits::Obligation::new(
tcx,
cause.clone(),
self.param_env,
ty::Binder::dummy(ty::ProjectionPredicate {
projection_ty: tcx.mk_alias_ty(tcx.lang_items().deref_target()?, [ty]),
term: ty_var.into(),
}),
),
);
ty_var
} else {
let normalized_ty = self
.infcx
.at(&cause, self.param_env)
.normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, trait_ref.substs));
normalized_ty.into_value_registering_obligations(self.infcx, &mut *fulfill_cx)
};

let errors = fulfill_cx.select_where_possible(&self.infcx);
if !errors.is_empty() {
// This shouldn't happen, except for evaluate/fulfill mismatches,
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
// by design).
debug!("overloaded_deref_ty: encountered errors {:?} while fulfilling", errors);
return None;
}
let obligations = fulfillcx.pending_obligations();
let obligations = fulfill_cx.pending_obligations();
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
self.state.obligations.extend(obligations);

Expand Down
8 changes: 8 additions & 0 deletions tests/ui/traits/new-solver/autoderef-infinite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// compile-flags: -Ztrait-solver=next

fn main() {
let y = [Default::default()];
y[0].method();
//~^ ERROR type annotations needed
//~| ERROR no method named `method` found
}
16 changes: 16 additions & 0 deletions tests/ui/traits/new-solver/autoderef-infinite.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error[E0282]: type annotations needed
--> $DIR/autoderef-infinite.rs:5:10
|
LL | y[0].method();
| ^^^^^^ cannot infer type

error[E0599]: no method named `method` found for associated type `<usize as SliceIndex<[_]>>::Output` in the current scope
--> $DIR/autoderef-infinite.rs:5:10
|
LL | y[0].method();
| ^^^^^^ method not found in `<usize as SliceIndex<[_]>>::Output`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0282, E0599.
For more information about an error, try `rustc --explain E0282`.
25 changes: 2 additions & 23 deletions tests/ui/traits/new-solver/equating-projection-cyclically.stderr
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
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`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`equating_projection_cyclically`)

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`
--> $DIR/equating-projection-cyclically.rs:22:9
|
LL | x = transform(x);
| ^^^^^^^^^^^^ deref recursion limit reached
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`equating_projection_cyclically`)

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`
--> $DIR/equating-projection-cyclically.rs:22:9
|
LL | x = transform(x);
| ^^^^^^^^^^^^ deref recursion limit reached
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`equating_projection_cyclically`)

error[E0308]: mismatched types
--> $DIR/equating-projection-cyclically.rs:22:9
|
Expand All @@ -26,7 +6,6 @@ LL | x = transform(x);
| |
| cyclic type of infinite size

error: aborting due to 4 previous errors
error: aborting due to previous error

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

0 comments on commit f4c695a

Please sign in to comment.