1
Fork 0

use an enum in matches_projection_projection

This commit is contained in:
Michael Goulet 2022-02-12 13:30:30 -08:00
parent 784c7a6cad
commit 879e4f8131
2 changed files with 28 additions and 16 deletions

View file

@ -19,6 +19,7 @@ use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
use crate::traits::error_reporting::InferCtxtExt as _; use crate::traits::error_reporting::InferCtxtExt as _;
use crate::traits::select::ProjectionMatchesProjection;
use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::sso::SsoHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_errors::ErrorReported; use rustc_errors::ErrorReported;
@ -1248,7 +1249,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
}); });
match is_match { match is_match {
Some(true) => { ProjectionMatchesProjection::Yes => {
candidate_set.push_candidate(ctor(data)); candidate_set.push_candidate(ctor(data));
if potentially_unnormalized_candidates if potentially_unnormalized_candidates
@ -1260,10 +1261,10 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
return; return;
} }
} }
Some(false) => {} ProjectionMatchesProjection::Ambiguous => {
None => {
candidate_set.mark_ambiguous(); candidate_set.mark_ambiguous();
} }
ProjectionMatchesProjection::No => {}
} }
} }
} }

View file

@ -1508,15 +1508,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}) })
} }
/// Return Some(true) if the obligation's predicate type applies to the env_predicate, and /// Return `Yes` if the obligation's predicate type applies to the env_predicate, and
/// Some(false) if it does not. Returns None in the case that the projection type is a GAT, /// `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. /// 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( pub(super) fn match_projection_projections(
&mut self, &mut self,
obligation: &ProjectionTyObligation<'tcx>, obligation: &ProjectionTyObligation<'tcx>,
env_predicate: PolyProjectionPredicate<'tcx>, env_predicate: PolyProjectionPredicate<'tcx>,
potentially_unnormalized_candidates: bool, potentially_unnormalized_candidates: bool,
) -> Option<bool> { ) -> ProjectionMatchesProjection {
let mut nested_obligations = Vec::new(); let mut nested_obligations = Vec::new();
let (infer_predicate, _) = self.infcx.replace_bound_vars_with_fresh_vars( let (infer_predicate, _) = self.infcx.replace_bound_vars_with_fresh_vars(
obligation.cause.span, obligation.cause.span,
@ -1553,22 +1556,24 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if is_match { if is_match {
let generics = self.tcx().generics_of(obligation.predicate.item_def_id); let generics = self.tcx().generics_of(obligation.predicate.item_def_id);
if !generics.params.is_empty() { // FIXME(generic-associated-types): Addresses aggressive inference in #92917.
// If any of the obligation's predicate substs shallow-resolve to // If this type is a GAT, and of the GAT substs resolve to something new,
// something new, that means that we must have newly inferred something // that means that we must have newly inferred something about the GAT.
// about the GAT. We should give up with ambiguity in that case. // We should give up in that case.
if obligation.predicate.substs[generics.parent_count..] if !generics.params.is_empty()
&& obligation.predicate.substs[generics.parent_count..]
.iter() .iter()
.any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p) .any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p)
{ {
return None; ProjectionMatchesProjection::Ambiguous
} else {
ProjectionMatchesProjection::Yes
} }
} else {
ProjectionMatchesProjection::No
} }
} }
Some(is_match)
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// WINNOW // WINNOW
// //
@ -2766,3 +2771,9 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
write!(f, "TraitObligationStack({:?})", self.obligation) write!(f, "TraitObligationStack({:?})", self.obligation)
} }
} }
pub enum ProjectionMatchesProjection {
Yes,
Ambiguous,
No,
}