Skip to content

Commit 294cae2

Browse files
committed
first draft of program_clauses_for_env
This computes the transitive closure of traits that appear in the environment and then appends their clauses. It needs some work, but it's in the right direction.
1 parent 7173fd7 commit 294cae2

File tree

10 files changed

+145
-18
lines changed

10 files changed

+145
-18
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ define_dep_nodes!( <'tcx>
655655
[input] Features,
656656

657657
[] ProgramClausesFor(DefId),
658+
[] ProgramClausesForEnv(ParamEnv<'tcx>),
658659
[] WasmImportModuleMap(CrateNum),
659660
[] ForeignModules(CrateNum),
660661

src/librustc/ty/maps/config.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
717717
}
718718
}
719719

720+
impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> {
721+
fn describe(_tcx: TyCtxt, _: ty::ParamEnv<'tcx>) -> String {
722+
format!("generating chalk-style clauses for param env")
723+
}
724+
}
725+
720726
impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> {
721727
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
722728
format!("wasm import module map")

src/librustc/ty/maps/keys.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ impl<'tcx> Key for Ty<'tcx> {
154154
}
155155
}
156156

157+
impl<'tcx> Key for ty::ParamEnv<'tcx> {
158+
fn map_crate(&self) -> CrateNum {
159+
LOCAL_CRATE
160+
}
161+
fn default_span(&self, _: TyCtxt) -> Span {
162+
DUMMY_SP
163+
}
164+
}
165+
157166
impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
158167
fn map_crate(&self) -> CrateNum {
159168
self.value.map_crate()

src/librustc/ty/maps/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,10 @@ define_maps! { <'tcx>
447447

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

450+
[] fn program_clauses_for_env: ProgramClausesForEnv(
451+
ty::ParamEnv<'tcx>
452+
) -> Lrc<&'tcx Slice<Clause<'tcx>>>,
453+
450454
[] fn wasm_custom_sections: WasmCustomSections(CrateNum) -> Lrc<Vec<DefId>>,
451455
[] fn wasm_import_module_map: WasmImportModuleMap(CrateNum)
452456
-> Lrc<FxHashMap<DefId, String>>,

src/librustc/ty/maps/plumbing.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
978978
DepKind::DropckOutlives |
979979
DepKind::SubstituteNormalizeAndTestPredicates |
980980
DepKind::InstanceDefSizeEstimate |
981+
DepKind::ProgramClausesForEnv |
981982

982983
// This one should never occur in this context
983984
DepKind::Null => {

src/librustc/ty/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,11 @@ pub struct ProjectionPredicate<'tcx> {
11381138
pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
11391139

11401140
impl<'tcx> PolyProjectionPredicate<'tcx> {
1141+
/// Returns the def-id of the associated item being projected.
1142+
pub fn item_def_id(&self) -> DefId {
1143+
self.skip_binder().projection_ty.item_def_id
1144+
}
1145+
11411146
pub fn to_poly_trait_ref(&self, tcx: TyCtxt) -> PolyTraitRef<'tcx> {
11421147
// Note: unlike with TraitRef::to_poly_trait_ref(),
11431148
// self.0.trait_ref is permitted to have escaping regions.

src/librustc_traits/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub fn provide(p: &mut Providers) {
3737
normalize_ty_after_erasing_regions:
3838
normalize_erasing_regions::normalize_ty_after_erasing_regions,
3939
program_clauses_for: lowering::program_clauses_for,
40+
program_clauses_for_env: lowering::program_clauses_for_env,
4041
..*p
4142
};
4243
}

src/librustc_traits/lowering.rs

Lines changed: 70 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@
1010

1111
use rustc::hir::def_id::DefId;
1212
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
13+
use rustc::hir::map::definitions::DefPathData;
14+
use rustc::hir::{self, ImplPolarity};
1315
use rustc::traits::{Clause, DomainGoal, Goal, PolyDomainGoal, ProgramClause, WhereClauseAtom};
1416
use rustc::ty::subst::Substs;
1517
use rustc::ty::{self, Slice, TyCtxt};
18+
use rustc_data_structures::fx::FxHashSet;
1619
use rustc_data_structures::sync::Lrc;
17-
use syntax::ast;
20+
use std::mem;
1821
use syntax::ast;
1922

2023
use std::iter;
@@ -120,24 +123,73 @@ crate fn program_clauses_for<'a, 'tcx>(
120123
tcx: TyCtxt<'a, 'tcx, 'tcx>,
121124
def_id: DefId,
122125
) -> Lrc<&'tcx Slice<Clause<'tcx>>> {
123-
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
124-
let node = tcx.hir.find(node_id).unwrap();
125-
match node {
126-
hir::map::Node::NodeItem(item) => match item.node {
127-
hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
128-
hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
129-
_ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
130-
},
131-
hir::map::Node::NodeImplItem(item) => {
132-
if let hir::ImplItemKind::Type(..) = item.node {
133-
program_clauses_for_associated_type_value(tcx, def_id)
134-
} else {
135-
Lrc::new(tcx.mk_clauses(iter::empty::<Clause>()))
136-
}
137-
}
126+
match tcx.def_key(def_id).disambiguated_data.data {
127+
DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
128+
DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
129+
DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
130+
_ => Lrc::new(Slice::empty()),
131+
}
132+
}
133+
134+
crate fn program_clauses_for_env<'a, 'tcx>(
135+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
136+
param_env: ty::ParamEnv<'tcx>,
137+
) -> Lrc<&'tcx Slice<Clause<'tcx>>> {
138+
debug!("program_clauses_for_env(param_env={:?})", param_env);
139+
140+
let mut last_round = FxHashSet();
141+
last_round.extend(
142+
param_env
143+
.caller_bounds
144+
.iter()
145+
.flat_map(|&p| predicate_def_id(p)),
146+
);
147+
148+
let mut closure = last_round.clone();
149+
let mut next_round = FxHashSet();
150+
while !last_round.is_empty() {
151+
next_round.extend(
152+
last_round
153+
.drain()
154+
.flat_map(|def_id| {
155+
tcx.predicates_of(def_id)
156+
.instantiate_identity(tcx)
157+
.predicates
158+
})
159+
.flat_map(|p| predicate_def_id(p))
160+
.filter(|&def_id| closure.insert(def_id)),
161+
);
162+
mem::swap(&mut next_round, &mut last_round);
163+
}
164+
165+
debug!("program_clauses_for_env: closure = {:#?}", closure);
138166

139-
// FIXME: other constructions e.g. traits, associated types...
140-
_ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
167+
return Lrc::new(
168+
tcx.mk_clauses(
169+
closure
170+
.into_iter()
171+
.flat_map(|def_id| tcx.program_clauses_for(def_id).iter().cloned()),
172+
),
173+
);
174+
175+
/// Given that `predicate` is in the environment, returns the
176+
/// def-id of something (e.g., a trait, associated item, etc)
177+
/// whose predicates can also be assumed to be true. We will
178+
/// compute the transitive closure of such things.
179+
fn predicate_def_id<'tcx>(predicate: ty::Predicate<'tcx>) -> Option<DefId> {
180+
match predicate {
181+
ty::Predicate::Trait(predicate) => Some(predicate.def_id()),
182+
183+
ty::Predicate::Projection(projection) => Some(projection.item_def_id()),
184+
185+
ty::Predicate::WellFormed(..)
186+
| ty::Predicate::RegionOutlives(..)
187+
| ty::Predicate::TypeOutlives(..)
188+
| ty::Predicate::ObjectSafe(..)
189+
| ty::Predicate::ClosureKind(..)
190+
| ty::Predicate::Subtype(..)
191+
| ty::Predicate::ConstEvaluatable(..) => None,
192+
}
141193
}
142194
}
143195

src/test/ui/chalkify/lower_env1.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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+
#![feature(rustc_attrs)]
12+
#![allow(dead_code)]
13+
14+
trait Foo { }
15+
16+
#[rustc_dump_program_clauses] //~ ERROR program clause dump
17+
trait Bar where Self: Foo { }
18+
19+
#[rustc_dump_env_program_clauses] //~ ERROR program clause dump
20+
fn bar<T: Bar>() {
21+
}
22+
23+
fn main() {
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: program clause dump
2+
--> $DIR/lower_env1.rs:16:1
3+
|
4+
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
8+
= note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
9+
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
10+
11+
error: program clause dump
12+
--> $DIR/lower_env1.rs:19:1
13+
|
14+
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
= note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
18+
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
19+
= note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
20+
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
21+
= note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
22+
23+
error: aborting due to 2 previous errors
24+

0 commit comments

Comments
 (0)