Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
oli-obk opened this issue Jun 27, 2024 · 3 comments
Labels
A-trait-system Area: Trait system E-help-wanted Call for participation: Help is requested to fix this issue.

Comments

@oli-obk
Copy link
Contributor

oli-obk commented Jun 27, 2024

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

@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jun 27, 2024
@veera-sivarajan
Copy link
Contributor

@rustbot label -needs-triage +A-traits +E-help-wanted

@rustbot rustbot added A-trait-system Area: Trait system E-help-wanted Call for participation: Help is requested to fix this issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jun 30, 2024
@lcnr
Copy link
Contributor

lcnr commented Jul 10, 2024

quite certain that the change in confirm_projection_candidate (modulo old solver weirdness) can only be triggered once we're using DefineOpaqueTypes::Yes here:

.eq(DefineOpaqueTypes::No, placeholder_trait_ref, trait_bound)

@oli-obk
Copy link
Contributor Author

oli-obk commented Jul 10, 2024

I did that in ced0945, and tested everything on top of that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system E-help-wanted Call for participation: Help is requested to fix this issue.
Projects
None yet
Development

No branches or pull requests

4 participants