Skip to content

Commit 1271f0b

Browse files
committed
Add MVP for chalkification
1 parent 8c4ff22 commit 1271f0b

File tree

12 files changed

+519
-0
lines changed

12 files changed

+519
-0
lines changed

src/librustc/dep_graph/dep_node.rs

+2
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,8 @@ define_dep_nodes!( <'tcx>
648648
[] GetSymbolExportLevel(DefId),
649649

650650
[input] Features,
651+
652+
[] ProgramClausesFor(DefId),
651653
);
652654

653655
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {

src/librustc/ich/impls_ty.rs

+83
Original file line numberDiff line numberDiff line change
@@ -1286,3 +1286,86 @@ impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> {
12861286
impl_stable_hash_for!(enum infer::canonical::Certainty {
12871287
Proven, Ambiguous
12881288
});
1289+
1290+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::WhereClauseAtom<'tcx> {
1291+
fn hash_stable<W: StableHasherResult>(&self,
1292+
hcx: &mut StableHashingContext<'a>,
1293+
hasher: &mut StableHasher<W>) {
1294+
use traits::WhereClauseAtom::*;
1295+
1296+
mem::discriminant(self).hash_stable(hcx, hasher);
1297+
match *self {
1298+
Implemented(ref trait_ref) => trait_ref.hash_stable(hcx, hasher),
1299+
ProjectionEq(ref projection) => projection.hash_stable(hcx, hasher),
1300+
}
1301+
}
1302+
}
1303+
1304+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::DomainGoal<'tcx> {
1305+
fn hash_stable<W: StableHasherResult>(&self,
1306+
hcx: &mut StableHashingContext<'a>,
1307+
hasher: &mut StableHasher<W>) {
1308+
use traits::DomainGoal::*;
1309+
1310+
mem::discriminant(self).hash_stable(hcx, hasher);
1311+
match *self {
1312+
Holds(ref where_clause) |
1313+
WellFormed(ref where_clause) |
1314+
FromEnv(ref where_clause) => where_clause.hash_stable(hcx, hasher),
1315+
1316+
WellFormedTy(ref ty) => ty.hash_stable(hcx, hasher),
1317+
FromEnvTy(ref ty) => ty.hash_stable(hcx, hasher),
1318+
RegionOutlives(ref predicate) => predicate.hash_stable(hcx, hasher),
1319+
TypeOutlives(ref predicate) => predicate.hash_stable(hcx, hasher),
1320+
}
1321+
}
1322+
}
1323+
1324+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::LeafGoal<'tcx> {
1325+
fn hash_stable<W: StableHasherResult>(&self,
1326+
hcx: &mut StableHashingContext<'a>,
1327+
hasher: &mut StableHasher<W>) {
1328+
use traits::LeafGoal::*;
1329+
1330+
mem::discriminant(self).hash_stable(hcx, hasher);
1331+
match *self {
1332+
DomainGoal(ref domain_goal) => domain_goal.hash_stable(hcx, hasher),
1333+
}
1334+
}
1335+
}
1336+
1337+
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Goal<'tcx> {
1338+
fn hash_stable<W: StableHasherResult>(&self,
1339+
hcx: &mut StableHashingContext<'a>,
1340+
hasher: &mut StableHasher<W>) {
1341+
use traits::Goal::*;
1342+
1343+
mem::discriminant(self).hash_stable(hcx, hasher);
1344+
match *self {
1345+
Implies(ref hypotheses, ref goal) => {
1346+
hypotheses.hash_stable(hcx, hasher);
1347+
goal.hash_stable(hcx, hasher);
1348+
},
1349+
And(ref goal1, ref goal2) => {
1350+
goal1.hash_stable(hcx, hasher);
1351+
goal2.hash_stable(hcx, hasher);
1352+
}
1353+
Not(ref goal) => goal.hash_stable(hcx, hasher),
1354+
Leaf(ref leaf_goal) => leaf_goal.hash_stable(hcx, hasher),
1355+
Quantified(quantifier, ref goal) => {
1356+
quantifier.hash_stable(hcx, hasher);
1357+
goal.hash_stable(hcx, hasher);
1358+
},
1359+
}
1360+
}
1361+
}
1362+
1363+
impl_stable_hash_for!(enum traits::QuantifierKind {
1364+
Universal,
1365+
Existential
1366+
});
1367+
1368+
impl_stable_hash_for!(struct traits::ProgramClause<'tcx> {
1369+
consequence,
1370+
conditions
1371+
});

src/librustc/traits/lowering.rs

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use hir::{self, ImplPolarity};
12+
use hir::def_id::DefId;
13+
use hir::intravisit::{self, NestedVisitorMap, Visitor};
14+
use ty::{self, PolyTraitPredicate, TraitPredicate, PolyProjectionPredicate, TyCtxt, Predicate};
15+
use super::{DomainGoal, ProgramClause, WhereClauseAtom};
16+
use rustc_data_structures::sync::Lrc;
17+
use syntax::ast;
18+
19+
trait Lower<T> {
20+
fn lower(&self) -> T;
21+
}
22+
23+
impl<T, U> Lower<Vec<U>> for Vec<T> where T: Lower<U> {
24+
fn lower(&self) -> Vec<U> {
25+
self.iter().map(|item| item.lower()).collect()
26+
}
27+
}
28+
29+
impl<'tcx> Lower<WhereClauseAtom<'tcx>> for PolyTraitPredicate<'tcx> {
30+
fn lower(&self) -> WhereClauseAtom<'tcx> {
31+
WhereClauseAtom::Implemented(*self)
32+
}
33+
}
34+
35+
impl<'tcx> Lower<WhereClauseAtom<'tcx>> for PolyProjectionPredicate<'tcx> {
36+
fn lower(&self) -> WhereClauseAtom<'tcx> {
37+
WhereClauseAtom::ProjectionEq(*self)
38+
}
39+
}
40+
41+
impl<'tcx, T> Lower<DomainGoal<'tcx>> for T where T: Lower<WhereClauseAtom<'tcx>> {
42+
fn lower(&self) -> DomainGoal<'tcx> {
43+
DomainGoal::Holds(self.lower())
44+
}
45+
}
46+
47+
impl<'tcx> Lower<DomainGoal<'tcx>> for Predicate<'tcx> {
48+
fn lower(&self) -> DomainGoal<'tcx> {
49+
use self::Predicate::*;
50+
51+
match *self {
52+
Trait(predicate) => predicate.lower(),
53+
RegionOutlives(predicate) => DomainGoal::RegionOutlives(predicate),
54+
TypeOutlives(predicate) => DomainGoal::TypeOutlives(predicate),
55+
Projection(predicate) => predicate.lower(),
56+
WellFormed(ty) => DomainGoal::WellFormedTy(ty),
57+
ObjectSafe(..) |
58+
ClosureKind(..) |
59+
Subtype(..) |
60+
ConstEvaluatable(..) => unimplemented!(),
61+
62+
}
63+
}
64+
}
65+
66+
pub fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
67+
-> Lrc<Vec<ProgramClause<'tcx>>>
68+
{
69+
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
70+
let item = tcx.hir.expect_item(node_id);
71+
match item.node {
72+
hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
73+
_ => Lrc::new(vec![]),
74+
}
75+
}
76+
77+
fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
78+
-> Lrc<Vec<ProgramClause<'tcx>>>
79+
{
80+
if let ImplPolarity::Negative = tcx.impl_polarity(def_id) {
81+
return Lrc::new(vec![]);
82+
}
83+
84+
let trait_ref = tcx.impl_trait_ref(def_id).unwrap();
85+
let trait_ref = ty::Binder(TraitPredicate { trait_ref }).lower();
86+
let where_clauses = tcx.predicates_of(def_id).predicates.lower();
87+
88+
let clause = ProgramClause {
89+
consequence: trait_ref,
90+
conditions: where_clauses.into_iter().map(|wc| wc.into()).collect(),
91+
};
92+
93+
Lrc::new(vec![clause])
94+
}
95+
96+
pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
97+
if !tcx.features().rustc_attrs {
98+
return;
99+
}
100+
101+
let mut visitor = ClauseDumper { tcx };
102+
tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
103+
}
104+
105+
struct ClauseDumper<'a, 'tcx: 'a> {
106+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
107+
}
108+
109+
impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
110+
fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
111+
let def_id = self.tcx.hir.local_def_id(node_id);
112+
for attr in attrs {
113+
if attr.check_name("rustc_dump_program_clauses") {
114+
let clauses = self.tcx.program_clauses_for(def_id);
115+
for clause in &*clauses {
116+
self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
117+
}
118+
}
119+
}
120+
}
121+
}
122+
123+
impl<'a, 'tcx> Visitor<'tcx> for ClauseDumper<'a, 'tcx> {
124+
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
125+
NestedVisitorMap::OnlyBodies(&self.tcx.hir)
126+
}
127+
128+
fn visit_item(&mut self, item: &'tcx hir::Item) {
129+
self.process_attrs(item.id, &item.attrs);
130+
intravisit::walk_item(self, item);
131+
}
132+
133+
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
134+
self.process_attrs(trait_item.id, &trait_item.attrs);
135+
intravisit::walk_trait_item(self, trait_item);
136+
}
137+
138+
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
139+
self.process_attrs(impl_item.id, &impl_item.attrs);
140+
intravisit::walk_impl_item(self, impl_item);
141+
}
142+
143+
fn visit_struct_field(&mut self, s: &'tcx hir::StructField) {
144+
self.process_attrs(s.id, &s.attrs);
145+
intravisit::walk_struct_field(self, s);
146+
}
147+
}

src/librustc/traits/mod.rs

+56
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use infer::{InferCtxt};
2929

3030
use rustc_data_structures::sync::Lrc;
3131
use std::rc::Rc;
32+
use std::convert::From;
3233
use syntax::ast;
3334
use syntax_pos::{Span, DUMMY_SP};
3435

@@ -62,6 +63,7 @@ mod specialize;
6263
mod structural_impls;
6364
pub mod trans;
6465
mod util;
66+
mod lowering;
6567

6668
pub mod query;
6769

@@ -244,6 +246,59 @@ pub type Obligations<'tcx, O> = Vec<Obligation<'tcx, O>>;
244246
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
245247
pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
246248

249+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
250+
pub enum WhereClauseAtom<'tcx> {
251+
Implemented(ty::PolyTraitPredicate<'tcx>),
252+
ProjectionEq(ty::PolyProjectionPredicate<'tcx>),
253+
}
254+
255+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
256+
pub enum DomainGoal<'tcx> {
257+
Holds(WhereClauseAtom<'tcx>),
258+
WellFormed(WhereClauseAtom<'tcx>),
259+
FromEnv(WhereClauseAtom<'tcx>),
260+
WellFormedTy(Ty<'tcx>),
261+
FromEnvTy(Ty<'tcx>),
262+
RegionOutlives(ty::PolyRegionOutlivesPredicate<'tcx>),
263+
TypeOutlives(ty::PolyTypeOutlivesPredicate<'tcx>),
264+
}
265+
266+
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
267+
pub enum LeafGoal<'tcx> {
268+
DomainGoal(DomainGoal<'tcx>),
269+
}
270+
271+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
272+
pub enum QuantifierKind {
273+
Universal,
274+
Existential,
275+
}
276+
277+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
278+
pub enum Goal<'tcx> {
279+
Implies(Vec<DomainGoal<'tcx>>, Box<Goal<'tcx>>),
280+
And(Box<Goal<'tcx>>, Box<Goal<'tcx>>),
281+
Not(Box<Goal<'tcx>>),
282+
Leaf(LeafGoal<'tcx>),
283+
Quantified(QuantifierKind, Box<ty::Binder<Goal<'tcx>>>)
284+
}
285+
286+
impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
287+
fn from(domain_goal: DomainGoal<'tcx>) -> Self {
288+
Goal::Leaf(LeafGoal::DomainGoal(domain_goal))
289+
}
290+
}
291+
292+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
293+
pub struct ProgramClause<'tcx> {
294+
pub consequence: DomainGoal<'tcx>,
295+
pub conditions: Vec<Goal<'tcx>>,
296+
}
297+
298+
pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
299+
lowering::dump_program_clauses(tcx)
300+
}
301+
247302
pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
248303

249304
#[derive(Clone,Debug)]
@@ -915,6 +970,7 @@ pub fn provide(providers: &mut ty::maps::Providers) {
915970
specialization_graph_of: specialize::specialization_graph_provider,
916971
specializes: specialize::specializes,
917972
trans_fulfill_obligation: trans::trans_fulfill_obligation,
973+
program_clauses_for: lowering::program_clauses_for,
918974
vtable_methods,
919975
substitute_normalize_and_test_predicates,
920976
..*providers

0 commit comments

Comments
 (0)