X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=compiler%2Frustc_trait_selection%2Fsrc%2Ftraits%2Fselect%2Fmod.rs;h=8bcb1ccb5846d42586dc3168dac96015641e5b86;hb=02ff9e0aef03d48fdecc2d114311217010ec1d81;hp=64af875dd22bbb8a2024f88e824c79fd90e76dba;hpb=f1c918f1f3166c1cb2624ce2e2783d357e70dc3d;p=rust.git diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 64af875dd22..8bcb1ccb584 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -29,7 +29,7 @@ use crate::traits::ProjectionCacheKey; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::ErrorReported; +use rustc_errors::{Diagnostic, ErrorReported}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::LateBoundRegionConversionTime; @@ -64,7 +64,7 @@ pub enum IntercrateAmbiguityCause { impl IntercrateAmbiguityCause { /// Emits notes when the overlap is caused by complex intercrate ambiguities. /// See #23980 for details. - pub fn add_intercrate_ambiguity_hint(&self, err: &mut rustc_errors::DiagnosticBuilder<'_>) { + pub fn add_intercrate_ambiguity_hint(&self, err: &mut Diagnostic) { err.note(&self.intercrate_ambiguity_hint()); } @@ -922,7 +922,7 @@ fn evaluate_stack<'o>( if !candidate_set.ambiguous && candidate_set.vec.is_empty() { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; let self_ty = trait_ref.self_ty(); - let cause = with_no_trimmed_paths(|| { + let cause = with_no_trimmed_paths!({ IntercrateAmbiguityCause::DownstreamCrate { trait_desc: trait_ref.print_only_trait_path().to_string(), self_desc: if self_ty.has_concrete_skeleton() { @@ -1481,7 +1481,7 @@ fn match_normalize_trait_ref( .map_err(|_| ()) } - fn evaluate_where_clause<'o>( + fn where_clause_may_apply<'o>( &mut self, stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>, @@ -1494,12 +1494,18 @@ fn evaluate_where_clause<'o>( }) } + /// Return `Yes` if the obligation's predicate type applies to the env_predicate, and + /// `No` if it does not. Return `Ambiguous` in the case that the projection type is a GAT, + /// and applying this env_predicate constrains any of the obligation's GAT substitutions. + /// + /// This behavior is a somewhat of a hack to prevent overconstraining inference variables + /// in cases like #91762. pub(super) fn match_projection_projections( &mut self, obligation: &ProjectionTyObligation<'tcx>, env_predicate: PolyProjectionPredicate<'tcx>, potentially_unnormalized_candidates: bool, - ) -> bool { + ) -> ProjectionMatchesProjection { let mut nested_obligations = Vec::new(); let (infer_predicate, _) = self.infcx.replace_bound_vars_with_fresh_vars( obligation.cause.span, @@ -1521,7 +1527,8 @@ pub(super) fn match_projection_projections( infer_predicate.projection_ty }; - self.infcx + let is_match = self + .infcx .at(&obligation.cause, obligation.param_env) .sup(obligation.predicate, infer_projection) .map_or(false, |InferOk { obligations, value: () }| { @@ -1530,7 +1537,26 @@ pub(super) fn match_projection_projections( nested_obligations.into_iter().chain(obligations), ) .map_or(false, |res| res.may_apply()) - }) + }); + + if is_match { + let generics = self.tcx().generics_of(obligation.predicate.item_def_id); + // FIXME(generic-associated-types): Addresses aggressive inference in #92917. + // If this type is a GAT, and of the GAT substs resolve to something new, + // that means that we must have newly inferred something about the GAT. + // We should give up in that case. + if !generics.params.is_empty() + && obligation.predicate.substs[generics.parent_count..] + .iter() + .any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p) + { + ProjectionMatchesProjection::Ambiguous + } else { + ProjectionMatchesProjection::Yes + } + } else { + ProjectionMatchesProjection::No + } } /////////////////////////////////////////////////////////////////////////// @@ -1826,9 +1852,7 @@ fn sized_conditions( ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None, ty::Tuple(tys) => Where( - obligation - .predicate - .rebind(tys.last().into_iter().map(|k| k.expect_ty()).collect()), + obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])), ), ty::Adt(def, substs) => { @@ -1891,7 +1915,7 @@ fn copy_clone_conditions( ty::Tuple(tys) => { // (*) binder moved here - Where(obligation.predicate.rebind(tys.iter().map(|k| k.expect_ty()).collect())) + Where(obligation.predicate.rebind(tys.iter().collect())) } ty::Closure(_, substs) => { @@ -1971,7 +1995,7 @@ fn constituent_types_for_ty( ty::Tuple(ref tys) => { // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet - t.rebind(tys.iter().map(|k| k.expect_ty()).collect()) + t.rebind(tys.iter().collect()) } ty::Closure(_, ref substs) => { @@ -2709,3 +2733,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "TraitObligationStack({:?})", self.obligation) } } + +pub enum ProjectionMatchesProjection { + Yes, + Ambiguous, + No, +}