Skip to content

Help needed finding a test that changes behaviour when changing DefiningOpaqueTypes::No to Yes #127035

Open
@oli-obk

Description

@oli-obk

cc @lcnr @compiler-errors

I am trying to change

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

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

Metadata

Assignees

No one assigned

    Labels

    A-trait-systemArea: Trait systemE-help-wantedCall for participation: Help is requested to fix this issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions