-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Help needed finding a test that changes behaviour when changing DefiningOpaqueTypes::No to Yes #127035
Open
Labels
A-trait-systemArea: Trait systemArea: Trait systemE-help-wantedCall for participation: Help is requested to fix this issue.Call for participation: Help is requested to fix this issue.
Description
opened on Jun 27, 2024
I am trying to change
rust/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
Lines 151 to 201 in 127fa22
fn confirm_projection_candidate( | |
&mut self, | |
obligation: &PolyTraitObligation<'tcx>, | |
idx: usize, | |
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> { | |
let tcx = self.tcx(); | |
let placeholder_trait_predicate = | |
self.infcx.enter_forall_and_leak_universe(obligation.predicate).trait_ref; | |
let placeholder_self_ty = self.infcx.shallow_resolve(placeholder_trait_predicate.self_ty()); | |
let candidate_predicate = self | |
.for_each_item_bound( | |
placeholder_self_ty, | |
|_, clause, clause_idx| { | |
if clause_idx == idx { | |
ControlFlow::Break(clause) | |
} else { | |
ControlFlow::Continue(()) | |
} | |
}, | |
|| unreachable!(), | |
) | |
.break_value() | |
.expect("expected to index into clause that exists"); | |
let candidate = candidate_predicate | |
.as_trait_clause() | |
.expect("projection candidate is not a trait predicate") | |
.map_bound(|t| t.trait_ref); | |
let candidate = self.infcx.instantiate_binder_with_fresh_vars( | |
obligation.cause.span, | |
HigherRankedType, | |
candidate, | |
); | |
let mut obligations = Vec::new(); | |
let candidate = normalize_with_depth_to( | |
self, | |
obligation.param_env, | |
obligation.cause.clone(), | |
obligation.recursion_depth + 1, | |
candidate, | |
&mut obligations, | |
); | |
obligations.extend( | |
self.infcx | |
.at(&obligation.cause, obligation.param_env) | |
.eq(DefineOpaqueTypes::No, placeholder_trait_predicate, candidate) | |
.map(|InferOk { obligations, .. }| obligations) | |
.map_err(|_| Unimplemented)?, | |
); |
and
rust/compiler/rustc_trait_selection/src/traits/select/mod.rs
Lines 1759 to 1828 in 127fa22
pub(super) fn match_projection_projections( | |
&mut self, | |
obligation: &ProjectionTermObligation<'tcx>, | |
env_predicate: PolyProjectionPredicate<'tcx>, | |
potentially_unnormalized_candidates: bool, | |
) -> ProjectionMatchesProjection { | |
debug_assert_eq!(obligation.predicate.def_id, env_predicate.projection_def_id()); | |
let mut nested_obligations = Vec::new(); | |
let infer_predicate = self.infcx.instantiate_binder_with_fresh_vars( | |
obligation.cause.span, | |
BoundRegionConversionTime::HigherRankedType, | |
env_predicate, | |
); | |
let infer_projection = if potentially_unnormalized_candidates { | |
ensure_sufficient_stack(|| { | |
normalize_with_depth_to( | |
self, | |
obligation.param_env, | |
obligation.cause.clone(), | |
obligation.recursion_depth + 1, | |
infer_predicate.projection_term, | |
&mut nested_obligations, | |
) | |
}) | |
} else { | |
infer_predicate.projection_term | |
}; | |
let is_match = self | |
.infcx | |
.at(&obligation.cause, obligation.param_env) | |
.eq(DefineOpaqueTypes::No, obligation.predicate, infer_projection) | |
.is_ok_and(|InferOk { obligations, value: () }| { | |
self.evaluate_predicates_recursively( | |
TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()), | |
nested_obligations.into_iter().chain(obligations), | |
) | |
.is_ok_and(|res| res.may_apply()) | |
}); | |
if is_match { | |
let generics = self.tcx().generics_of(obligation.predicate.def_id); | |
// FIXME(generic-associated-types): Addresses aggressive inference in #92917. | |
// If this type is a GAT, and of the GAT args resolve to something new, | |
// that means that we must have newly inferred something about the GAT. | |
// We should give up in that case. | |
// FIXME(generic-associated-types): This only detects one layer of inference, | |
// which is probably not what we actually want, but fixing it causes some ambiguity: | |
// <https://github.com/rust-lang/rust/issues/125196>. | |
if !generics.is_own_empty() | |
&& obligation.predicate.args[generics.parent_count..].iter().any(|&p| { | |
p.has_non_region_infer() | |
&& match p.unpack() { | |
ty::GenericArgKind::Const(ct) => { | |
self.infcx.shallow_resolve_const(ct) != ct | |
} | |
ty::GenericArgKind::Type(ty) => self.infcx.shallow_resolve(ty) != ty, | |
ty::GenericArgKind::Lifetime(_) => false, | |
} | |
}) | |
{ | |
ProjectionMatchesProjection::Ambiguous | |
} else { | |
ProjectionMatchesProjection::Yes | |
} | |
} else { | |
ProjectionMatchesProjection::No | |
} | |
} |
to DefiningOpaqueTypes::Yes. But I have been unable to preserve an opaque type all the way to this point. I can provide some tests of previous attempts, but it's probably better to start from a clean slate ^^
Note that while I did add this change as a commit to 2b1f439, the change can just be done on master without affecting any tests
Metadata
Assignees
Labels
A-trait-systemArea: Trait systemArea: Trait systemE-help-wantedCall for participation: Help is requested to fix this issue.Call for participation: Help is requested to fix this issue.
Activity