use an enum in matches_projection_projection
This commit is contained in:
parent
784c7a6cad
commit
879e4f8131
2 changed files with 28 additions and 16 deletions
|
@ -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 => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue