-
Notifications
You must be signed in to change notification settings - Fork 14k
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
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
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.