From f4c695ad5010708b5da4fb4f90152b6c27cb32ef Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 12 Apr 2023 03:22:15 +0000 Subject: [PATCH] Don't autoderef infinitely on ambiguity --- compiler/rustc_hir_analysis/src/autoderef.rs | 39 ++++++++++++++----- .../traits/new-solver/autoderef-infinite.rs | 8 ++++ .../new-solver/autoderef-infinite.stderr | 16 ++++++++ .../equating-projection-cyclically.stderr | 25 +----------- 4 files changed, 56 insertions(+), 32 deletions(-) create mode 100644 tests/ui/traits/new-solver/autoderef-infinite.rs create mode 100644 tests/ui/traits/new-solver/autoderef-infinite.stderr diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index ba2d4319af6e2..fb1a02a799f64 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -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}; @@ -138,14 +139,34 @@ 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 = >::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 = >::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 @@ -153,7 +174,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { 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); diff --git a/tests/ui/traits/new-solver/autoderef-infinite.rs b/tests/ui/traits/new-solver/autoderef-infinite.rs new file mode 100644 index 0000000000000..4caeb1d3546c1 --- /dev/null +++ b/tests/ui/traits/new-solver/autoderef-infinite.rs @@ -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 +} diff --git a/tests/ui/traits/new-solver/autoderef-infinite.stderr b/tests/ui/traits/new-solver/autoderef-infinite.stderr new file mode 100644 index 0000000000000..e226c882b4b8a --- /dev/null +++ b/tests/ui/traits/new-solver/autoderef-infinite.stderr @@ -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 `>::Output` in the current scope + --> $DIR/autoderef-infinite.rs:5:10 + | +LL | y[0].method(); + | ^^^^^^ method not found in `>::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`. diff --git a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr b/tests/ui/traits/new-solver/equating-projection-cyclically.stderr index f03f6b4bf9003..2a4ad39e1335e 100644 --- a/tests/ui/traits/new-solver/equating-projection-cyclically.stderr +++ b/tests/ui/traits/new-solver/equating-projection-cyclically.stderr @@ -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 | @@ -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`.