Skip to content

Commit a8bf437

Browse files
authored
Merge pull request #359 from yaahc/builtin
extend `TraitDefn` with concept of "well-known trait" identifier
2 parents 61e5a0b + 36fe821 commit a8bf437

File tree

9 files changed

+112
-4
lines changed

9 files changed

+112
-4
lines changed

chalk-integration/src/lowering.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,7 @@ impl LowerTrait for TraitDefn {
12481248
binders: binders,
12491249
flags: self.flags.lower(),
12501250
associated_ty_ids,
1251+
well_known: self.well_known.map(|t| t.lower()),
12511252
};
12521253

12531254
debug!("trait_datum={:?}", trait_datum);
@@ -1353,6 +1354,18 @@ impl LowerQuantifiedGoal for Goal {
13531354
}
13541355
}
13551356

1357+
trait LowerWellKnownTrait {
1358+
fn lower(&self) -> rust_ir::WellKnownTrait;
1359+
}
1360+
1361+
impl LowerWellKnownTrait for WellKnownTrait {
1362+
fn lower(&self) -> rust_ir::WellKnownTrait {
1363+
match self {
1364+
Self::SizedTrait => rust_ir::WellKnownTrait::SizedTrait,
1365+
}
1366+
}
1367+
}
1368+
13561369
/// Lowers LowerResult<Vec<T>> -> Vec<LowerResult<T>>.
13571370
trait ApplyResult {
13581371
type Output;

chalk-ir/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,10 @@ impl UniverseIndex {
144144
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
145145
pub struct StructId<I: Interner>(pub I::DefId);
146146

147+
/// The id of a trait definition; could be used to load the trait datum by
148+
/// invoking the [`trait_datum`] method.
149+
///
150+
/// [`trait_datum`]: ../chalk_solve/trait.RustIrDatabase.html#tymethod.trait_datum
147151
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
148152
pub struct TraitId<I: Interner>(pub I::DefId);
149153

@@ -153,6 +157,10 @@ pub struct ImplId<I: Interner>(pub I::DefId);
153157
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
154158
pub struct ClauseId<I: Interner>(pub I::DefId);
155159

160+
/// The id for the associated type member of a trait. The details of the type
161+
/// can be found by invoking the [`associated_ty_data`] method.
162+
///
163+
/// [`associated_ty_data`]: ../chalk_solve/trait.RustIrDatabase.html#tymethod.associated_ty_data
156164
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
157165
pub struct AssocTypeId<I: Interner>(pub I::DefId);
158166

chalk-parse/src/ast.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ pub struct TraitDefn {
4848
pub where_clauses: Vec<QuantifiedWhereClause>,
4949
pub assoc_ty_defns: Vec<AssocTyDefn>,
5050
pub flags: TraitFlags,
51+
pub well_known: Option<WellKnownTrait>,
52+
}
53+
54+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
55+
pub enum WellKnownTrait {
56+
SizedTrait,
5157
}
5258

5359
#[derive(Clone, PartialEq, Eq, Debug)]

chalk-parse/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![recursion_limit = "1024"]
2+
#![allow(unused_parens)]
23

34
#[macro_use]
45
extern crate lalrpop_util;

chalk-parse/src/parser.lalrpop

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ FundamentalKeyword: () = "#" "[" "fundamental" "]";
4343
NonEnumerableKeyword: () = "#" "[" "non_enumerable" "]";
4444
CoinductiveKeyword: () = "#" "[" "coinductive" "]";
4545

46+
WellKnownTrait: WellKnownTrait = {
47+
"#" "[" "lang" "(" "sized" ")" "]" => WellKnownTrait::SizedTrait,
48+
};
49+
4650
StructDefn: StructDefn = {
4751
<upstream:UpstreamKeyword?> <fundamental:FundamentalKeyword?> "struct" <n:Id><p:Angle<ParameterKind>>
4852
<w:QuantifiedWhereClauses> "{" <f:Fields> "}" => StructDefn
@@ -59,13 +63,14 @@ StructDefn: StructDefn = {
5963
};
6064

6165
TraitDefn: TraitDefn = {
62-
<auto:AutoKeyword?> <marker:MarkerKeyword?> <upstream:UpstreamKeyword?> <fundamental:FundamentalKeyword?> <non_enumerable:NonEnumerableKeyword?> <coinductive:CoinductiveKeyword?> "trait" <n:Id><p:Angle<ParameterKind>>
66+
<auto:AutoKeyword?> <marker:MarkerKeyword?> <upstream:UpstreamKeyword?> <fundamental:FundamentalKeyword?> <non_enumerable:NonEnumerableKeyword?> <coinductive:CoinductiveKeyword?> <well_known:WellKnownTrait?> "trait" <n:Id><p:Angle<ParameterKind>>
6367
<w:QuantifiedWhereClauses> "{" <a:AssocTyDefn*> "}" => TraitDefn
6468
{
6569
name: n,
6670
parameter_kinds: p,
6771
where_clauses: w,
6872
assoc_ty_defns: a,
73+
well_known,
6974
flags: TraitFlags {
7075
auto: auto.is_some(),
7176
marker: marker.is_some(),

chalk-rust-ir/src/lib.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,30 @@ pub struct StructFlags {
8787
}
8888

8989
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
90+
/// A rust intermediate representation (rust_ir) of a Trait Definition. For
91+
/// example, given the following rust code:
92+
///
93+
/// ```compile_fail
94+
/// use std::fmt::Debug;
95+
///
96+
/// trait Foo<T>
97+
/// where
98+
/// T: Debug,
99+
/// {
100+
/// type Bar<U>;
101+
/// }
102+
/// ```
103+
///
104+
/// This would represent the `trait Foo` declaration. Note that the details of
105+
/// the trait members (e.g., the associated type declaration (`type Bar<U>`) are
106+
/// not contained in this type, and are represented separately (e.g., in
107+
/// [`AssociatedTyDatum`]).
108+
///
109+
/// Not to be confused with the rust_ir for a Trait Implementation, which is
110+
/// represented by [`ImplDatum`]
111+
///
112+
/// [`ImplDatum`]: struct.ImplDatum.html
113+
/// [`AssociatedTyDatum`]: struct.AssociatedTyDatum.html
90114
pub struct TraitDatum<I: Interner> {
91115
pub id: TraitId<I>,
92116

@@ -97,8 +121,18 @@ pub struct TraitDatum<I: Interner> {
97121
/// chalk we add annotations like `#[auto]`.
98122
pub flags: TraitFlags,
99123

100-
/// The id of each associated type defined in the trait.
101124
pub associated_ty_ids: Vec<AssocTypeId<I>>,
125+
126+
/// If this is a well-known trait, which one? If `None`, this is a regular,
127+
/// user-defined trait.
128+
pub well_known: Option<WellKnownTrait>,
129+
}
130+
131+
/// A list of the traits that are "well known" to chalk, which means that
132+
/// the chalk-solve crate has special, hard-coded impls for them.
133+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
134+
pub enum WellKnownTrait {
135+
SizedTrait,
102136
}
103137

104138
impl<I: Interner> TraitDatum<I> {
@@ -128,11 +162,34 @@ pub struct TraitDatumBound<I: Interner> {
128162

129163
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
130164
pub struct TraitFlags {
165+
/// An "auto trait" is one that is "automatically implemented" for every
166+
/// struct, so long as no explicit impl is given.
167+
///
168+
/// Examples are `Send` and `Sync`.
131169
pub auto: bool,
170+
132171
pub marker: bool,
172+
173+
/// Indicate that a trait is defined upstream (in a dependency), used during
174+
/// coherence checking.
133175
pub upstream: bool,
176+
177+
/// A fundamental trait is a trait where adding an impl for an existing type
178+
/// is considered a breaking change. Examples of fundamental traits are the
179+
/// closure traits like `Fn` and `FnMut`.
180+
///
181+
/// As of this writing (2020-03-27), fundamental traits are declared by the
182+
/// unstable `#[fundamental]` attribute in rustc, and hence cannot appear
183+
/// outside of the standard library.
134184
pub fundamental: bool,
185+
186+
/// Indicates that chalk cannot list all of the implementations of the given
187+
/// trait, likely because it is a publicly exported trait in a library.
188+
///
189+
/// Currently (2020-03-27) rustc and rust-analyzer mark all traits as
190+
/// non_enumerable, and in the future it may become the only option.
135191
pub non_enumerable: bool,
192+
136193
pub coinductive: bool,
137194
}
138195

chalk-solve/src/clauses.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use chalk_ir::*;
1010
use rustc_hash::FxHashSet;
1111

1212
pub mod builder;
13+
mod builtin_traits;
1314
mod env_elaborator;
1415
pub mod program_clauses;
1516

@@ -236,7 +237,9 @@ fn program_clauses_that_could_match<I: Interner>(
236237
}
237238
}
238239

239-
// TODO sized, unsize_trait, builtin impls?
240+
if let Some(well_known) = trait_datum.well_known {
241+
builtin_traits::add_builtin_program_clauses(well_known, trait_ref, builder);
242+
}
240243
}
241244
DomainGoal::Holds(WhereClause::AliasEq(alias_predicate)) => {
242245
db.associated_ty_data(alias_predicate.alias.associated_ty_id)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use super::builder::ClauseBuilder;
2+
use crate::Interner;
3+
use crate::{TraitRef, WellKnownTrait};
4+
5+
/// For well known traits we have special hard-coded impls, either as an
6+
/// optimization or to enforce special rules for correctness.
7+
pub fn add_builtin_program_clauses<I: Interner>(
8+
well_known: WellKnownTrait,
9+
_trait_ref: &TraitRef<I>,
10+
_builder: &mut ClauseBuilder<I>,
11+
) {
12+
match well_known {
13+
WellKnownTrait::SizedTrait => { /* TODO */ }
14+
}
15+
}

chalk-solve/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub trait RustIrDatabase<I: Interner>: Debug {
2424
/// Returns the datum for the associated type with the given id.
2525
fn associated_ty_data(&self, ty: AssocTypeId<I>) -> Arc<AssociatedTyDatum<I>>;
2626

27-
/// Returns the datum for the impl with the given id.
27+
/// Returns the datum for the definition with the given id.
2828
fn trait_datum(&self, trait_id: TraitId<I>) -> Arc<TraitDatum<I>>;
2929

3030
/// Returns the datum for the impl with the given id.

0 commit comments

Comments
 (0)