From e490665776ae75f30ce769b357df5ff0f702b7da Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Sat, 5 May 2018 00:03:12 -0500 Subject: [PATCH 1/5] Remove where clauses on associated type values --- chalk-parse/src/ast.rs | 1 - chalk-parse/src/parser.lalrpop | 8 +------- src/fold/mod.rs | 2 +- src/ir/lowering/mod.rs | 1 - src/ir/lowering/test.rs | 3 +-- src/ir/mod.rs | 4 ---- src/rules/mod.rs | 5 +---- 7 files changed, 4 insertions(+), 20 deletions(-) diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index a63f708da6d..bd03fcb005b 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -115,7 +115,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..43cab905350 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -102,11 +102,10 @@ ParameterKind: ParameterKind = { }; AssocTyValue: AssocTyValue = { - "type" > "=" ";" => AssocTyValue { + "type" > "=" ";" => AssocTyValue { name: n, parameter_kinds: a, value: v, - where_clauses: wc, }, }; @@ -201,11 +200,6 @@ InlineClause: Clause = { } }; -WhereClauses: Vec = { - "where" >, - () => vec![], -}; - QuantifiedWhereClauses: Vec = { "where" >, () => 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..f0066ee9124 100644 --- a/src/ir/lowering/mod.rs +++ b/src/ir/lowering/mod.rs @@ -872,7 +872,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..c248af698b9 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> } } ], diff --git a/src/ir/mod.rs b/src/ir/mod.rs index 66844c61b9f..64c5d047207 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -289,10 +289,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/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<_> = { From 23ec2132f8076c5035e14a7d1baa8b73cf5d83b3 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Sun, 6 May 2018 17:40:18 -0500 Subject: [PATCH 2/5] Add parse rules for GATs --- chalk-parse/src/ast.rs | 2 ++ chalk-parse/src/parser.lalrpop | 23 ++++++++++++++++++++--- src/ir/lowering/test.rs | 31 +++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index bd03fcb005b..5b7daf6d6de 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 bound: Option, + pub where_clauses: Vec, } pub enum ParameterKind { diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index 43cab905350..448912bb0b6 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -72,9 +72,26 @@ TraitDefn: TraitDefn = { }; AssocTyDefn: AssocTyDefn = { - "type" > ";" => AssocTyDefn { - name: name, - parameter_kinds: p + "type" > >)?> + ";" => + { + let bound = match b { + Some((t, a)) => { + let mut args = vec![Parameter::Ty(Ty::Id{ name })]; + args.extend(a); + Some(TraitRef { + trait_name: t, + args: args, + }) + } + None => None + }; + AssocTyDefn { + name: name, + parameter_kinds: p, + where_clauses: w, + bound, + } } }; diff --git a/src/ir/lowering/test.rs b/src/ir/lowering/test.rs index c248af698b9..76b4ace8b19 100644 --- a/src/ir/lowering/test.rs +++ b/src/ir/lowering/test.rs @@ -302,3 +302,34 @@ fn check_parameter_kinds() { } } } + +#[test] +fn gat_parse() { + let program = Arc::new( + parse_and_lower_program( + " + trait Sized {} + + trait Foo { + type Item<'a, T>: Clone where Self: Sized; + } + + trait Bar { + type Item<'a, T> where Self: Sized; + } + + trait Baz { + type Item<'a, T>: Clone; + } + + trait Quux { + type Item<'a, T>; + } + ", + SolverChoice::slg() + ).unwrap() + ); + tls::set_current_program(&program, || { + println!("{:#?}", program.associated_ty_data.values()); + }); +} From 3a6169e025d9eb51dbf773046a4e8cab583b210d Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 8 May 2018 22:02:02 -0500 Subject: [PATCH 3/5] Add support for + on GAT bounds --- chalk-parse/src/ast.rs | 7 ++++++- chalk-parse/src/parser.lalrpop | 29 ++++++++++++++++------------- src/ir/lowering/test.rs | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index 5b7daf6d6de..a97245348cc 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -54,7 +54,7 @@ pub struct TraitFlags { pub struct AssocTyDefn { pub name: Identifier, pub parameter_kinds: Vec, - pub bound: Option, + pub bounds: Vec, pub where_clauses: Vec, } @@ -177,6 +177,11 @@ impl PolarizedTraitRef { } } +pub struct TraitBound { + pub trait_name: Identifier, + pub args_no_self: Vec, +} + #[derive(Copy, Clone, Debug)] pub struct Identifier { pub str: InternedString, diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index 448912bb0b6..d357df68292 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -72,25 +72,23 @@ TraitDefn: TraitDefn = { }; AssocTyDefn: AssocTyDefn = { - "type" > >)?> + "type" > >)?> ";" => { - let bound = match b { - Some((t, a)) => { - let mut args = vec![Parameter::Ty(Ty::Id{ name })]; - args.extend(a); - Some(TraitRef { - trait_name: t, - args: args, - }) - } - None => None - }; AssocTyDefn { name: name, parameter_kinds: p, where_clauses: w, - bound, + bounds: b.unwrap_or(vec![]), + } + } +}; + +TraitBound: TraitBound = { + > => { + TraitBound { + trait_name: t, + args_no_self: a, } } }; @@ -301,6 +299,11 @@ SemiColon: Vec = { > }; +#[inline] +Plus: Vec = { + > +}; + Angle: Vec = { "<" > ">", () => vec![], diff --git a/src/ir/lowering/test.rs b/src/ir/lowering/test.rs index 76b4ace8b19..4fd6e4f4e3b 100644 --- a/src/ir/lowering/test.rs +++ b/src/ir/lowering/test.rs @@ -311,7 +311,7 @@ fn gat_parse() { trait Sized {} trait Foo { - type Item<'a, T>: Clone where Self: Sized; + type Item<'a, T>: Sized + Clone where Self: Sized; } trait Bar { From 52c171e2227c594f5a29209f180d50540d46fd9c Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Tue, 8 May 2018 22:23:32 -0500 Subject: [PATCH 4/5] Add parse rules for ProjectionEq bounds on GATs --- chalk-parse/src/ast.rs | 24 +++++++++++++++++++----- chalk-parse/src/parser.lalrpop | 14 +++++++++++++- src/ir/lowering/test.rs | 6 +++++- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index a97245348cc..099f91037c0 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -68,6 +68,25 @@ pub enum Parameter { Lifetime(Lifetime), } +/// 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, +} + +pub enum TraitBoundParameter { + Ty(Ty), + Lifetime(Lifetime), + ProjectionEq(ProjectionEqBound), +} + +pub struct ProjectionEqBound { + pub name: Identifier, + pub parameters: Vec, + pub value: Ty, +} + #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Kind { Ty, @@ -177,11 +196,6 @@ impl PolarizedTraitRef { } } -pub struct TraitBound { - pub trait_name: Identifier, - pub args_no_self: Vec, -} - #[derive(Copy, Clone, Debug)] pub struct Identifier { pub str: InternedString, diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index d357df68292..96e90e1f76e 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -85,7 +85,7 @@ AssocTyDefn: AssocTyDefn = { }; TraitBound: TraitBound = { - > => { + > => { TraitBound { trait_name: t, args_no_self: a, @@ -93,6 +93,18 @@ TraitBound: TraitBound = { } }; +TraitBoundParameter: TraitBoundParameter = { + Ty => TraitBoundParameter::Ty(<>), + Lifetime => TraitBoundParameter::Lifetime(<>), + ProjectionEqBound => TraitBoundParameter::ProjectionEq(<>), +}; + +ProjectionEqBound: ProjectionEqBound = { + > "=" => ProjectionEqBound { + name, parameters, value + }, +}; + Impl: Impl = { "impl" > > "for" "{" "}" => diff --git a/src/ir/lowering/test.rs b/src/ir/lowering/test.rs index 4fd6e4f4e3b..8aa6e635cf1 100644 --- a/src/ir/lowering/test.rs +++ b/src/ir/lowering/test.rs @@ -318,8 +318,12 @@ fn gat_parse() { type Item<'a, T> where Self: Sized; } + struct Container { + value: T + } + trait Baz { - type Item<'a, T>: Clone; + type Item<'a, 'b, T>: Foo = Containter> + Clone; } trait Quux { From 0db2be984aa34cd46a9e907b5e1700c2414b4d01 Mon Sep 17 00:00:00 2001 From: scalexm Date: Thu, 10 May 2018 15:19:16 +0200 Subject: [PATCH 5/5] Tweak inline bounds on associated types in the grammar --- chalk-parse/src/ast.rs | 19 +++++++----- chalk-parse/src/parser.lalrpop | 29 +++++++++++------- src/ir/lowering/mod.rs | 16 ++++++---- src/ir/lowering/test.rs | 55 +++++++++++++++++++++++++++------- src/ir/mod.rs | 4 ++- src/lib.rs | 2 -- 6 files changed, 86 insertions(+), 39 deletions(-) diff --git a/chalk-parse/src/ast.rs b/chalk-parse/src/ast.rs index 099f91037c0..5affaaae3e0 100644 --- a/chalk-parse/src/ast.rs +++ b/chalk-parse/src/ast.rs @@ -54,7 +54,7 @@ pub struct TraitFlags { pub struct AssocTyDefn { pub name: Identifier, pub parameter_kinds: Vec, - pub bounds: Vec, + pub bounds: Vec, pub where_clauses: Vec, } @@ -68,20 +68,23 @@ 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, -} - -pub enum TraitBoundParameter { - Ty(Ty), - Lifetime(Lifetime), - ProjectionEq(ProjectionEqBound), + 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, diff --git a/chalk-parse/src/parser.lalrpop b/chalk-parse/src/parser.lalrpop index 96e90e1f76e..a043f68eb3d 100644 --- a/chalk-parse/src/parser.lalrpop +++ b/chalk-parse/src/parser.lalrpop @@ -72,7 +72,7 @@ TraitDefn: TraitDefn = { }; AssocTyDefn: AssocTyDefn = { - "type" > >)?> + "type" > >)?> ";" => { AssocTyDefn { @@ -84,8 +84,13 @@ AssocTyDefn: AssocTyDefn = { } }; +InlineBound: InlineBound = { + TraitBound => InlineBound::TraitBound(<>), + ProjectionEqBound => InlineBound::ProjectionEqBound(<>), +}; + TraitBound: TraitBound = { - > => { + > => { TraitBound { trait_name: t, args_no_self: a, @@ -93,16 +98,18 @@ TraitBound: TraitBound = { } }; -TraitBoundParameter: TraitBoundParameter = { - Ty => TraitBoundParameter::Ty(<>), - Lifetime => TraitBoundParameter::Lifetime(<>), - ProjectionEqBound => TraitBoundParameter::ProjectionEq(<>), -}; - ProjectionEqBound: ProjectionEqBound = { - > "=" => ProjectionEqBound { - name, parameters, value - }, + "<" > ",")?> > + "=" ">" => ProjectionEqBound + { + trait_bound: TraitBound { + trait_name: t, + args_no_self: a.unwrap_or(vec![]), + }, + name, + parameters: a2, + value: ty, + } }; Impl: Impl = { diff --git a/src/ir/lowering/mod.rs b/src/ir/lowering/mod.rs index f0066ee9124..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 { diff --git a/src/ir/lowering/test.rs b/src/ir/lowering/test.rs index 8aa6e635cf1..f97a10e27bd 100644 --- a/src/ir/lowering/test.rs +++ b/src/ir/lowering/test.rs @@ -305,9 +305,8 @@ fn check_parameter_kinds() { #[test] fn gat_parse() { - let program = Arc::new( - parse_and_lower_program( - " + lowering_success! { + program { trait Sized {} trait Foo { @@ -323,17 +322,51 @@ fn gat_parse() { } trait Baz { - type Item<'a, 'b, T>: Foo = Containter> + Clone; + type Item<'a, 'b, T>: Foo = Container> + Clone; } trait Quux { type Item<'a, T>; } - ", - SolverChoice::slg() - ).unwrap() - ); - tls::set_current_program(&program, || { - println!("{:#?}", program.associated_ty_data.values()); - }); + } + } + + 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 64c5d047207..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)] 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]