From 41883fd19a174b8c2d23494a24edd5b92b959fc6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 3 Feb 2023 02:29:52 +0000 Subject: [PATCH] intern external constraints --- compiler/rustc_middle/src/arena.rs | 1 + compiler/rustc_middle/src/traits/mod.rs | 1 + compiler/rustc_middle/src/traits/solve.rs | 55 +++++++++++++++++++ compiler/rustc_middle/src/ty/context.rs | 4 ++ .../rustc_trait_selection/src/solve/mod.rs | 35 ++++++------ .../src/solve/search_graph/cache.rs | 3 +- triagebot.toml | 3 +- 7 files changed, 80 insertions(+), 22 deletions(-) create mode 100644 compiler/rustc_middle/src/traits/solve.rs diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 72f4f6e649b..2ba7ec5b151 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -112,6 +112,7 @@ macro_rules! arena_types { [decode] trait_impl_trait_tys: rustc_data_structures::fx::FxHashMap>, [] bit_set_u32: rustc_index::bit_set::BitSet, + [] external_constraints: rustc_middle::traits::solve::ExternalConstraintsData<'tcx>, ]); ) } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index cf3dce48064..75525059e90 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -5,6 +5,7 @@ mod chalk; pub mod query; pub mod select; +pub mod solve; pub mod specialization_graph; mod structural_impls; pub mod util; diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs new file mode 100644 index 00000000000..63f9c32f0a7 --- /dev/null +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -0,0 +1,55 @@ +use std::ops::ControlFlow; + +use rustc_data_structures::intern::Interned; + +use crate::ty::{FallibleTypeFolder, Ty, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor}; + +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>); + +impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { + type Target = ExternalConstraintsData<'tcx>; + + fn deref(&self) -> &Self::Target { + &*self.0 + } +} + +/// Additional constraints returned on success. +#[derive(Debug, PartialEq, Eq, Clone, Hash, Default)] +pub struct ExternalConstraintsData<'tcx> { + // FIXME: implement this. + pub regions: (), + pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>, +} + +impl<'tcx> TypeFoldable<'tcx> for ExternalConstraints<'tcx> { + fn try_fold_with>(self, folder: &mut F) -> Result { + Ok(FallibleTypeFolder::tcx(folder).intern_external_constraints(ExternalConstraintsData { + regions: (), + opaque_types: self + .opaque_types + .iter() + .map(|opaque| opaque.try_fold_with(folder)) + .collect::>()?, + })) + } + + fn fold_with>(self, folder: &mut F) -> Self { + TypeFolder::tcx(folder).intern_external_constraints(ExternalConstraintsData { + regions: (), + opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(), + }) + } +} + +impl<'tcx> TypeVisitable<'tcx> for ExternalConstraints<'tcx> { + fn visit_with>( + &self, + visitor: &mut V, + ) -> std::ops::ControlFlow { + self.regions.visit_with(visitor)?; + self.opaque_types.visit_with(visitor)?; + ControlFlow::Continue(()) + } +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f98172e4201..9205a8a0ffe 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -17,6 +17,7 @@ }; use crate::thir::Thir; use crate::traits; +use crate::traits::solve::{ExternalConstraints, ExternalConstraintsData}; use crate::ty::query::{self, TyCtxtAt}; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Const, ConstData, DefIdTree, FloatTy, FloatVar, @@ -148,6 +149,7 @@ pub struct CtxtInterners<'tcx> { bound_variable_kinds: InternedSet<'tcx, List>, layout: InternedSet<'tcx, LayoutS>, adt_def: InternedSet<'tcx, AdtDefData>, + external_constraints: InternedSet<'tcx, ExternalConstraintsData<'tcx>>, } impl<'tcx> CtxtInterners<'tcx> { @@ -169,6 +171,7 @@ fn new(arena: &'tcx WorkerLocal>) -> CtxtInterners<'tcx> { bound_variable_kinds: Default::default(), layout: Default::default(), adt_def: Default::default(), + external_constraints: Default::default(), } } @@ -1449,6 +1452,7 @@ pub fn $method(self, v: $ty) -> $ret_ty { const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, layout: intern_layout(LayoutS): Layout -> Layout<'tcx>, adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>, + external_constraints: intern_external_constraints(ExternalConstraintsData<'tcx>): ExternalConstraints -> ExternalConstraints<'tcx>, } macro_rules! slice_interners { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 36170b3788a..e4725c0a1b7 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -24,7 +24,8 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::Obligation; use rustc_middle::infer::canonical::Certainty as OldCertainty; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{ CoercePredicate, RegionOutlivesPredicate, SubtypePredicate, ToPredicate, TypeOutlivesPredicate, }; @@ -72,8 +73,7 @@ fn from(obligation: Obligation<'tcx, P>) -> Goal<'tcx, P> { Goal { param_env: obligation.param_env, predicate: obligation.predicate } } } - -#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] pub struct Response<'tcx> { pub var_values: CanonicalVarValues<'tcx>, /// Additional constraints returned by this query. @@ -121,14 +121,6 @@ pub enum MaybeCause { Overflow, } -/// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, TypeFoldable, TypeVisitable, Default)] -pub struct ExternalConstraints<'tcx> { - // FIXME: implement this. - regions: (), - opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>, -} - type CanonicalGoal<'tcx, T = ty::Predicate<'tcx>> = Canonical<'tcx, Goal<'tcx, T>>; type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>; /// The result of evaluating a canonical query. @@ -218,15 +210,14 @@ fn evaluate_canonical_goal( EvalCtxt { infcx, var_values, search_graph, in_projection_eq_hack: false }; let result = ecx.compute_goal(goal); - // FIXME: `Response` should be `Copy` - if search_graph.try_finalize_goal(tcx, canonical_goal, result.clone()) { + if search_graph.try_finalize_goal(tcx, canonical_goal, result) { return result; } } } fn make_canonical_response(&self, certainty: Certainty) -> QueryResult<'tcx> { - let external_constraints = take_external_constraints(self.infcx)?; + let external_constraints = compute_external_query_constraints(self.infcx)?; Ok(self.infcx.canonicalize_response(Response { var_values: self.var_values, @@ -461,18 +452,18 @@ fn evaluate_all_and_make_canonical_response( } #[instrument(level = "debug", skip(infcx), ret)] -fn take_external_constraints<'tcx>( +fn compute_external_query_constraints<'tcx>( infcx: &InferCtxt<'tcx>, ) -> Result, NoSolution> { let region_obligations = infcx.take_registered_region_obligations(); let opaque_types = infcx.take_opaque_types_for_query_response(); - Ok(ExternalConstraints { + Ok(infcx.tcx.intern_external_constraints(ExternalConstraintsData { // FIXME: Now that's definitely wrong :) // // Should also do the leak check here I think regions: drop(region_obligations), opaque_types, - }) + })) } fn instantiate_canonical_query_response<'tcx>( @@ -492,7 +483,10 @@ fn instantiate_canonical_query_response<'tcx>( Certainty::Yes => OldCertainty::Proven, Certainty::Maybe(_) => OldCertainty::Ambiguous, }, - opaque_types: resp.external_constraints.opaque_types, + // FIXME: This to_owned makes me sad, but we should eventually impl + // `instantiate_query_response_and_region_obligations` separately + // instead of piggybacking off of the old implementation. + opaque_types: resp.external_constraints.opaque_types.to_owned(), value: resp.certainty, }), ) else { bug!(); }; @@ -510,7 +504,10 @@ pub(super) fn response_no_constraints<'tcx>( variables: goal.variables, value: Response { var_values: CanonicalVarValues::make_identity(tcx, goal.variables), - external_constraints: Default::default(), + // FIXME: maybe we should store the "no response" version in tcx, like + // we do for tcx.types and stuff. + external_constraints: tcx + .intern_external_constraints(ExternalConstraintsData::default()), certainty, }, }) diff --git a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs index 80a388b8498..86b13c05f76 100644 --- a/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs +++ b/compiler/rustc_trait_selection/src/solve/search_graph/cache.rs @@ -95,8 +95,7 @@ pub(super) fn depth(&self, entry_index: EntryIndex) -> StackDepth { } pub(super) fn provisional_result(&self, entry_index: EntryIndex) -> QueryResult<'tcx> { - // FIXME: Responses should probably be `Copy` as well - self.entries[entry_index].response.clone() + self.entries[entry_index].response } } diff --git a/triagebot.toml b/triagebot.toml index 79958729fc5..9e37eccb6d3 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -250,7 +250,8 @@ new_pr = true [autolabel."WG-trait-system-refactor"] trigger_files = [ - "compiler/rustc_trait_selection/src/solve" + "compiler/rustc_trait_selection/src/solve", + "compiler/rustc_middle/src/traits/solve.rs" ] [notify-zulip."I-prioritize"]