Skip to content

Commit 72ac3eb

Browse files
committed
Rollup merge of #49497 - scalexm:hrtb, r=nikomatsakis
Chalkify - Tweak `Clause` definition and HRTBs r? @nikomatsakis
2 parents 46492ff + 1074a22 commit 72ac3eb

File tree

4 files changed

+88
-53
lines changed

4 files changed

+88
-53
lines changed

src/librustc/ich/impls_ty.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,12 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Goal<'tcx> {
13921392
}
13931393
}
13941394

1395+
impl_stable_hash_for!(
1396+
impl<'tcx> for struct traits::ProgramClause<'tcx> {
1397+
goal, hypotheses
1398+
}
1399+
);
1400+
13951401
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Clause<'tcx> {
13961402
fn hash_stable<W: StableHasherResult>(&self,
13971403
hcx: &mut StableHashingContext<'a>,
@@ -1400,11 +1406,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for traits::Clause<'tcx> {
14001406

14011407
mem::discriminant(self).hash_stable(hcx, hasher);
14021408
match self {
1403-
Implies(hypotheses, goal) => {
1404-
hypotheses.hash_stable(hcx, hasher);
1405-
goal.hash_stable(hcx, hasher);
1406-
}
1407-
DomainGoal(domain_goal) => domain_goal.hash_stable(hcx, hasher),
1409+
Implies(clause) => clause.hash_stable(hcx, hasher),
14081410
ForAll(clause) => clause.hash_stable(hcx, hasher),
14091411
}
14101412
}

src/librustc/traits/mod.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ pub enum DomainGoal<'tcx> {
272272
TypeOutlives(ty::TypeOutlivesPredicate<'tcx>),
273273
}
274274

275+
pub type PolyDomainGoal<'tcx> = ty::Binder<DomainGoal<'tcx>>;
276+
275277
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
276278
pub enum QuantifierKind {
277279
Universal,
@@ -294,20 +296,39 @@ impl<'tcx> From<DomainGoal<'tcx>> for Goal<'tcx> {
294296
}
295297
}
296298

297-
impl<'tcx> From<DomainGoal<'tcx>> for Clause<'tcx> {
298-
fn from(domain_goal: DomainGoal<'tcx>) -> Self {
299-
Clause::DomainGoal(domain_goal)
299+
impl<'tcx> From<PolyDomainGoal<'tcx>> for Goal<'tcx> {
300+
fn from(domain_goal: PolyDomainGoal<'tcx>) -> Self {
301+
match domain_goal.no_late_bound_regions() {
302+
Some(p) => p.into(),
303+
None => Goal::Quantified(
304+
QuantifierKind::Universal,
305+
Box::new(domain_goal.map_bound(|p| p.into()))
306+
),
307+
}
300308
}
301309
}
302310

303311
/// This matches the definition from Page 7 of "A Proof Procedure for the Logic of Hereditary
304312
/// Harrop Formulas".
305313
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
306314
pub enum Clause<'tcx> {
307-
// FIXME: again, use interned refs instead of `Box`
308-
Implies(Vec<Goal<'tcx>>, DomainGoal<'tcx>),
309-
DomainGoal(DomainGoal<'tcx>),
310-
ForAll(Box<ty::Binder<Clause<'tcx>>>),
315+
Implies(ProgramClause<'tcx>),
316+
ForAll(ty::Binder<ProgramClause<'tcx>>),
317+
}
318+
319+
/// A "program clause" has the form `D :- G1, ..., Gn`. It is saying
320+
/// that the domain goal `D` is true if `G1...Gn` are provable. This
321+
/// is equivalent to the implication `G1..Gn => D`; we usually write
322+
/// it with the reverse implication operator `:-` to emphasize the way
323+
/// that programs are actually solved (via backchaining, which starts
324+
/// with the goal to solve and proceeds from there).
325+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
326+
pub struct ProgramClause<'tcx> {
327+
/// This goal will be considered true...
328+
pub goal: DomainGoal<'tcx>,
329+
330+
/// ...if we can prove these hypotheses (there may be no hypotheses at all):
331+
pub hypotheses: Vec<Goal<'tcx>>,
311332
}
312333

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

src/librustc/traits/structural_impls.rs

+26-16
Original file line numberDiff line numberDiff line change
@@ -493,25 +493,29 @@ impl<'tcx> fmt::Display for traits::Goal<'tcx> {
493493
}
494494
}
495495

496+
impl<'tcx> fmt::Display for traits::ProgramClause<'tcx> {
497+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
498+
let traits::ProgramClause { goal, hypotheses } = self;
499+
write!(fmt, "{}", goal)?;
500+
if !hypotheses.is_empty() {
501+
write!(fmt, " :- ")?;
502+
for (index, condition) in hypotheses.iter().enumerate() {
503+
if index > 0 {
504+
write!(fmt, ", ")?;
505+
}
506+
write!(fmt, "{}", condition)?;
507+
}
508+
}
509+
write!(fmt, ".")
510+
}
511+
}
512+
496513
impl<'tcx> fmt::Display for traits::Clause<'tcx> {
497514
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
498515
use traits::Clause::*;
499516

500517
match self {
501-
Implies(hypotheses, goal) => {
502-
write!(fmt, "{}", goal)?;
503-
if !hypotheses.is_empty() {
504-
write!(fmt, " :- ")?;
505-
for (index, condition) in hypotheses.iter().enumerate() {
506-
if index > 0 {
507-
write!(fmt, ", ")?;
508-
}
509-
write!(fmt, "{}", condition)?;
510-
}
511-
}
512-
write!(fmt, ".")
513-
}
514-
DomainGoal(domain_goal) => write!(fmt, "{}.", domain_goal),
518+
Implies(clause) => write!(fmt, "{}", clause),
515519
ForAll(clause) => {
516520
// FIXME: appropriate binder names
517521
write!(fmt, "forall<> {{ {} }}", clause.skip_binder())
@@ -553,10 +557,16 @@ EnumTypeFoldableImpl! {
553557
}
554558
}
555559

560+
BraceStructTypeFoldableImpl! {
561+
impl<'tcx> TypeFoldable<'tcx> for traits::ProgramClause<'tcx> {
562+
goal,
563+
hypotheses
564+
}
565+
}
566+
556567
EnumTypeFoldableImpl! {
557568
impl<'tcx> TypeFoldable<'tcx> for traits::Clause<'tcx> {
558-
(traits::Clause::Implies)(hypotheses, goal),
559-
(traits::Clause::DomainGoal)(domain_goal),
569+
(traits::Clause::Implies)(clause),
560570
(traits::Clause::ForAll)(clause),
561571
}
562572
}

src/librustc_traits/lowering.rs

+27-25
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc::hir::def_id::DefId;
1313
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
1414
use rustc::ty::{self, TyCtxt};
1515
use rustc::ty::subst::Substs;
16-
use rustc::traits::{QuantifierKind, Goal, DomainGoal, Clause, WhereClauseAtom};
16+
use rustc::traits::{WhereClauseAtom, PolyDomainGoal, DomainGoal, ProgramClause, Clause};
1717
use syntax::ast;
1818
use rustc_data_structures::sync::Lrc;
1919

@@ -61,36 +61,27 @@ impl<'tcx> Lower<DomainGoal<'tcx>> for ty::TypeOutlivesPredicate<'tcx> {
6161
/// `ty::Binder` is used for wrapping a rustc construction possibly containing generic
6262
/// lifetimes, e.g. `for<'a> T: Fn(&'a i32)`. Instead of representing higher-ranked things
6363
/// in that leaf-form (i.e. `Holds(Implemented(Binder<TraitPredicate>))` in the previous
64-
/// example), we model them with quantified goals, e.g. as for the previous example:
64+
/// example), we model them with quantified domain goals, e.g. as for the previous example:
6565
/// `forall<'a> { T: Fn(&'a i32) }` which corresponds to something like
6666
/// `Binder<Holds(Implemented(TraitPredicate))>`.
67-
///
68-
/// Also, if `self` does not contain generic lifetimes, we can safely drop the binder and we
69-
/// can directly lower to a leaf goal instead of a quantified goal.
70-
impl<'tcx, T> Lower<Goal<'tcx>> for ty::Binder<T>
71-
where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx> + Copy
67+
impl<'tcx, T> Lower<PolyDomainGoal<'tcx>> for ty::Binder<T>
68+
where T: Lower<DomainGoal<'tcx>> + ty::fold::TypeFoldable<'tcx>
7269
{
73-
fn lower(&self) -> Goal<'tcx> {
74-
match self.no_late_bound_regions() {
75-
Some(p) => p.lower().into(),
76-
None => Goal::Quantified(
77-
QuantifierKind::Universal,
78-
Box::new(self.map_bound(|p| p.lower().into()))
79-
),
80-
}
70+
fn lower(&self) -> PolyDomainGoal<'tcx> {
71+
self.map_bound_ref(|p| p.lower())
8172
}
8273
}
8374

84-
impl<'tcx> Lower<Goal<'tcx>> for ty::Predicate<'tcx> {
85-
fn lower(&self) -> Goal<'tcx> {
75+
impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
76+
fn lower(&self) -> PolyDomainGoal<'tcx> {
8677
use rustc::ty::Predicate::*;
8778

8879
match self {
8980
Trait(predicate) => predicate.lower(),
9081
RegionOutlives(predicate) => predicate.lower(),
9182
TypeOutlives(predicate) => predicate.lower(),
9283
Projection(predicate) => predicate.lower(),
93-
WellFormed(ty) => DomainGoal::WellFormedTy(*ty).into(),
84+
WellFormed(ty) => ty::Binder::dummy(DomainGoal::WellFormedTy(*ty)),
9485
ObjectSafe(..) |
9586
ClosureKind(..) |
9687
Subtype(..) |
@@ -134,13 +125,16 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
134125
}
135126
};
136127
// `FromEnv(Self: Trait<P1..Pn>)`
137-
let from_env = Goal::DomainGoal(DomainGoal::FromEnv(trait_pred.lower()));
128+
let from_env = DomainGoal::FromEnv(trait_pred.lower()).into();
138129
// `Implemented(Self: Trait<P1..Pn>)`
139130
let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));
140131

141132
// `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
142-
let clause = Clause::Implies(vec![from_env], impl_trait);
143-
Lrc::new(vec![clause])
133+
let clause = ProgramClause {
134+
goal: impl_trait,
135+
hypotheses: vec![from_env],
136+
};
137+
Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))])
144138
}
145139

146140
fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
@@ -167,8 +161,11 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId
167161
let where_clauses = tcx.predicates_of(def_id).predicates.lower();
168162

169163
// `Implemented(A0: Trait<A1..An>) :- WC`
170-
let clause = Clause::Implies(where_clauses, trait_pred);
171-
Lrc::new(vec![clause])
164+
let clause = ProgramClause {
165+
goal: trait_pred,
166+
hypotheses: where_clauses.into_iter().map(|wc| wc.into()).collect()
167+
};
168+
Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))])
172169
}
173170

174171
pub fn dump_program_clauses<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
@@ -184,14 +181,19 @@ struct ClauseDumper<'a, 'tcx: 'a> {
184181
tcx: TyCtxt<'a, 'tcx, 'tcx>,
185182
}
186183

187-
impl <'a, 'tcx> ClauseDumper<'a, 'tcx > {
184+
impl<'a, 'tcx> ClauseDumper<'a, 'tcx > {
188185
fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
189186
let def_id = self.tcx.hir.local_def_id(node_id);
190187
for attr in attrs {
191188
if attr.check_name("rustc_dump_program_clauses") {
192189
let clauses = self.tcx.program_clauses_for(def_id);
193190
for clause in &*clauses {
194-
self.tcx.sess.struct_span_err(attr.span, &format!("{}", clause)).emit();
191+
// Skip the top-level binder for a less verbose output
192+
let program_clause = match clause {
193+
Clause::Implies(program_clause) => program_clause,
194+
Clause::ForAll(program_clause) => program_clause.skip_binder(),
195+
};
196+
self.tcx.sess.struct_span_err(attr.span, &format!("{}", program_clause)).emit();
195197
}
196198
}
197199
}

0 commit comments

Comments
 (0)