Skip to content

Commit 5607fc9

Browse files
committed
Update doc and refactor some parts of the lowering process
1 parent f7c4c26 commit 5607fc9

File tree

5 files changed

+83
-72
lines changed

5 files changed

+83
-72
lines changed

chalk-parse/src/ast.rs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use lalrpop_intern::InternedString;
22
use std::fmt;
33

4-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
55
pub struct Span {
66
pub lo: usize,
77
pub hi: usize,
@@ -13,17 +13,20 @@ impl Span {
1313
}
1414
}
1515

16+
#[derive(Clone, PartialEq, Eq, Debug)]
1617
pub struct Program {
1718
pub items: Vec<Item>
1819
}
1920

21+
#[derive(Clone, PartialEq, Eq, Debug)]
2022
pub enum Item {
2123
StructDefn(StructDefn),
2224
TraitDefn(TraitDefn),
2325
Impl(Impl),
2426
Clause(Clause),
2527
}
2628

29+
#[derive(Clone, PartialEq, Eq, Debug)]
2730
pub struct StructDefn {
2831
pub name: Identifier,
2932
pub parameter_kinds: Vec<ParameterKind>,
@@ -32,11 +35,13 @@ pub struct StructDefn {
3235
pub flags: StructFlags,
3336
}
3437

38+
#[derive(Clone, PartialEq, Eq, Debug)]
3539
pub struct StructFlags {
3640
pub external: bool,
3741
pub fundamental: bool,
3842
}
3943

44+
#[derive(Clone, PartialEq, Eq, Debug)]
4045
pub struct TraitDefn {
4146
pub name: Identifier,
4247
pub parameter_kinds: Vec<ParameterKind>,
@@ -45,43 +50,50 @@ pub struct TraitDefn {
4550
pub flags: TraitFlags,
4651
}
4752

53+
#[derive(Clone, PartialEq, Eq, Debug)]
4854
pub struct TraitFlags {
4955
pub auto: bool,
5056
pub marker: bool,
5157
pub external: bool,
5258
pub deref: bool,
5359
}
5460

61+
#[derive(Clone, PartialEq, Eq, Debug)]
5562
pub struct AssocTyDefn {
5663
pub name: Identifier,
5764
pub parameter_kinds: Vec<ParameterKind>,
5865
pub bounds: Vec<InlineBound>,
5966
pub where_clauses: Vec<QuantifiedWhereClause>,
6067
}
6168

69+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
6270
pub enum ParameterKind {
6371
Ty(Identifier),
6472
Lifetime(Identifier),
6573
}
6674

75+
#[derive(Clone, PartialEq, Eq, Debug)]
6776
pub enum Parameter {
6877
Ty(Ty),
6978
Lifetime(Lifetime),
7079
}
7180

81+
#[derive(Clone, PartialEq, Eq, Debug)]
7282
/// An inline bound, e.g. `: Foo<K>` in `impl<K, T: Foo<K>> SomeType<T>`.
7383
pub enum InlineBound {
7484
TraitBound(TraitBound),
7585
ProjectionEqBound(ProjectionEqBound),
7686
}
7787

88+
#[derive(Clone, PartialEq, Eq, Debug)]
7889
/// Represents a trait bound on e.g. a type or type parameter.
7990
/// Does not know anything about what it's binding.
8091
pub struct TraitBound {
8192
pub trait_name: Identifier,
8293
pub args_no_self: Vec<Parameter>,
8394
}
8495

96+
#[derive(Clone, PartialEq, Eq, Debug)]
8597
/// Represents a projection equality bound on e.g. a type or type parameter.
8698
/// Does not know anything about what it's binding.
8799
pub struct ProjectionEqBound {
@@ -91,7 +103,7 @@ pub struct ProjectionEqBound {
91103
pub value: Ty,
92104
}
93105

94-
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
106+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
95107
pub enum Kind {
96108
Ty,
97109
Lifetime,
@@ -130,19 +142,22 @@ impl Kinded for Parameter {
130142
}
131143
}
132144

145+
#[derive(Clone, PartialEq, Eq, Debug)]
133146
pub struct Impl {
134147
pub parameter_kinds: Vec<ParameterKind>,
135148
pub trait_ref: PolarizedTraitRef,
136149
pub where_clauses: Vec<QuantifiedWhereClause>,
137150
pub assoc_ty_values: Vec<AssocTyValue>,
138151
}
139152

153+
#[derive(Clone, PartialEq, Eq, Debug)]
140154
pub struct AssocTyValue {
141155
pub name: Identifier,
142156
pub parameter_kinds: Vec<ParameterKind>,
143157
pub value: Ty,
144158
}
145159

160+
#[derive(Clone, PartialEq, Eq, Debug)]
146161
pub enum Ty {
147162
Id {
148163
name: Identifier,
@@ -163,28 +178,33 @@ pub enum Ty {
163178
}
164179
}
165180

181+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
166182
pub enum Lifetime {
167183
Id {
168184
name: Identifier,
169185
}
170186
}
171187

188+
#[derive(Clone, PartialEq, Eq, Debug)]
172189
pub struct ProjectionTy {
173190
pub trait_ref: TraitRef,
174191
pub name: Identifier,
175192
pub args: Vec<Parameter>,
176193
}
177194

195+
#[derive(Clone, PartialEq, Eq, Debug)]
178196
pub struct UnselectedProjectionTy {
179197
pub name: Identifier,
180198
pub args: Vec<Parameter>,
181199
}
182200

201+
#[derive(Clone, PartialEq, Eq, Debug)]
183202
pub struct TraitRef {
184203
pub trait_name: Identifier,
185204
pub args: Vec<Parameter>,
186205
}
187206

207+
#[derive(Clone, PartialEq, Eq, Debug)]
188208
pub enum PolarizedTraitRef {
189209
Positive(TraitRef),
190210
Negative(TraitRef),
@@ -200,17 +220,19 @@ impl PolarizedTraitRef {
200220
}
201221
}
202222

203-
#[derive(Copy, Clone, Debug)]
223+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
204224
pub struct Identifier {
205225
pub str: InternedString,
206226
pub span: Span,
207227
}
208228

229+
#[derive(Clone, PartialEq, Eq, Debug)]
209230
pub enum WhereClause {
210231
Implemented { trait_ref: TraitRef },
211232
ProjectionEq { projection: ProjectionTy, ty: Ty },
212233
}
213234

235+
#[derive(Clone, PartialEq, Eq, Debug)]
214236
pub enum DomainGoal {
215237
Holds { where_clause: WhereClause },
216238
Normalize { projection: ProjectionTy, ty: Ty },
@@ -223,22 +245,26 @@ pub enum DomainGoal {
223245
IsLocal { ty: Ty },
224246
}
225247

248+
#[derive(Clone, PartialEq, Eq, Debug)]
226249
pub enum LeafGoal {
227250
DomainGoal { goal: DomainGoal },
228251
UnifyTys { a: Ty, b: Ty },
229252
UnifyLifetimes { a: Lifetime, b: Lifetime },
230253
}
231254

255+
#[derive(Clone, PartialEq, Eq, Debug)]
232256
pub struct QuantifiedWhereClause {
233257
pub parameter_kinds: Vec<ParameterKind>,
234258
pub where_clause: WhereClause,
235259
}
236260

261+
#[derive(Clone, PartialEq, Eq, Debug)]
237262
pub struct Field {
238263
pub name: Identifier,
239264
pub ty: Ty,
240265
}
241266

267+
#[derive(Clone, PartialEq, Eq, Debug)]
242268
/// This allows users to add arbitrary `A :- B` clauses into the
243269
/// logic; it has no equivalent in Rust, but it's useful for testing.
244270
pub struct Clause {
@@ -247,6 +273,7 @@ pub struct Clause {
247273
pub conditions: Vec<Box<Goal>>,
248274
}
249275

276+
#[derive(Clone, PartialEq, Eq, Debug)]
250277
pub enum Goal {
251278
ForAll(Vec<ParameterKind>, Box<Goal>),
252279
Exists(Vec<ParameterKind>, Box<Goal>),

src/ir.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ impl TraitBound {
295295
vec![WhereClause::Implemented(trait_ref)]
296296
}
297297

298-
fn as_trait_ref(&self, self_ty: Ty) -> TraitRef {
298+
crate fn as_trait_ref(&self, self_ty: Ty) -> TraitRef {
299299
let self_ty = ParameterKind::Ty(self_ty);
300300
TraitRef {
301301
trait_id: self.trait_id,

src/ir/lowering.rs

Lines changed: 35 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -418,14 +418,14 @@ trait LowerWhereClauseVec<T> {
418418

419419
impl LowerWhereClauseVec<ir::WhereClause> for [WhereClause] {
420420
fn lower(&self, env: &Env) -> Result<Vec<ir::WhereClause>> {
421-
self.iter().flat_map(|wc| LowerWhereClause::lower(wc, env).apply_result()).collect()
421+
self.iter().flat_map(|wc| wc.lower(env).apply_result()).collect()
422422
}
423423
}
424424

425425
impl LowerWhereClauseVec<ir::QuantifiedWhereClause> for [QuantifiedWhereClause] {
426426
fn lower(&self, env: &Env) -> Result<Vec<ir::QuantifiedWhereClause>> {
427427
self.iter()
428-
.flat_map(|wc| match LowerWhereClause::lower(wc, env) {
428+
.flat_map(|wc| match wc.lower(env) {
429429
Ok(v) => v.into_iter().map(Ok).collect(),
430430
Err(e) => vec![Err(e)],
431431
})
@@ -434,6 +434,10 @@ impl LowerWhereClauseVec<ir::QuantifiedWhereClause> for [QuantifiedWhereClause]
434434
}
435435

436436
trait LowerWhereClause<T> {
437+
/// Lower from an AST `where` clause to an internal IR.
438+
/// Some AST `where` clauses can lower to multiple ones, this is why we return a `Vec`.
439+
/// As for now, this is the only the case for `where T: Foo<Item = U>` which lowers to
440+
/// `Implemented(T: Foo)` and `ProjectionEq(<T as Foo>::Item = U)`.
437441
fn lower(&self, env: &Env) -> Result<Vec<T>>;
438442
}
439443

@@ -464,7 +468,7 @@ impl LowerWhereClause<ir::QuantifiedWhereClause> for QuantifiedWhereClause {
464468
fn lower(&self, env: &Env) -> Result<Vec<ir::QuantifiedWhereClause>> {
465469
let parameter_kinds = self.parameter_kinds.iter().map(|pk| pk.lower());
466470
let binders = env.in_binders(parameter_kinds, |env| {
467-
Ok(LowerWhereClause::lower(&self.where_clause, env)?)
471+
Ok(self.where_clause.lower(env)?)
468472
})?;
469473
Ok(binders.into_iter().collect())
470474
}
@@ -474,14 +478,6 @@ trait LowerDomainGoal {
474478
fn lower(&self, env: &Env) -> Result<Vec<ir::DomainGoal>>;
475479
}
476480

477-
/// Lowers a where-clause in the context of a clause (i.e. in "negative"
478-
/// position); this is limited to the kinds of where-clauses users can actually
479-
/// type in Rust and well-formedness checks.
480-
///
481-
/// Lowers a where-clause in the context of a goal (i.e. in "positive"
482-
/// position); this is richer in terms of the legal sorts of where-clauses that
483-
/// can appear, because it includes all the sorts of things that the compiler
484-
/// must verify.
485481
impl LowerDomainGoal for DomainGoal {
486482
fn lower(&self, env: &Env) -> Result<Vec<ir::DomainGoal>> {
487483
let goals = match self {
@@ -614,46 +610,22 @@ trait LowerTraitRef {
614610

615611
impl LowerTraitRef for TraitRef {
616612
fn lower(&self, env: &Env) -> Result<ir::TraitRef> {
617-
let id = match env.lookup(self.trait_name)? {
618-
NameLookup::Type(id) => id,
619-
NameLookup::Parameter(_) => bail!(ErrorKind::NotTrait(self.trait_name)),
620-
};
621-
622-
let k = env.type_kind(id);
623-
if k.sort != ir::TypeSort::Trait {
624-
bail!(ErrorKind::NotTrait(self.trait_name));
625-
}
626-
627-
let parameters = self.args
628-
.iter()
629-
.map(|a| Ok(a.lower(env)?))
630-
.collect::<Result<Vec<_>>>()?;
631-
632-
if parameters.len() != k.binders.len() + 1 {
633-
bail!(
634-
"wrong number of parameters, expected `{:?}`, got `{:?}`",
635-
k.binders.len() + 1,
636-
parameters.len()
637-
)
638-
}
639-
640-
for (binder, param) in k.binders.binders.iter().zip(parameters.iter().skip(1)) {
641-
check_type_kinds("incorrect kind for trait parameter", binder, param)?;
642-
}
613+
let without_self = TraitBound {
614+
trait_name: self.trait_name,
615+
args_no_self: self.args.iter().cloned().skip(1).collect(),
616+
}.lower(env)?;
643617

644-
Ok(ir::TraitRef {
645-
trait_id: id,
646-
parameters: parameters,
647-
})
618+
let self_parameter = self.args[0].lower(env)?;
619+
Ok(without_self.as_trait_ref(self_parameter.ty().unwrap()))
648620
}
649621
}
650622

651623
trait LowerTraitBound {
652-
fn lower_trait_bound(&self, env: &Env) -> Result<ir::TraitBound>;
624+
fn lower(&self, env: &Env) -> Result<ir::TraitBound>;
653625
}
654626

655627
impl LowerTraitBound for TraitBound {
656-
fn lower_trait_bound(&self, env: &Env) -> Result<ir::TraitBound> {
628+
fn lower(&self, env: &Env) -> Result<ir::TraitBound> {
657629
let id = match env.lookup(self.trait_name)? {
658630
NameLookup::Type(id) => id,
659631
NameLookup::Parameter(_) => bail!(ErrorKind::NotTrait(self.trait_name)),
@@ -688,19 +660,13 @@ impl LowerTraitBound for TraitBound {
688660
}
689661
}
690662

691-
trait LowerInlineBound {
692-
fn lower(&self, env: &Env) -> Result<ir::InlineBound>;
693-
}
694-
695-
impl LowerInlineBound for TraitBound {
696-
fn lower(&self, env: &Env) -> Result<ir::InlineBound> {
697-
Ok(ir::InlineBound::TraitBound(self.lower_trait_bound(&env)?))
698-
}
663+
trait LowerProjectionEqBound {
664+
fn lower(&self, env: &Env) -> Result<ir::ProjectionEqBound>;
699665
}
700666

701-
impl LowerInlineBound for ProjectionEqBound {
702-
fn lower(&self, env: &Env) -> Result<ir::InlineBound> {
703-
let trait_bound = self.trait_bound.lower_trait_bound(env)?;
667+
impl LowerProjectionEqBound for ProjectionEqBound {
668+
fn lower(&self, env: &Env) -> Result<ir::ProjectionEqBound> {
669+
let trait_bound = self.trait_bound.lower(env)?;
704670
let info = match env.associated_ty_infos.get(&(trait_bound.trait_id, self.name.str)) {
705671
Some(info) => info,
706672
None => bail!("no associated type `{}` defined in trait", self.name.str),
@@ -719,21 +685,30 @@ impl LowerInlineBound for ProjectionEqBound {
719685
check_type_kinds("incorrect kind for associated type parameter", param, arg)?;
720686
}
721687

722-
Ok(ir::InlineBound::ProjectionEqBound(ir::ProjectionEqBound {
688+
Ok(ir::ProjectionEqBound {
723689
trait_bound,
724690
associated_ty_id: info.id,
725691
parameters: args,
726692
value: self.value.lower(env)?,
727-
}))
693+
})
728694
}
729695
}
730696

697+
trait LowerInlineBound {
698+
fn lower(&self, env: &Env) -> Result<ir::InlineBound>;
699+
}
700+
731701
impl LowerInlineBound for InlineBound {
732702
fn lower(&self, env: &Env) -> Result<ir::InlineBound> {
733-
match self {
734-
InlineBound::TraitBound(b) => b.lower(&env),
735-
InlineBound::ProjectionEqBound(b) => b.lower(&env),
736-
}
703+
let bound = match self {
704+
InlineBound::TraitBound(b) => ir::InlineBound::TraitBound(
705+
b.lower(&env)?
706+
),
707+
InlineBound::ProjectionEqBound(b) => ir::InlineBound::ProjectionEqBound(
708+
b.lower(&env)?
709+
),
710+
};
711+
Ok(bound)
737712
}
738713
}
739714

0 commit comments

Comments
 (0)