From 84196f33710e2797a576ddc5241e418b7a4f1f2c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Jun 2023 22:07:53 +0000 Subject: [PATCH] Elaborate comment, make sure we do normalizes-to hack eventually for IATs, don't partially support const projection for impls --- .../src/solve/project_goals.rs | 55 ++++++++++--------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 99ed9ac7b62..23601f668ff 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -25,29 +25,39 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let def_id = goal.predicate.def_id(); match self.tcx().def_kind(def_id) { DefKind::AssocTy | DefKind::AssocConst => { - match self.tcx().associated_item(def_id).container { - ty::AssocItemContainer::TraitContainer => { - // To only compute normalization once for each projection we only - // normalize if the expected term is an unconstrained inference variable. - // - // E.g. for `::Assoc == u32` we recursively compute the goal - // `exists ::Assoc == U` and then take the resulting type for - // `U` and equate it with `u32`. This means that we don't need a separate - // projection cache in the solver. - if self.term_is_fully_unconstrained(goal) { + // To only compute normalization once for each projection we only + // assemble normalization candidates if the expected term is an + // unconstrained inference variable. + // + // Why: For better cache hits, since if we have an unconstrained RHS then + // there are only as many cache keys as there are (canonicalized) alias + // types in each normalizes-to goal. This also weakens inference in a + // forwards-compatible way so we don't use the value of the RHS term to + // affect candidate assembly for projections. + // + // E.g. for `::Assoc == u32` we recursively compute the goal + // `exists ::Assoc == U` and then take the resulting type for + // `U` and equate it with `u32`. This means that we don't need a separate + // projection cache in the solver, since we're piggybacking off of regular + // goal caching. + if self.term_is_fully_unconstrained(goal) { + match self.tcx().associated_item(def_id).container { + ty::AssocItemContainer::TraitContainer => { let candidates = self.assemble_and_evaluate_candidates(goal); self.merge_candidates(candidates) - } else { - self.set_normalizes_to_hack_goal(goal); - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + ty::AssocItemContainer::ImplContainer => { + bug!("IATs not supported here yet") } } - ty::AssocItemContainer::ImplContainer => bug!("IATs not supported here yet"), + } else { + self.set_normalizes_to_hack_goal(goal); + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } DefKind::AnonConst => self.normalize_anon_const(goal), DefKind::OpaqueTy => self.normalize_opaque_type(goal), - kind => bug!("uknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)), + kind => bug!("unknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)), } } @@ -203,17 +213,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ); // Finally we construct the actual value of the associated type. - let is_const = matches!(tcx.def_kind(assoc_def.item.def_id), DefKind::AssocConst); - let ty = tcx.type_of(assoc_def.item.def_id); - let term: ty::EarlyBinder> = if is_const { - let identity_substs = - ty::InternalSubsts::identity_for_item(tcx, assoc_def.item.def_id); - let did = assoc_def.item.def_id; - let kind = - ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs)); - ty.map_bound(|ty| tcx.mk_const(kind, ty).into()) - } else { - ty.map_bound(|ty| ty.into()) + let term = match assoc_def.item.kind { + ty::AssocKind::Type => tcx.type_of(assoc_def.item.def_id).map_bound(|ty| ty.into()), + ty::AssocKind::Const => bug!("associated const projection is not supported yet"), + ty::AssocKind::Fn => unreachable!("we should never project to a fn"), }; ecx.eq(goal.param_env, goal.predicate.term, term.subst(tcx, substs))