Rollup merge of #93892 - compiler-errors:issue-92917, r=jackh726,nikomatsakis
Only mark projection as ambiguous if GAT substs are constrained A slightly more targeted version of #92917, where we only give up with ambiguity if we infer something about the GATs substs when probing for a projection candidate. fixes #93874 also note (but like the previous PR, does not fix) #91762 r? `@jackh726` cc `@nikomatsakis` who reviewed #92917
This commit is contained in:
@@ -1494,12 +1494,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
})
|
||||
}
|
||||
|
||||
/// 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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
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 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -2709,3 +2735,9 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
|
||||
write!(f, "TraitObligationStack({:?})", self.obligation)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ProjectionMatchesProjection {
|
||||
Yes,
|
||||
Ambiguous,
|
||||
No,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user