diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index a63f708da6d..5affaaae3e0 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -54,6 +54,8 @@ pub struct TraitFlags { pub struct AssocTyDefn { pub name: Identifier, pub parameter_kinds: Vec, + pub bounds: Vec, + pub where_clauses: Vec, } pub enum ParameterKind { @@ -66,6 +68,28 @@ pub enum Parameter { Lifetime(Lifetime), } +/// An inline bound, e.g. `: Foo` in `impl> SomeType`. +pub enum InlineBound { + TraitBound(TraitBound), + ProjectionEqBound(ProjectionEqBound), +} + +/// Represents a trait bound on e.g. a type or type parameter. +/// Does not know anything about what it's binding. +pub struct TraitBound { + pub trait_name: Identifier, + pub args_no_self: Vec, +} + +/// Represents a projection equality bound on e.g. a type or type parameter. +/// Does not know anything about what it's binding. +pub struct ProjectionEqBound { + pub trait_bound: TraitBound, + pub name: Identifier, + pub parameters: Vec, + pub value: Ty, +} + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Kind { Ty, @@ -115,7 +139,6 @@ pub struct Impl { pub struct AssocTyValue { pub name: Identifier, pub parameter_kinds: Vec, - pub where_clauses: Vec, pub value: Ty, } diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index 71b528092ae..a043f68eb3d 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -72,9 +72,43 @@ TraitDefn: TraitDefn = { }; AssocTyDefn: AssocTyDefn = { - "type" > ";" => AssocTyDefn { - name: name, - parameter_kinds: p + "type" > >)?> + ";" => + { + AssocTyDefn { + name: name, + parameter_kinds: p, + where_clauses: w, + bounds: b.unwrap_or(vec![]), + } + } +}; + +InlineBound: InlineBound = { + TraitBound => InlineBound::TraitBound(<>), + ProjectionEqBound => InlineBound::ProjectionEqBound(<>), +}; + +TraitBound: TraitBound = { + > => { + TraitBound { + trait_name: t, + args_no_self: a, + } + } +}; + +ProjectionEqBound: ProjectionEqBound = { + "<" > ",")?> > + "=" ">" => ProjectionEqBound + { + trait_bound: TraitBound { + trait_name: t, + args_no_self: a.unwrap_or(vec![]), + }, + name, + parameters: a2, + value: ty, } }; @@ -102,11 +136,10 @@ ParameterKind: ParameterKind = { }; AssocTyValue: AssocTyValue = { - "type" > "=" ";" => AssocTyValue { + "type" > "=" ";" => AssocTyValue { name: n, parameter_kinds: a, value: v, - where_clauses: wc, }, }; @@ -201,11 +234,6 @@ InlineClause: Clause = { } }; -WhereClauses: Vec = { - "where" >, - () => vec![], -}; - QuantifiedWhereClauses: Vec = { "where" >, () => vec![], @@ -290,6 +318,11 @@ SemiColon: Vec = { > }; +#[inline] +Plus: Vec = { + > +}; + Angle: Vec = { "<" > ">", () => vec![], diff --git a/src/fold/mod.rs b/src/fold/mod.rs index d121d36a1f3..1fa900e7041 100644 --- a/src/fold/mod.rs +++ b/src/fold/mod.rs @@ -567,7 +567,7 @@ struct_fold!(AssociatedTyValue { associated_ty_id, value, }); -struct_fold!(AssociatedTyValueBound { ty, where_clauses }); +struct_fold!(AssociatedTyValueBound { ty }); struct_fold!(Environment { clauses }); struct_fold!(InEnvironment[F] { environment, goal } where F: Fold); struct_fold!(EqGoal { a, b }); diff --git a/src/ir/lowering/mod.rs b/src/ir/lowering/mod.rs index 395c8cca4ba..34d51cbd592 100644 --- a/src/ir/lowering/mod.rs +++ b/src/ir/lowering/mod.rs @@ -70,7 +70,7 @@ impl<'k> Env<'k> { /// Introduces new parameters, shifting the indices of existing /// parameters to accommodate them. The indices of the new binders /// will be assigned in order as they are iterated. - fn introduce(&self, binders: I) -> Self + fn introduce(&self, binders: I) -> Result where I: IntoIterator>, I::IntoIter: ExactSizeIterator, @@ -82,10 +82,13 @@ impl<'k> Env<'k> { .map(|(&k, &v)| (k, v + len)) .chain(binders) .collect(); - Env { + if parameter_map.len() != self.parameter_map.len() + len { + bail!("duplicate parameters"); + } + Ok(Env { parameter_map, ..*self - } + }) } fn in_binders(&self, binders: I, op: OP) -> Result> @@ -95,7 +98,7 @@ impl<'k> Env<'k> { OP: FnOnce(&Self) -> Result, { let binders: Vec<_> = binders.into_iter().collect(); - let env = self.introduce(binders.iter().cloned()); + let env = self.introduce(binders.iter().cloned())?; Ok(ir::Binders { binders: binders.anonymize(), value: op(&env)?, @@ -178,6 +181,7 @@ impl LowerProgram for Program { let mut parameter_kinds = defn.all_parameters(); parameter_kinds.extend(d.all_parameters()); + let env = empty_env.introduce(parameter_kinds.clone())?; associated_ty_data.insert( info.id, @@ -186,7 +190,7 @@ impl LowerProgram for Program { id: info.id, name: defn.name.str, parameter_kinds: parameter_kinds, - where_clauses: vec![], + where_clauses: defn.where_clauses.lower(&env)?, }, ); } @@ -757,7 +761,7 @@ impl LowerTy for Ty { lifetime_names .iter() .map(|id| ir::ParameterKind::Lifetime(id.str)), - ); + )?; let ty = ty.lower(&quantified_env)?; let quantified_ty = ir::QuantifiedTy { @@ -872,7 +876,6 @@ impl LowerAssocTyValue for AssocTyValue { let value = env.in_binders(self.all_parameters(), |env| { Ok(ir::AssociatedTyValueBound { ty: self.value.lower(env)?, - where_clauses: self.where_clauses.lower(env)?, }) })?; Ok(ir::AssociatedTyValue { diff --git a/src/ir/lowering/test.rs b/src/ir/lowering/test.rs index e23413f10aa..f97a10e27bd 100644 --- a/src/ir/lowering/test.rs +++ b/src/ir/lowering/test.rs @@ -211,8 +211,7 @@ fn atc_accounting() { AssociatedTyValue { associated_ty_id: (Iterable::Iter), value: for AssociatedTyValueBound { - ty: Iter<'?0, ?1>, - where_clauses: [] + ty: Iter<'?0, ?1> } } ], @@ -303,3 +302,71 @@ fn check_parameter_kinds() { } } } + +#[test] +fn gat_parse() { + lowering_success! { + program { + trait Sized {} + + trait Foo { + type Item<'a, T>: Sized + Clone where Self: Sized; + } + + trait Bar { + type Item<'a, T> where Self: Sized; + } + + struct Container { + value: T + } + + trait Baz { + type Item<'a, 'b, T>: Foo = Container> + Clone; + } + + trait Quux { + type Item<'a, T>; + } + } + } + + lowering_error! { + program { + trait Sized { } + + trait Foo { + type Item where K: Sized; + } + } + + error_msg { + "invalid type name `K`" + } + } +} + +#[test] +fn duplicate_parameters() { + lowering_error! { + program { + trait Foo { } + } + + error_msg { + "duplicate parameters" + } + } + + lowering_error! { + program { + trait Foo { + type Item; + } + } + + error_msg { + "duplicate parameters" + } + } +} diff --git a/src/ir/mod.rs b/src/ir/mod.rs index 66844c61b9f..e99392f71f4 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -273,8 +273,10 @@ pub struct AssociatedTyDatum { /// but possibly including more. crate parameter_kinds: Vec>, + // FIXME: inline bounds on the associated ty need to be implemented + /// Where clauses that must hold for the projection be well-formed. - crate where_clauses: Vec, + crate where_clauses: Vec, } #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -289,10 +291,6 @@ pub struct AssociatedTyValue { pub struct AssociatedTyValueBound { /// Type that we normalize to. The X in `type Foo<'a> = X`. crate ty: Ty, - - /// Where-clauses that must hold for projection to be valid. The - /// WC in `type Foo<'a> = X where WC`. - crate where_clauses: Vec, } #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] diff --git a/src/lib.rs b/src/lib.rs index c8dbaf5e029..e20ec4a7849 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,13 +3,11 @@ #![feature(catch_expr)] #![feature(crate_in_paths)] #![feature(crate_visibility_modifier)] -#![feature(dyn_trait)] #![feature(in_band_lifetimes)] #![feature(macro_at_most_once_rep)] #![feature(macro_vis_matcher)] #![feature(specialization)] #![feature(step_trait)] -#![feature(underscore_lifetimes)] extern crate chalk_parse; #[macro_use] diff --git a/src/rules/mod.rs b/src/rules/mod.rs index 2ced3cc2f8c..522a52132ef 100644 --- a/src/rules/mod.rs +++ b/src/rules/mod.rs @@ -200,10 +200,7 @@ impl ir::AssociatedTyValue { .trait_ref .trait_ref() .up_shift(self.value.len()); - let conditions: Vec = Some(impl_trait_ref.clone().cast()) - .into_iter() - .chain(self.value.value.where_clauses.clone().cast()) - .collect(); + let conditions: Vec = vec![impl_trait_ref.clone().cast()]; // Bound parameters + `Self` type of the trait-ref let parameters: Vec<_> = {