Skip to content

Commit dbab381

Browse files
committedOct 19, 2018
Auto merge of #55040 - scalexm:param-env, r=nikomatsakis
Replace `ParamEnv` with a new type in chalk context. I left a few FIXMEs. r? @nikomatsakis
·
1.88.01.31.0
2 parents cb5e1b9 + 55ce7a2 commit dbab381

File tree

16 files changed

+553
-116
lines changed

16 files changed

+553
-116
lines changed
 

‎src/librustc/dep_graph/dep_node.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
7070
use std::fmt;
7171
use std::hash::Hash;
7272
use syntax_pos::symbol::InternedString;
73+
use traits;
7374
use traits::query::{
7475
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal,
7576
CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
@@ -550,6 +551,7 @@ define_dep_nodes!( <'tcx>
550551
[anon] TraitSelect,
551552

552553
[] ParamEnv(DefId),
554+
[] Environment(DefId),
553555
[] DescribeDef(DefId),
554556

555557
// FIXME(mw): DefSpans are not really inputs since they are derived from
@@ -669,7 +671,7 @@ define_dep_nodes!( <'tcx>
669671
[input] Features,
670672

671673
[] ProgramClausesFor(DefId),
672-
[] ProgramClausesForEnv(ParamEnv<'tcx>),
674+
[] ProgramClausesForEnv(traits::Environment<'tcx>),
673675
[] WasmImportModuleMap(CrateNum),
674676
[] ForeignModules(CrateNum),
675677

‎src/librustc/ich/impls_ty.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1395,10 +1395,16 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Goal<'tcx> {
13951395

13961396
impl_stable_hash_for!(
13971397
impl<'tcx> for struct traits::ProgramClause<'tcx> {
1398-
goal, hypotheses
1398+
goal, hypotheses, category
13991399
}
14001400
);
14011401

1402+
impl_stable_hash_for!(enum traits::ProgramClauseCategory {
1403+
ImpliedBound,
1404+
WellFormed,
1405+
Other,
1406+
});
1407+
14021408
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Clause<'tcx> {
14031409
fn hash_stable<W: StableHasherResult>(&self,
14041410
hcx: &mut StableHashingContext<'a>,
@@ -1422,3 +1428,8 @@ impl_stable_hash_for!(struct ty::subst::UserSubsts<'tcx> { substs, user_self_ty
14221428

14231429
impl_stable_hash_for!(struct ty::subst::UserSelfTy<'tcx> { impl_def_id, self_ty });
14241430

1431+
impl_stable_hash_for!(
1432+
impl<'tcx> for struct traits::Environment<'tcx> {
1433+
clauses,
1434+
}
1435+
);

‎src/librustc/traits/mod.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
278278
/// * `DomainGoal`
279279
/// * `Goal`
280280
/// * `Clause`
281+
/// * `Environment`
282+
/// * `InEnvironment`
281283
/// are used for representing the trait system in the form of
282284
/// logic programming clauses. They are part of the interface
283285
/// for the chalk SLG solver.
@@ -335,6 +337,14 @@ impl<'tcx> DomainGoal<'tcx> {
335337
pub fn into_goal(self) -> GoalKind<'tcx> {
336338
GoalKind::DomainGoal(self)
337339
}
340+
341+
pub fn into_program_clause(self) -> ProgramClause<'tcx> {
342+
ProgramClause {
343+
goal: self,
344+
hypotheses: ty::List::empty(),
345+
category: ProgramClauseCategory::Other,
346+
}
347+
}
338348
}
339349

340350
impl<'tcx> GoalKind<'tcx> {
@@ -360,6 +370,15 @@ pub enum Clause<'tcx> {
360370
ForAll(ty::Binder<ProgramClause<'tcx>>),
361371
}
362372

373+
impl Clause<'tcx> {
374+
pub fn category(self) -> ProgramClauseCategory {
375+
match self {
376+
Clause::Implies(clause) => clause.category,
377+
Clause::ForAll(clause) => clause.skip_binder().category,
378+
}
379+
}
380+
}
381+
363382
/// Multiple clauses.
364383
pub type Clauses<'tcx> = &'tcx List<Clause<'tcx>>;
365384

@@ -376,6 +395,38 @@ pub struct ProgramClause<'tcx> {
376395

377396
/// ...if we can prove these hypotheses (there may be no hypotheses at all):
378397
pub hypotheses: Goals<'tcx>,
398+
399+
/// Useful for filtering clauses.
400+
pub category: ProgramClauseCategory,
401+
}
402+
403+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
404+
pub enum ProgramClauseCategory {
405+
ImpliedBound,
406+
WellFormed,
407+
Other,
408+
}
409+
410+
/// A set of clauses that we assume to be true.
411+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
412+
pub struct Environment<'tcx> {
413+
pub clauses: Clauses<'tcx>,
414+
}
415+
416+
impl Environment<'tcx> {
417+
pub fn with<G>(self, goal: G) -> InEnvironment<'tcx, G> {
418+
InEnvironment {
419+
environment: self,
420+
goal,
421+
}
422+
}
423+
}
424+
425+
/// Something (usually a goal), along with an environment.
426+
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
427+
pub struct InEnvironment<'tcx, G> {
428+
pub environment: Environment<'tcx>,
429+
pub goal: G,
379430
}
380431

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

‎src/librustc/traits/structural_impls.rs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ impl<'tcx> fmt::Display for traits::Goal<'tcx> {
496496

497497
impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
498498
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
499-
let traits::ProgramClause { goal, hypotheses } = self;
499+
let traits::ProgramClause { goal, hypotheses, .. } = self;
500500
write!(fmt, "{}", goal)?;
501501
if !hypotheses.is_empty() {
502502
write!(fmt, " :- ")?;
@@ -647,18 +647,59 @@ impl<'tcx> TypeFoldable<'tcx> for traits::Goal<'tcx> {
647647
BraceStructTypeFoldableImpl! {
648648
impl<'tcx> TypeFoldable<'tcx> for traits::ProgramClause<'tcx> {
649649
goal,
650-
hypotheses
650+
hypotheses,
651+
category,
651652
}
652653
}
653654

655+
CloneTypeFoldableAndLiftImpls! {
656+
traits::ProgramClauseCategory,
657+
}
658+
654659
EnumTypeFoldableImpl! {
655660
impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> {
656661
(traits::Clause::Implies)(clause),
657662
(traits::Clause::ForAll)(clause),
658663
}
659664
}
660665

661-
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<traits::Clause<'tcx>> {
666+
BraceStructTypeFoldableImpl! {
667+
impl<'tcx> TypeFoldable<'tcx> for traits::Environment<'tcx> { clauses }
668+
}
669+
670+
BraceStructTypeFoldableImpl! {
671+
impl<'tcx, G> TypeFoldable<'tcx> for traits::InEnvironment<'tcx, G> {
672+
environment,
673+
goal
674+
} where G: TypeFoldable<'tcx>
675+
}
676+
677+
impl<'a, 'tcx> Lift<'tcx> for traits::Environment<'a> {
678+
type Lifted = traits::Environment<'tcx>;
679+
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
680+
tcx.lift(&self.clauses).map(|clauses| {
681+
traits::Environment {
682+
clauses,
683+
}
684+
})
685+
}
686+
}
687+
688+
impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> {
689+
type Lifted = traits::InEnvironment<'tcx, G::Lifted>;
690+
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
691+
tcx.lift(&self.environment).and_then(|environment| {
692+
tcx.lift(&self.goal).map(|goal| {
693+
traits::InEnvironment {
694+
environment,
695+
goal,
696+
}
697+
})
698+
})
699+
}
700+
}
701+
702+
impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> {
662703
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
663704
let v = self.iter()
664705
.map(|t| t.fold_with(folder))

‎src/librustc/ty/query/config.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use dep_graph::SerializedDepNodeIndex;
1212
use dep_graph::DepNode;
1313
use hir::def_id::{CrateNum, DefId, DefIndex};
1414
use mir::interpret::GlobalId;
15+
use traits;
1516
use traits::query::{
1617
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal,
1718
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
@@ -826,8 +827,14 @@ impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
826827
}
827828

828829
impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> {
829-
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: ty::ParamEnv<'tcx>) -> Cow<'static, str> {
830-
"generating chalk-style clauses for param env".into()
830+
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: traits::Environment<'tcx>) -> Cow<'static, str> {
831+
"generating chalk-style clauses for environment".into()
832+
}
833+
}
834+
835+
impl<'tcx> QueryDescription<'tcx> for queries::environment<'tcx> {
836+
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
837+
"return a chalk-style environment".into()
831838
}
832839
}
833840

‎src/librustc/ty/query/keys.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use infer::canonical::Canonical;
1414
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex};
15+
use traits;
1516
use ty::{self, Ty, TyCtxt};
1617
use ty::subst::Substs;
1718
use ty::fast_reject::SimplifiedType;
@@ -181,6 +182,15 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> {
181182
}
182183
}
183184

185+
impl<'tcx> Key for traits::Environment<'tcx> {
186+
fn query_crate(&self) -> CrateNum {
187+
LOCAL_CRATE
188+
}
189+
fn default_span(&self, _: TyCtxt<'_, '_, '_>) -> Span {
190+
DUMMY_SP
191+
}
192+
}
193+
184194
impl Key for InternedString {
185195
fn query_crate(&self) -> CrateNum {
186196
LOCAL_CRATE

‎src/librustc/ty/query/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,8 +664,11 @@ define_queries! { <'tcx>
664664
[] fn program_clauses_for: ProgramClausesFor(DefId) -> Clauses<'tcx>,
665665

666666
[] fn program_clauses_for_env: ProgramClausesForEnv(
667-
ty::ParamEnv<'tcx>
667+
traits::Environment<'tcx>
668668
) -> Clauses<'tcx>,
669+
670+
// Get the chalk-style environment of the given item.
671+
[] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
669672
},
670673

671674
Linking {

‎src/librustc/ty/query/plumbing.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
11561156
DepKind::CheckMatch => { force!(check_match, def_id!()); }
11571157

11581158
DepKind::ParamEnv => { force!(param_env, def_id!()); }
1159+
DepKind::Environment => { force!(environment, def_id!()); }
11591160
DepKind::DescribeDef => { force!(describe_def, def_id!()); }
11601161
DepKind::DefSpan => { force!(def_span, def_id!()); }
11611162
DepKind::LookupStability => { force!(lookup_stability, def_id!()); }

‎src/librustc_traits/chalk_context.rs

Lines changed: 48 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ use rustc::traits::{
2222
ExClauseLift,
2323
Goal,
2424
GoalKind,
25-
ProgramClause,
26-
QuantifierKind
25+
Clause,
26+
QuantifierKind,
27+
Environment,
28+
InEnvironment,
2729
};
2830
use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
2931
use rustc::ty::subst::Kind;
@@ -68,10 +70,10 @@ BraceStructTypeFoldableImpl! {
6870
impl context::Context for ChalkArenas<'tcx> {
6971
type CanonicalExClause = Canonical<'tcx, ExClause<Self>>;
7072

71-
type CanonicalGoalInEnvironment = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Goal<'tcx>>>;
73+
type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
7274

7375
// u-canonicalization not yet implemented
74-
type UCanonicalGoalInEnvironment = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Goal<'tcx>>>;
76+
type UCanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>;
7577

7678
type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>;
7779

@@ -82,13 +84,13 @@ impl context::Context for ChalkArenas<'tcx> {
8284

8385
type InferenceNormalizedSubst = CanonicalVarValues<'tcx>;
8486

85-
type GoalInEnvironment = ty::ParamEnvAnd<'tcx, Goal<'tcx>>;
87+
type GoalInEnvironment = InEnvironment<'tcx, Goal<'tcx>>;
8688

8789
type RegionConstraint = QueryRegionConstraint<'tcx>;
8890

8991
type Substitution = CanonicalVarValues<'tcx>;
9092

91-
type Environment = ty::ParamEnv<'tcx>;
93+
type Environment = Environment<'tcx>;
9294

9395
type Goal = Goal<'tcx>;
9496

@@ -98,24 +100,24 @@ impl context::Context for ChalkArenas<'tcx> {
98100

99101
type Parameter = Kind<'tcx>;
100102

101-
type ProgramClause = ProgramClause<'tcx>;
103+
type ProgramClause = Clause<'tcx>;
102104

103-
type ProgramClauses = Vec<ProgramClause<'tcx>>;
105+
type ProgramClauses = Vec<Clause<'tcx>>;
104106

105107
type UnificationResult = InferOk<'tcx, ()>;
106108

107109
fn goal_in_environment(
108-
env: &ty::ParamEnv<'tcx>,
110+
env: &Environment<'tcx>,
109111
goal: Goal<'tcx>,
110-
) -> ty::ParamEnvAnd<'tcx, Goal<'tcx>> {
111-
env.and(goal)
112+
) -> InEnvironment<'tcx, Goal<'tcx>> {
113+
env.with(goal)
112114
}
113115
}
114116

115117
impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
116118
fn make_solution(
117119
&self,
118-
_root_goal: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
120+
_root_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
119121
_simplified_answers: impl context::AnswerStream<ChalkArenas<'gcx>>,
120122
) -> Option<Canonical<'gcx, QueryResponse<'gcx, ()>>> {
121123
unimplemented!()
@@ -124,7 +126,10 @@ impl context::AggregateOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
124126

125127
impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
126128
/// True if this is a coinductive goal -- e.g., proving an auto trait.
127-
fn is_coinductive(&self, _goal: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>) -> bool {
129+
fn is_coinductive(
130+
&self,
131+
_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>
132+
) -> bool {
128133
unimplemented!()
129134
}
130135

@@ -142,7 +147,7 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
142147
/// - the environment and goal found by substitution `S` into `arg`
143148
fn instantiate_ucanonical_goal<R>(
144149
&self,
145-
_arg: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
150+
_arg: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
146151
_op: impl context::WithInstantiatedUCanonicalGoal<ChalkArenas<'gcx>, Output = R>,
147152
) -> R {
148153
unimplemented!()
@@ -175,19 +180,19 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
175180
}
176181

177182
fn canonical(
178-
u_canon: &'a Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
179-
) -> &'a Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
183+
u_canon: &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
184+
) -> &'a Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
180185
u_canon
181186
}
182187

183188
fn is_trivial_substitution(
184-
_u_canon: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
189+
_u_canon: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
185190
_canonical_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
186191
) -> bool {
187192
unimplemented!()
188193
}
189194

190-
fn num_universes(_: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>) -> usize {
195+
fn num_universes(_: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>) -> usize {
191196
0 // FIXME
192197
}
193198

@@ -196,8 +201,8 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
196201
/// but for the universes of universally quantified names.
197202
fn map_goal_from_canonical(
198203
_map: &UniverseMap,
199-
value: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
200-
) -> Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
204+
value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
205+
) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
201206
*value // FIXME universe maps not implemented yet
202207
}
203208

@@ -267,10 +272,14 @@ impl context::InferenceTable<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
267272

268273
fn add_clauses(
269274
&mut self,
270-
_env: &ty::ParamEnv<'tcx>,
271-
_clauses: Vec<ProgramClause<'tcx>>,
272-
) -> ty::ParamEnv<'tcx> {
273-
panic!("FIXME no method to add clauses to ParamEnv yet")
275+
env: &Environment<'tcx>,
276+
clauses: Vec<Clause<'tcx>>,
277+
) -> Environment<'tcx> {
278+
Environment {
279+
clauses: self.infcx.tcx.mk_clauses(
280+
env.clauses.iter().cloned().chain(clauses.into_iter())
281+
)
282+
}
274283
}
275284
}
276285

@@ -279,19 +288,19 @@ impl context::ResolventOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
279288
{
280289
fn resolvent_clause(
281290
&mut self,
282-
_environment: &ty::ParamEnv<'tcx>,
291+
_environment: &Environment<'tcx>,
283292
_goal: &DomainGoal<'tcx>,
284293
_subst: &CanonicalVarValues<'tcx>,
285-
_clause: &ProgramClause<'tcx>,
294+
_clause: &Clause<'tcx>,
286295
) -> chalk_engine::fallible::Fallible<Canonical<'gcx, ChalkExClause<'gcx>>> {
287296
panic!()
288297
}
289298

290299
fn apply_answer_subst(
291300
&mut self,
292301
_ex_clause: ChalkExClause<'tcx>,
293-
_selected_goal: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
294-
_answer_table_goal: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
302+
_selected_goal: &InEnvironment<'tcx, Goal<'tcx>>,
303+
_answer_table_goal: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
295304
_canonical_answer_subst: &Canonical<'gcx, ConstrainedSubst<'gcx>>,
296305
) -> chalk_engine::fallible::Fallible<ChalkExClause<'tcx>> {
297306
panic!()
@@ -303,8 +312,8 @@ impl context::TruncateOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
303312
{
304313
fn truncate_goal(
305314
&mut self,
306-
subgoal: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
307-
) -> Option<ty::ParamEnvAnd<'tcx, Goal<'tcx>>> {
315+
subgoal: &InEnvironment<'tcx, Goal<'tcx>>,
316+
) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
308317
Some(*subgoal) // FIXME we should truncate at some point!
309318
}
310319

@@ -321,9 +330,9 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
321330
{
322331
fn program_clauses(
323332
&self,
324-
_environment: &ty::ParamEnv<'tcx>,
333+
_environment: &Environment<'tcx>,
325334
goal: &DomainGoal<'tcx>,
326-
) -> Vec<ProgramClause<'tcx>> {
335+
) -> Vec<Clause<'tcx>> {
327336
use rustc::traits::WhereClause::*;
328337

329338
match goal {
@@ -389,8 +398,8 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
389398

390399
fn canonicalize_goal(
391400
&mut self,
392-
value: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
393-
) -> Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>> {
401+
value: &InEnvironment<'tcx, Goal<'tcx>>,
402+
) -> Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>> {
394403
let mut _orig_values = OriginalQueryValues::default();
395404
self.infcx.canonicalize_query(value, &mut _orig_values)
396405
}
@@ -412,24 +421,24 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
412421

413422
fn u_canonicalize_goal(
414423
&mut self,
415-
value: &Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
424+
value: &Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
416425
) -> (
417-
Canonical<'gcx, ty::ParamEnvAnd<'gcx, Goal<'gcx>>>,
426+
Canonical<'gcx, InEnvironment<'gcx, Goal<'gcx>>>,
418427
UniverseMap,
419428
) {
420429
(value.clone(), UniverseMap)
421430
}
422431

423432
fn invert_goal(
424433
&mut self,
425-
_value: &ty::ParamEnvAnd<'tcx, Goal<'tcx>>,
426-
) -> Option<ty::ParamEnvAnd<'tcx, Goal<'tcx>>> {
434+
_value: &InEnvironment<'tcx, Goal<'tcx>>,
435+
) -> Option<InEnvironment<'tcx, Goal<'tcx>>> {
427436
panic!("goal inversion not yet implemented")
428437
}
429438

430439
fn unify_parameters(
431440
&mut self,
432-
_environment: &ty::ParamEnv<'tcx>,
441+
_environment: &Environment<'tcx>,
433442
_a: &Kind<'tcx>,
434443
_b: &Kind<'tcx>,
435444
) -> ChalkEngineFallible<InferOk<'tcx, ()>> {
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
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 rustc::traits::{
12+
Clause,
13+
Clauses,
14+
DomainGoal,
15+
FromEnv,
16+
ProgramClause,
17+
ProgramClauseCategory,
18+
Environment,
19+
};
20+
use rustc::ty::{self, TyCtxt, Ty};
21+
use rustc::hir::def_id::DefId;
22+
use rustc_data_structures::fx::FxHashSet;
23+
24+
struct ClauseVisitor<'set, 'a, 'tcx: 'a + 'set> {
25+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
26+
round: &'set mut FxHashSet<Clause<'tcx>>,
27+
}
28+
29+
impl ClauseVisitor<'set, 'a, 'tcx> {
30+
fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, round: &'set mut FxHashSet<Clause<'tcx>>) -> Self {
31+
ClauseVisitor {
32+
tcx,
33+
round,
34+
}
35+
}
36+
37+
fn visit_ty(&mut self, ty: Ty<'tcx>) {
38+
match ty.sty {
39+
ty::Projection(data) => {
40+
self.round.extend(
41+
self.tcx.program_clauses_for(data.item_def_id)
42+
.iter()
43+
.filter(|c| c.category() == ProgramClauseCategory::ImpliedBound)
44+
.cloned()
45+
);
46+
}
47+
48+
// forall<'a, T> { `Outlives(T, 'a) :- FromEnv(&'a T)` }
49+
ty::Ref(_region, _sub_ty, ..) => {
50+
// FIXME: we'd need bound tys in order to properly write the above rule
51+
}
52+
53+
ty::Dynamic(..) => {
54+
// FIXME: trait object rules are not yet implemented
55+
}
56+
57+
ty::Adt(def, ..) => {
58+
self.round.extend(
59+
self.tcx.program_clauses_for(def.did)
60+
.iter()
61+
.filter(|c| c.category() == ProgramClauseCategory::ImpliedBound)
62+
.cloned()
63+
);
64+
}
65+
66+
ty::Foreign(def_id) |
67+
ty::FnDef(def_id, ..) |
68+
ty::Closure(def_id, ..) |
69+
ty::Generator(def_id, ..) |
70+
ty::Opaque(def_id, ..) => {
71+
self.round.extend(
72+
self.tcx.program_clauses_for(def_id)
73+
.iter()
74+
.filter(|c| c.category() == ProgramClauseCategory::ImpliedBound)
75+
.cloned()
76+
);
77+
}
78+
79+
ty::Bool |
80+
ty::Char |
81+
ty::Int(..) |
82+
ty::Uint(..) |
83+
ty::Float(..) |
84+
ty::Str |
85+
ty::Array(..) |
86+
ty::Slice(..) |
87+
ty::RawPtr(..) |
88+
ty::FnPtr(..) |
89+
ty::Never |
90+
ty::Tuple(..) |
91+
ty::GeneratorWitness(..) |
92+
ty::UnnormalizedProjection(..) |
93+
ty::Param(..) |
94+
ty::Infer(..) |
95+
ty::Error => (),
96+
}
97+
}
98+
99+
fn visit_from_env(&mut self, from_env: FromEnv<'tcx>) {
100+
match from_env {
101+
FromEnv::Trait(predicate) => {
102+
self.round.extend(
103+
self.tcx.program_clauses_for(predicate.def_id())
104+
.iter()
105+
.filter(|c| c.category() == ProgramClauseCategory::ImpliedBound)
106+
.cloned()
107+
);
108+
}
109+
110+
FromEnv::Ty(ty) => self.visit_ty(ty),
111+
}
112+
}
113+
114+
fn visit_domain_goal(&mut self, domain_goal: DomainGoal<'tcx>) {
115+
// The only domain goals we can find in an environment are:
116+
// * `DomainGoal::Holds(..)`
117+
// * `DomainGoal::FromEnv(..)`
118+
// The former do not lead to any implied bounds. So we only need
119+
// to visit the latter.
120+
if let DomainGoal::FromEnv(from_env) = domain_goal {
121+
self.visit_from_env(from_env);
122+
}
123+
}
124+
125+
fn visit_program_clause(&mut self, clause: ProgramClause<'tcx>) {
126+
self.visit_domain_goal(clause.goal);
127+
// No need to visit `clause.hypotheses`: they are always of the form
128+
// `FromEnv(...)` and were visited at a previous round.
129+
}
130+
131+
fn visit_clause(&mut self, clause: Clause<'tcx>) {
132+
match clause {
133+
Clause::Implies(clause) => self.visit_program_clause(clause),
134+
Clause::ForAll(clause) => self.visit_program_clause(*clause.skip_binder()),
135+
}
136+
}
137+
}
138+
139+
crate fn program_clauses_for_env<'a, 'tcx>(
140+
tcx: TyCtxt<'a, 'tcx, 'tcx>,
141+
environment: Environment<'tcx>,
142+
) -> Clauses<'tcx> {
143+
debug!("program_clauses_for_env(environment={:?})", environment);
144+
145+
let mut last_round = FxHashSet();
146+
{
147+
let mut visitor = ClauseVisitor::new(tcx, &mut last_round);
148+
for &clause in environment.clauses {
149+
visitor.visit_clause(clause);
150+
}
151+
}
152+
153+
let mut closure = last_round.clone();
154+
let mut next_round = FxHashSet();
155+
while !last_round.is_empty() {
156+
let mut visitor = ClauseVisitor::new(tcx, &mut next_round);
157+
for clause in last_round.drain() {
158+
visitor.visit_clause(clause);
159+
}
160+
last_round.extend(
161+
next_round.drain().filter(|&clause| closure.insert(clause))
162+
);
163+
}
164+
165+
debug!("program_clauses_for_env: closure = {:#?}", closure);
166+
167+
return tcx.mk_clauses(
168+
closure.into_iter()
169+
);
170+
}
171+
172+
crate fn environment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Environment<'tcx> {
173+
use super::{Lower, IntoFromEnvGoal};
174+
use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
175+
176+
// The environment of an impl Trait type is its defining function's environment.
177+
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
178+
return environment(tcx, parent);
179+
}
180+
181+
// Compute the bounds on `Self` and the type parameters.
182+
let ty::InstantiatedPredicates { predicates } =
183+
tcx.predicates_of(def_id).instantiate_identity(tcx);
184+
185+
let clauses = predicates.into_iter()
186+
.map(|predicate| predicate.lower())
187+
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_from_env_goal()))
188+
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_program_clause()))
189+
190+
// `ForAll` because each `domain_goal` is a `PolyDomainGoal` and
191+
// could bound lifetimes.
192+
.map(Clause::ForAll);
193+
194+
let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
195+
let node = tcx.hir.get(node_id);
196+
197+
let mut is_fn = false;
198+
let mut is_impl = false;
199+
match node {
200+
Node::TraitItem(item) => match item.node {
201+
TraitItemKind::Method(..) => is_fn = true,
202+
_ => (),
203+
}
204+
205+
Node::ImplItem(item) => match item.node {
206+
ImplItemKind::Method(..) => is_fn = true,
207+
_ => (),
208+
}
209+
210+
Node::Item(item) => match item.node {
211+
ItemKind::Impl(..) => is_impl = true,
212+
ItemKind::Fn(..) => is_fn = true,
213+
_ => (),
214+
}
215+
216+
Node::ForeignItem(item) => match item.node {
217+
ForeignItemKind::Fn(..) => is_fn = true,
218+
_ => (),
219+
}
220+
221+
// FIXME: closures?
222+
_ => (),
223+
}
224+
225+
let mut input_tys = FxHashSet::default();
226+
227+
// In an impl, we assume that the receiver type and all its constituents
228+
// are well-formed.
229+
if is_impl {
230+
let trait_ref = tcx.impl_trait_ref(def_id).expect("not an impl");
231+
input_tys.extend(trait_ref.self_ty().walk());
232+
}
233+
234+
// In an fn, we assume that the arguments and all their constituents are
235+
// well-formed.
236+
if is_fn {
237+
let fn_sig = tcx.fn_sig(def_id);
238+
input_tys.extend(
239+
// FIXME: `skip_binder` seems ok for now? In a real setting,
240+
// the late bound regions would next be instantiated with things
241+
// in the inference table.
242+
fn_sig.skip_binder().inputs().iter().flat_map(|ty| ty.walk())
243+
);
244+
}
245+
246+
let clauses = clauses.chain(
247+
input_tys.into_iter()
248+
.map(|ty| DomainGoal::FromEnv(FromEnv::Ty(ty)))
249+
.map(|domain_goal| domain_goal.into_program_clause())
250+
.map(Clause::Implies)
251+
);
252+
253+
Environment {
254+
clauses: tcx.mk_clauses(clauses),
255+
}
256+
}

‎src/librustc_traits/lowering.rs renamed to ‎src/librustc_traits/lowering/mod.rs

Lines changed: 18 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
mod environment;
12+
1113
use rustc::hir::def_id::DefId;
1214
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
1315
use rustc::hir::map::definitions::DefPathData;
@@ -20,21 +22,21 @@ use rustc::traits::{
2022
GoalKind,
2123
PolyDomainGoal,
2224
ProgramClause,
25+
ProgramClauseCategory,
2326
WellFormed,
2427
WhereClause,
2528
};
2629
use rustc::ty::query::Providers;
2730
use rustc::ty::{self, List, TyCtxt};
28-
use rustc_data_structures::fx::FxHashSet;
29-
use std::mem;
3031
use syntax::ast;
3132

3233
use std::iter;
3334

3435
crate fn provide(p: &mut Providers) {
3536
*p = Providers {
3637
program_clauses_for,
37-
program_clauses_for_env,
38+
program_clauses_for_env: environment::program_clauses_for_env,
39+
environment: environment::environment,
3840
..*p
3941
};
4042
}
@@ -173,66 +175,6 @@ crate fn program_clauses_for<'a, 'tcx>(
173175
}
174176
}
175177

176-
crate fn program_clauses_for_env<'a, 'tcx>(
177-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
178-
param_env: ty::ParamEnv<'tcx>,
179-
) -> Clauses<'tcx> {
180-
debug!("program_clauses_for_env(param_env={:?})", param_env);
181-
182-
let mut last_round = FxHashSet();
183-
last_round.extend(
184-
param_env
185-
.caller_bounds
186-
.iter()
187-
.flat_map(|&p| predicate_def_id(p)),
188-
);
189-
190-
let mut closure = last_round.clone();
191-
let mut next_round = FxHashSet();
192-
while !last_round.is_empty() {
193-
next_round.extend(
194-
last_round
195-
.drain()
196-
.flat_map(|def_id| {
197-
tcx.predicates_of(def_id)
198-
.instantiate_identity(tcx)
199-
.predicates
200-
})
201-
.flat_map(|p| predicate_def_id(p))
202-
.filter(|&def_id| closure.insert(def_id)),
203-
);
204-
mem::swap(&mut next_round, &mut last_round);
205-
}
206-
207-
debug!("program_clauses_for_env: closure = {:#?}", closure);
208-
209-
return tcx.mk_clauses(
210-
closure
211-
.into_iter()
212-
.flat_map(|def_id| tcx.program_clauses_for(def_id).iter().cloned()),
213-
);
214-
215-
/// Given that `predicate` is in the environment, returns the
216-
/// def-id of something (e.g., a trait, associated item, etc)
217-
/// whose predicates can also be assumed to be true. We will
218-
/// compute the transitive closure of such things.
219-
fn predicate_def_id<'tcx>(predicate: ty::Predicate<'tcx>) -> Option<DefId> {
220-
match predicate {
221-
ty::Predicate::Trait(predicate) => Some(predicate.def_id()),
222-
223-
ty::Predicate::Projection(projection) => Some(projection.item_def_id()),
224-
225-
ty::Predicate::WellFormed(..)
226-
| ty::Predicate::RegionOutlives(..)
227-
| ty::Predicate::TypeOutlives(..)
228-
| ty::Predicate::ObjectSafe(..)
229-
| ty::Predicate::ClosureKind(..)
230-
| ty::Predicate::Subtype(..)
231-
| ty::Predicate::ConstEvaluatable(..) => None,
232-
}
233-
}
234-
}
235-
236178
fn program_clauses_for_trait<'a, 'tcx>(
237179
tcx: TyCtxt<'a, 'tcx, 'tcx>,
238180
def_id: DefId,
@@ -263,6 +205,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
263205
let implemented_from_env = ProgramClause {
264206
goal: impl_trait,
265207
hypotheses,
208+
category: ProgramClauseCategory::ImpliedBound,
266209
};
267210

268211
let clauses = iter::once(Clause::ForAll(ty::Binder::dummy(implemented_from_env)));
@@ -290,6 +233,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
290233
.map(|wc| wc.map_bound(|goal| ProgramClause {
291234
goal: goal.into_from_env_goal(),
292235
hypotheses,
236+
category: ProgramClauseCategory::ImpliedBound,
293237
}))
294238
.map(Clause::ForAll);
295239

@@ -316,6 +260,7 @@ fn program_clauses_for_trait<'a, 'tcx>(
316260
hypotheses: tcx.mk_goals(
317261
wf_conditions.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
318262
),
263+
category: ProgramClauseCategory::WellFormed,
319264
};
320265
let wf_clause = iter::once(Clause::ForAll(ty::Binder::dummy(wf_clause)));
321266

@@ -358,6 +303,7 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
358303
where_clauses
359304
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
360305
),
306+
category: ProgramClauseCategory::Other,
361307
};
362308
tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
363309
}
@@ -394,6 +340,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
394340
.cloned()
395341
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
396342
),
343+
category: ProgramClauseCategory::WellFormed,
397344
};
398345

399346
let well_formed_clause = iter::once(Clause::ForAll(ty::Binder::dummy(well_formed)));
@@ -419,6 +366,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>(
419366
.map(|wc| wc.map_bound(|goal| ProgramClause {
420367
goal: goal.into_from_env_goal(),
421368
hypotheses,
369+
category: ProgramClauseCategory::ImpliedBound,
422370
}))
423371

424372
.map(Clause::ForAll);
@@ -466,7 +414,8 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
466414

467415
let projection_eq_clause = ProgramClause {
468416
goal: DomainGoal::Holds(projection_eq),
469-
hypotheses: &ty::List::empty(),
417+
hypotheses: ty::List::empty(),
418+
category: ProgramClauseCategory::Other,
470419
};
471420

472421
// Rule WellFormed-AssocTy
@@ -484,6 +433,7 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
484433
let wf_clause = ProgramClause {
485434
goal: DomainGoal::WellFormed(WellFormed::Ty(placeholder_ty)),
486435
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
436+
category: ProgramClauseCategory::Other,
487437
};
488438

489439
// Rule Implied-Trait-From-AssocTy
@@ -500,6 +450,7 @@ pub fn program_clauses_for_associated_type_def<'a, 'tcx>(
500450
let from_env_clause = ProgramClause {
501451
goal: DomainGoal::FromEnv(FromEnv::Trait(trait_predicate)),
502452
hypotheses: tcx.mk_goals(iter::once(hypothesis)),
453+
category: ProgramClauseCategory::ImpliedBound,
503454
};
504455

505456
let clauses = iter::once(projection_eq_clause)
@@ -565,6 +516,7 @@ pub fn program_clauses_for_associated_type_value<'a, 'tcx>(
565516
.into_iter()
566517
.map(|wc| tcx.mk_goal(GoalKind::from_poly_domain_goal(wc, tcx))),
567518
),
519+
category: ProgramClauseCategory::Other,
568520
};
569521
tcx.mk_clauses(iter::once(Clause::ForAll(ty::Binder::dummy(clause))))
570522
}
@@ -595,8 +547,8 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx> {
595547
}
596548

597549
if attr.check_name("rustc_dump_env_program_clauses") {
598-
let param_env = self.tcx.param_env(def_id);
599-
clauses = Some(self.tcx.program_clauses_for_env(param_env));
550+
let environment = self.tcx.environment(def_id);
551+
clauses = Some(self.tcx.program_clauses_for_env(environment));
600552
}
601553

602554
if let Some(clauses) = clauses {

‎src/test/ui/chalkify/lower_env1.stderr

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
1818
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
1919
= note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
2020
= note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
21-
= note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
22-
= note: WellFormed(Self: Foo) :- Implemented(Self: Foo).
23-
= note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized).
2421

2522
error: aborting due to 2 previous errors
2623

‎src/test/ui/chalkify/lower_env2.rs

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

‎src/test/ui/chalkify/lower_env3.rs

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

0 commit comments

Comments
 (0)
Please sign in to comment.