Skip to content

Commit b15df80

Browse files
committed
traits: Implement interning for Goal and Clause
1 parent d26f9e4 commit b15df80

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

@@ -2088,6 +2095,20 @@ impl<'tcx: 'lcx, 'lcx> Borrow<Const<'lcx>> for Interned<'tcx, Const<'tcx>> {
20882095
}
20892096
}
20902097

2098+
impl<'tcx: 'lcx, 'lcx> Borrow<[Clause<'lcx>]>
2099+
for Interned<'tcx, Slice<Clause<'tcx>>> {
2100+
fn borrow<'a>(&'a self) -> &'a [Clause<'lcx>] {
2101+
&self.0[..]
2102+
}
2103+
}
2104+
2105+
impl<'tcx: 'lcx, 'lcx> Borrow<[Goal<'lcx>]>
2106+
for Interned<'tcx, Slice<Goal<'tcx>>> {
2107+
fn borrow<'a>(&'a self) -> &'a [Goal<'lcx>] {
2108+
&self.0[..]
2109+
}
2110+
}
2111+
20912112
macro_rules! intern_method {
20922113
($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
20932114
$alloc_method:ident,
@@ -2185,7 +2206,9 @@ slice_interners!(
21852206
existential_predicates: _intern_existential_predicates(ExistentialPredicate),
21862207
predicates: _intern_predicates(Predicate),
21872208
type_list: _intern_type_list(Ty),
2188-
substs: _intern_substs(Kind)
2209+
substs: _intern_substs(Kind),
2210+
clauses: _intern_clauses(Clause),
2211+
goals: _intern_goals(Goal)
21892212
);
21902213

21912214
// This isn't a perfect fit: CanonicalVarInfo slices are always
@@ -2490,6 +2513,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
24902513
}
24912514
}
24922515

2516+
pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> &'tcx Slice<Clause<'tcx>> {
2517+
if ts.len() == 0 {
2518+
Slice::empty()
2519+
} else {
2520+
self._intern_clauses(ts)
2521+
}
2522+
}
2523+
2524+
pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> &'tcx Slice<Goal<'tcx>> {
2525+
if ts.len() == 0 {
2526+
Slice::empty()
2527+
} else {
2528+
self._intern_goals(ts)
2529+
}
2530+
}
2531+
24932532
pub fn mk_fn_sig<I>(self,
24942533
inputs: I,
24952534
output: I::Item,
@@ -2536,6 +2575,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
25362575
self.mk_substs(iter::once(s).chain(t.into_iter().cloned()).map(Kind::from))
25372576
}
25382577

2578+
pub fn mk_clauses<I: InternAs<[Clause<'tcx>],
2579+
&'tcx Slice<Clause<'tcx>>>>(self, iter: I) -> I::Output {
2580+
iter.intern_with(|xs| self.intern_clauses(xs))
2581+
}
2582+
2583+
pub fn mk_goals<I: InternAs<[Goal<'tcx>],
2584+
&'tcx Slice<Goal<'tcx>>>>(self, iter: I) -> I::Output {
2585+
iter.intern_with(|xs| self.intern_goals(xs))
2586+
}
2587+
2588+
pub fn mk_goal(self, goal: Goal<'tcx>) -> &'tcx Goal {
2589+
&self.mk_goals(iter::once(goal))[0]
2590+
}
2591+
25392592
pub fn lint_node<S: Into<MultiSpan>>(self,
25402593
lint: &'static Lint,
25412594
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};
@@ -435,7 +435,7 @@ define_maps! { <'tcx>
435435

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

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

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

0 commit comments

Comments
 (0)