Skip to content

Commit b8f60f3

Browse files
committed
Auto merge of #49800 - ishitatsuyuki:intern-goal, r=nikomatsakis
traits: Implement interning for Goal and Clause r? @nikomatsakis Close #49054 Contains some refactoring for the interning mechanism, mainly aimed at reducing pain when changing types of interning map. This should be mostly good, although I'm not sure with the naming of `Goal::from_poly_domain_goal`.
2 parents 99d4886 + b15df80 commit b8f60f3

File tree

5 files changed

+151
-59
lines changed

5 files changed

+151
-59
lines changed

src/librustc/traits/mod.rs

+21-20
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,12 @@ use infer::outlives::env::OutlivesEnvironment;
2323
use middle::region;
2424
use middle::const_val::ConstEvalErr;
2525
use ty::subst::Substs;
26-
use ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, ToPredicate};
26+
use ty::{self, AdtKind, Slice, Ty, TyCtxt, TypeFoldable, ToPredicate};
2727
use ty::error::{ExpectedFound, TypeError};
2828
use infer::{InferCtxt};
2929

3030
use rustc_data_structures::sync::Lrc;
3131
use std::rc::Rc;
32-
use std::convert::From;
3332
use syntax::ast;
3433
use syntax_pos::{Span, DUMMY_SP};
3534

@@ -280,37 +279,39 @@ pub enum QuantifierKind {
280279
Existential,
281280
}
282281

283-
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
282+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
284283
pub enum Goal<'tcx> {
285-
// FIXME: use interned refs instead of `Box`
286-
Implies(Vec<Clause<'tcx>>, Box<Goal<'tcx>>),
287-
And(Box<Goal<'tcx>>, Box<Goal<'tcx>>),
288-
Not(Box<Goal<'tcx>>),
284+
Implies(&'tcx Slice<Clause<'tcx>>, &'tcx Goal<'tcx>),
285+
And(&'tcx Goal<'tcx>, &'tcx Goal<'tcx>),
286+
Not(&'tcx Goal<'tcx>),
289287
DomainGoal(DomainGoal<'tcx>),
290-
Quantified(QuantifierKind, Box<ty::Binder<Goal<'tcx>>>)
291-
}
292-
293-
impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
294-
fn from(domain_goal: DomainGoal<'tcx>) -> Self {
295-
Goal::DomainGoal(domain_goal)
296-
}
288+
Quantified(QuantifierKind, ty::Binder<&'tcx Goal<'tcx>>)
297289
}
298290

299-
impl<'tcx> From<PolyDomainGoal<'tcx>> for Goal<'tcx> {
300-
fn from(domain_goal: PolyDomainGoal<'tcx>) -> Self {
291+
impl<'tcx> Goal<'tcx> {
292+
pub fn from_poly_domain_goal<'a>(
293+
domain_goal: PolyDomainGoal<'tcx>,
294+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
295+
) -> Goal<'tcx> {
301296
match domain_goal.no_late_bound_regions() {
302297
Some(p) => p.into(),
303298
None => Goal::Quantified(
304299
QuantifierKind::Universal,
305-
Box::new(domain_goal.map_bound(|p| p.into()))
300+
domain_goal.map_bound(|p| tcx.mk_goal(Goal::from(p)))
306301
),
307302
}
308303
}
309304
}
310305

306+
impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
307+
fn from(domain_goal: DomainGoal<'tcx>) -> Self {
308+
Goal::DomainGoal(domain_goal)
309+
}
310+
}
311+
311312
/// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
312313
/// Harrop Formulas".
313-
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
314+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
314315
pub enum Clause<'tcx> {
315316
Implies(ProgramClause<'tcx>),
316317
ForAll(ty::Binder<ProgramClause<'tcx>>),
@@ -322,13 +323,13 @@ pub enum Clause<'tcx> {
322323
/// it with the reverse implication operator `:-` to emphasize the way
323324
/// that programs are actually solved (via backchaining, which starts
324325
/// with the goal to solve and proceeds from there).
325-
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
326+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
326327
pub struct ProgramClause<'tcx> {
327328
/// This goal will be considered true...
328329
pub goal: DomainGoal<'tcx>,
329330

330331
/// ...if we can prove these hypotheses (there may be no hypotheses at all):
331-
pub hypotheses: Vec<Goal<'tcx>>,
332+
pub hypotheses: &'tcx Slice<Goal<'tcx>>,
332333
}
333334

334335
pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;

src/librustc/traits/structural_impls.rs

+34
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use rustc_data_structures::accumulate_vec::AccumulateVec;
1112
use traits;
1213
use traits::project::Normalized;
1314
use ty::{self, Lift, TyCtxt};
@@ -557,6 +558,28 @@ EnumTypeFoldableImpl! {
557558
}
558559
}
559560

561+
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Goal<'tcx>> {
562+
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
563+
let v = self.iter().map(|t| t.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
564+
folder.tcx().intern_goals(&v)
565+
}
566+
567+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
568+
self.iter().any(|t| t.visit_with(visitor))
569+
}
570+
}
571+
572+
impl<'tcx> TypeFoldable<'tcx> for &'tcx traits::Goal<'tcx> {
573+
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
574+
let v = (**self).fold_with(folder);
575+
folder.tcx().mk_goal(v)
576+
}
577+
578+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
579+
(**self).visit_with(visitor)
580+
}
581+
}
582+
560583
BraceStructTypeFoldableImpl! {
561584
impl<'tcx> TypeFoldable<'tcx> for traits::ProgramClause<'tcx> {
562585
goal,
@@ -570,3 +593,14 @@ EnumTypeFoldableImpl! {
570593
(traits::Clause::ForAll)(clause),
571594
}
572595
}
596+
597+
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<traits::Clause<'tcx>> {
598+
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
599+
let v = self.iter().map(|t| t.fold_with(folder)).collect::<AccumulateVec<[_; 8]>>();
600+
folder.tcx().intern_clauses(&v)
601+
}
602+
603+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
604+
self.iter().any(|t| t.visit_with(visitor))
605+
}
606+
}

src/librustc/ty/context.rs

+71-18
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use ty::subst::{Kind, Substs};
3838
use ty::ReprOptions;
3939
use ty::Instance;
4040
use traits;
41+
use traits::{Clause, Goal};
4142
use ty::{self, Ty, TypeAndMut};
4243
use ty::{TyS, TypeVariants, Slice};
4344
use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorInterior, Region, Const};
@@ -125,34 +126,40 @@ impl<'tcx> GlobalArenas<'tcx> {
125126
}
126127
}
127128

129+
type InternedSet<'tcx, T> = Lock<FxHashSet<Interned<'tcx, T>>>;
130+
128131
pub struct CtxtInterners<'tcx> {
129132
/// The arena that types, regions, etc are allocated from
130133
arena: &'tcx DroplessArena,
131134

132135
/// Specifically use a speedy hash algorithm for these hash sets,
133136
/// they're accessed quite often.
134-
type_: Lock<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
135-
type_list: Lock<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
136-
substs: Lock<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
137-
canonical_var_infos: Lock<FxHashSet<Interned<'tcx, Slice<CanonicalVarInfo>>>>,
138-
region: Lock<FxHashSet<Interned<'tcx, RegionKind>>>,
139-
existential_predicates: Lock<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
140-
predicates: Lock<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
141-
const_: Lock<FxHashSet<Interned<'tcx, Const<'tcx>>>>,
137+
type_: InternedSet<'tcx, TyS<'tcx>>,
138+
type_list: InternedSet<'tcx, Slice<Ty<'tcx>>>,
139+
substs: InternedSet<'tcx, Substs<'tcx>>,
140+
canonical_var_infos: InternedSet<'tcx, Slice<CanonicalVarInfo>>,
141+
region: InternedSet<'tcx, RegionKind>,
142+
existential_predicates: InternedSet<'tcx, Slice<ExistentialPredicate<'tcx>>>,
143+
predicates: InternedSet<'tcx, Slice<Predicate<'tcx>>>,
144+
const_: InternedSet<'tcx, Const<'tcx>>,
145+
clauses: InternedSet<'tcx, Slice<Clause<'tcx>>>,
146+
goals: InternedSet<'tcx, Slice<Goal<'tcx>>>,
142147
}
143148

144149
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
145150
fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
146151
CtxtInterners {
147-
arena: arena,
148-
type_: Lock::new(FxHashSet()),
149-
type_list: Lock::new(FxHashSet()),
150-
substs: Lock::new(FxHashSet()),
151-
canonical_var_infos: Lock::new(FxHashSet()),
152-
region: Lock::new(FxHashSet()),
153-
existential_predicates: Lock::new(FxHashSet()),
154-
predicates: Lock::new(FxHashSet()),
155-
const_: Lock::new(FxHashSet()),
152+
arena,
153+
type_: Default::default(),
154+
type_list: Default::default(),
155+
substs: Default::default(),
156+
region: Default::default(),
157+
existential_predicates: Default::default(),
158+
canonical_var_infos: Default::default(),
159+
predicates: Default::default(),
160+
const_: Default::default(),
161+
clauses: Default::default(),
162+
goals: Default::default(),
156163
}
157164
}
158165

@@ -2099,6 +2106,20 @@ impl<'tcx: 'lcx, 'lcx> Borrow<Const<'lcx>> for Interned<'tcx, Const<'tcx>> {
20992106
}
21002107
}
21012108

2109+
impl<'tcx: 'lcx, 'lcx> Borrow<[Clause<'lcx>]>
2110+
for Interned<'tcx, Slice<Clause<'tcx>>> {
2111+
fn borrow<'a>(&'a self) -> &'a [Clause<'lcx>] {
2112+
&self.0[..]
2113+
}
2114+
}
2115+
2116+
impl<'tcx: 'lcx, 'lcx> Borrow<[Goal<'lcx>]>
2117+
for Interned<'tcx, Slice<Goal<'tcx>>> {
2118+
fn borrow<'a>(&'a self) -> &'a [Goal<'lcx>] {
2119+
&self.0[..]
2120+
}
2121+
}
2122+
21022123
macro_rules! intern_method {
21032124
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
21042125
$alloc_method:ident,
@@ -2196,7 +2217,9 @@ slice_interners!(
21962217
existential_predicates: _intern_existential_predicates(ExistentialPredicate),
21972218
predicates: _intern_predicates(Predicate),
21982219
type_list: _intern_type_list(Ty),
2199-
substs: _intern_substs(Kind)
2220+
substs: _intern_substs(Kind),
2221+
clauses: _intern_clauses(Clause),
2222+
goals: _intern_goals(Goal)
22002223
);
22012224

22022225
// This isn't a perfect fit: CanonicalVarInfo slices are always
@@ -2501,6 +2524,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
25012524
}
25022525
}
25032526

2527+
pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> &'tcx Slice<Clause<'tcx>> {
2528+
if ts.len() == 0 {
2529+
Slice::empty()
2530+
} else {
2531+
self._intern_clauses(ts)
2532+
}
2533+
}
2534+
2535+
pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> &'tcx Slice<Goal<'tcx>> {
2536+
if ts.len() == 0 {
2537+
Slice::empty()
2538+
} else {
2539+
self._intern_goals(ts)
2540+
}
2541+
}
2542+
25042543
pub fn mk_fn_sig<I>(self,
25052544
inputs: I,
25062545
output: I::Item,
@@ -2547,6 +2586,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
25472586
self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
25482587
}
25492588

2589+
pub fn mk_clauses<I: InternAs<[Clause<'tcx>],
2590+
&'tcx Slice<Clause<'tcx>>>>(self, iter: I) -> I::Output {
2591+
iter.intern_with(|xs| self.intern_clauses(xs))
2592+
}
2593+
2594+
pub fn mk_goals<I: InternAs<[Goal<'tcx>],
2595+
&'tcx Slice<Goal<'tcx>>>>(self, iter: I) -> I::Output {
2596+
iter.intern_with(|xs| self.intern_goals(xs))
2597+
}
2598+
2599+
pub fn mk_goal(self, goal: Goal<'tcx>) -> &'tcx Goal {
2600+
&self.mk_goals(iter::once(goal))[0]
2601+
}
2602+
25502603
pub fn lint_node<S: Into<MultiSpan>>(self,
25512604
lint: &'static Lint,
25522605
id: NodeId,

src/librustc/ty/maps/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
3939
use traits::query::normalize::NormalizationResult;
4040
use traits::specialization_graph;
4141
use traits::Clause;
42-
use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
42+
use ty::{self, CrateInherentImpls, ParamEnvAnd, Slice, Ty, TyCtxt};
4343
use ty::steal::Steal;
4444
use ty::subst::Substs;
4545
use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
@@ -445,7 +445,7 @@ define_maps! { <'tcx>
445445

446446
[] fn features_query: features_node(CrateNum) -> Lrc<feature_gate::Features>,
447447

448-
[] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<Vec<Clause<'tcx>>>,
448+
[] fn program_clauses_for: ProgramClausesFor(DefId) -> Lrc<&'tcx Slice<Clause<'tcx>>>,
449449

450450
[] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>,
451451
[] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)

0 commit comments

Comments
 (0)