diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2014-11-29 17:08:30 +1300 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2014-12-12 19:11:59 +1300 |
| commit | 397dda8aa08ee540cffd36f542ebd1140227d0bd (patch) | |
| tree | ee4cc3c5f3434375ef05a0092f7df8154708b765 /src/libsyntax | |
| parent | da83ad8e2c8e2c5f522dc59963e00f55b1f8c03b (diff) | |
| download | rust-397dda8aa08ee540cffd36f542ebd1140227d0bd.tar.gz rust-397dda8aa08ee540cffd36f542ebd1140227d0bd.zip | |
Add support for equality constraints on associated types
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 43 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/mod.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/ty.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/rand.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/ext/env.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ext/format.rs | 1 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 48 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 177 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 28 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 18 |
12 files changed, 290 insertions, 65 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 11af1a43277..ea8de458ce2 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -255,6 +255,7 @@ impl PathParameters { AngleBracketedParameters(AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) } @@ -307,6 +308,17 @@ impl PathParameters { } } } + + pub fn bindings(&self) -> Vec<&P<TypeBinding>> { + match *self { + AngleBracketedParameters(ref data) => { + data.bindings.iter().collect() + } + ParenthesizedParameters(_) => { + Vec::new() + } + } + } } /// A path like `Foo<'a, T>` @@ -316,11 +328,14 @@ pub struct AngleBracketedParameterData { pub lifetimes: Vec<Lifetime>, /// The type parameters for this path segment, if present. pub types: OwnedSlice<P<Ty>>, + /// Bindings (equality constraints) on associated types, if present. + /// E.g., `Foo<A=Bar>`. + pub bindings: OwnedSlice<P<TypeBinding>>, } impl AngleBracketedParameterData { fn is_empty(&self) -> bool { - self.lifetimes.is_empty() && self.types.is_empty() + self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty() } } @@ -406,13 +421,27 @@ pub struct WhereClause { } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] -pub struct WherePredicate { +pub enum WherePredicate { + BoundPredicate(WhereBoundPredicate), + EqPredicate(WhereEqPredicate) +} + +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct WhereBoundPredicate { pub id: NodeId, pub span: Span, pub ident: Ident, pub bounds: OwnedSlice<TyParamBound>, } +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct WhereEqPredicate { + pub id: NodeId, + pub span: Span, + pub path: Path, + pub ty: P<Ty>, +} + /// The set of MetaItems that define the compilation environment of the crate, /// used to drive conditional compilation pub type CrateConfig = Vec<P<MetaItem>> ; @@ -1118,6 +1147,16 @@ impl FloatTy { } } +// Bind a type to an associated type: `A=Foo`. +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct TypeBinding { + pub id: NodeId, + pub ident: Ident, + pub ty: P<Ty>, + pub span: Span, +} + + // NB PartialEq method appears below. #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct Ty { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 7dba6a57fc4..eec3f69ee64 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -174,12 +174,28 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) } ), } } +// If path is a single segment ident path, return that ident. Otherwise, return +// None. +pub fn path_to_ident(path: &Path) -> Option<Ident> { + if path.segments.len() != 1 { + return None; + } + + let segment = &path.segments[0]; + if !segment.parameters.is_empty() { + return None; + } + + Some(segment.identifier) +} + pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> P<Pat> { P(Pat { id: id, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index b4bb1a1a529..84040bcfa9f 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -37,7 +37,8 @@ pub trait AstBuilder { global: bool, idents: Vec<ast::Ident> , lifetimes: Vec<ast::Lifetime>, - types: Vec<P<ast::Ty>> ) + types: Vec<P<ast::Ty>>, + bindings: Vec<P<ast::TypeBinding>> ) -> ast::Path; // types @@ -293,20 +294,21 @@ pub trait AstBuilder { impl<'a> AstBuilder for ExtCtxt<'a> { fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path { - self.path_all(span, false, strs, Vec::new(), Vec::new()) + self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new()) } fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path { self.path(span, vec!(id)) } fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path { - self.path_all(span, true, strs, Vec::new(), Vec::new()) + self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) } fn path_all(&self, sp: Span, global: bool, mut idents: Vec<ast::Ident> , lifetimes: Vec<ast::Lifetime>, - types: Vec<P<ast::Ty>> ) + types: Vec<P<ast::Ty>>, + bindings: Vec<P<ast::TypeBinding>> ) -> ast::Path { let last_identifier = idents.pop().unwrap(); let mut segments: Vec<ast::PathSegment> = idents.into_iter() @@ -321,6 +323,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }) }); ast::Path { @@ -391,7 +394,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.ident_of("Option") ), Vec::new(), - vec!( ty ))) + vec!( ty ), + Vec::new())) } fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField { diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index d5f472bd827..cf3b3ad9051 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -444,7 +444,7 @@ impl<'a> TraitDef<'a> { // Create the type of `self`. let self_type = cx.ty_path( cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes, - self_ty_params.into_vec())); + self_ty_params.into_vec(), Vec::new())); let attr = cx.attribute( self.span, diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index 01398273161..56d11c2377f 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -80,7 +80,7 @@ impl<'a> Path<'a> { let lt = mk_lifetimes(cx, span, &self.lifetime); let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); - cx.path_all(span, self.global, idents, lt, tys) + cx.path_all(span, self.global, idents, lt, tys, Vec::new()) } } @@ -177,7 +177,7 @@ impl<'a> Ty<'a> { .collect(); cx.path_all(span, false, vec!(self_ty), lifetimes, - self_params.into_vec()) + self_params.into_vec(), Vec::new()) } Literal(ref p) => { p.to_path(cx, span, self_ty, self_generics) diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 8ad8436906b..c4e64d58c29 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -88,6 +88,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) true, rand_ident.clone(), Vec::new(), + Vec::new(), Vec::new()); let rand_name = cx.expr_path(rand_name); diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index e6a44c57f1b..8c17b31f458 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -45,7 +45,8 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT Some(cx.lifetime(sp, cx.ident_of( "'static").name)), - ast::MutImmutable)))) + ast::MutImmutable)), + Vec::new())) } Some(s) => { cx.expr_call_global(sp, diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index c8fed3dcd16..5d595474e9c 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -530,6 +530,7 @@ impl<'a, 'b> Context<'a, 'b> { self.fmtsp, true, Context::rtpath(self.ecx, "Argument"), vec![static_lifetime], + vec![], vec![] )); lets.push(Context::item_static_array(self.ecx, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 122f99cabb3..69e311c57f5 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -146,6 +146,10 @@ pub trait Folder { noop_fold_qpath(t, self) } + fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> { + noop_fold_ty_binding(t, self) + } + fn fold_mod(&mut self, m: Mod) -> Mod { noop_fold_mod(m, self) } @@ -391,6 +395,15 @@ pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl> }) } +pub fn noop_fold_ty_binding<T: Folder>(b: P<TypeBinding>, fld: &mut T) -> P<TypeBinding> { + b.map(|TypeBinding { id, ident, ty, span }| TypeBinding { + id: fld.new_id(id), + ident: ident, + ty: fld.fold_ty(ty), + span: fld.new_span(span), + }) +} + pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { t.map(|Ty {id, node, span}| Ty { id: fld.new_id(id), @@ -533,9 +546,10 @@ pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedP fld: &mut T) -> AngleBracketedParameterData { - let AngleBracketedParameterData { lifetimes, types } = data; + let AngleBracketedParameterData { lifetimes, types, bindings } = data; AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes), - types: types.move_map(|ty| fld.fold_ty(ty)) } + types: types.move_map(|ty| fld.fold_ty(ty)), + bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) } } pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData, @@ -807,14 +821,32 @@ pub fn noop_fold_where_clause<T: Folder>( } pub fn noop_fold_where_predicate<T: Folder>( - WherePredicate {id, ident, bounds, span}: WherePredicate, + pred: WherePredicate, fld: &mut T) -> WherePredicate { - WherePredicate { - id: fld.new_id(id), - ident: fld.fold_ident(ident), - bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), - span: fld.new_span(span) + match pred { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{id, + ident, + bounds, + span}) => { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + id: fld.new_id(id), + ident: fld.fold_ident(ident), + bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), + span: fld.new_span(span) + }) + } + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, + path, + ty, + span}) => { + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ + id: fld.new_id(id), + path: fld.fold_path(path), + ty:fld.fold_ty(ty), + span: fld.new_span(span) + }) + } } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4929ee885ac..92c7380a61d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -53,7 +53,7 @@ use ast::{StructVariantKind, BiSub, StrStyle}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; use ast::{TtDelimited, TtSequence, TtToken}; -use ast::{TupleVariantKind, Ty, Ty_}; +use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; @@ -62,7 +62,7 @@ use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; use ast::{UnnamedField, UnsafeBlock}; use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; -use ast::{Visibility, WhereClause, WherePredicate}; +use ast::{Visibility, WhereClause}; use ast; use ast_util::{mod, as_prec, ident_to_path, operator_prec}; use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp}; @@ -769,13 +769,10 @@ impl<'a> Parser<'a> { } } - /// Parse a sequence bracketed by '<' and '>', stopping - /// before the '>'. - pub fn parse_seq_to_before_gt<T>( - &mut self, - sep: Option<token::Token>, - f: |&mut Parser| -> T) - -> OwnedSlice<T> { + pub fn parse_seq_to_before_gt_or_return<T>(&mut self, + sep: Option<token::Token>, + f: |&mut Parser| -> Option<T>) + -> (OwnedSlice<T>, bool) { let mut v = Vec::new(); // This loop works by alternating back and forth between parsing types // and commas. For example, given a string `A, B,>`, the parser would @@ -792,24 +789,48 @@ impl<'a> Parser<'a> { } if i % 2 == 0 { - v.push(f(self)); + match f(self) { + Some(result) => v.push(result), + None => return (OwnedSlice::from_vec(v), true) + } } else { sep.as_ref().map(|t| self.expect(t)); } } - return OwnedSlice::from_vec(v); + return (OwnedSlice::from_vec(v), false); + } + + /// Parse a sequence bracketed by '<' and '>', stopping + /// before the '>'. + pub fn parse_seq_to_before_gt<T>(&mut self, + sep: Option<token::Token>, + f: |&mut Parser| -> T) + -> OwnedSlice<T> { + let (result, returned) = self.parse_seq_to_before_gt_or_return(sep, |p| Some(f(p))); + assert!(!returned); + return result; } - pub fn parse_seq_to_gt<T>( - &mut self, - sep: Option<token::Token>, - f: |&mut Parser| -> T) - -> OwnedSlice<T> { + pub fn parse_seq_to_gt<T>(&mut self, + sep: Option<token::Token>, + f: |&mut Parser| -> T) + -> OwnedSlice<T> { let v = self.parse_seq_to_before_gt(sep, f); self.expect_gt(); return v; } + pub fn parse_seq_to_gt_or_return<T>(&mut self, + sep: Option<token::Token>, + f: |&mut Parser| -> Option<T>) + -> (OwnedSlice<T>, bool) { + let (v, returned) = self.parse_seq_to_before_gt_or_return(sep, f); + if !returned { + self.expect_gt(); + } + return (v, returned); + } + /// Parse a sequence, including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. @@ -1842,11 +1863,12 @@ impl<'a> Parser<'a> { // Parse types, optionally. let parameters = if self.eat_lt(false) { - let (lifetimes, types) = self.parse_generic_values_after_lt(); + let (lifetimes, types, bindings) = self.parse_generic_values_after_lt(); ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }) } else if self.eat(&token::OpenDelim(token::Paren)) { let inputs = self.parse_seq_to_end( @@ -1894,6 +1916,7 @@ impl<'a> Parser<'a> { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) }); return segments; @@ -1902,12 +1925,13 @@ impl<'a> Parser<'a> { // Check for a type segment. if self.eat_lt(false) { // Consumed `a::b::<`, go look for types - let (lifetimes, types) = self.parse_generic_values_after_lt(); + let (lifetimes, types, bindings) = self.parse_generic_values_after_lt(); segments.push(ast::PathSegment { identifier: identifier, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }), }); @@ -2435,13 +2459,18 @@ impl<'a> Parser<'a> { let dot = self.last_span.hi; hi = self.span.hi; self.bump(); - let (_, tys) = if self.eat(&token::ModSep) { + let (_, tys, bindings) = if self.eat(&token::ModSep) { self.expect_lt(); self.parse_generic_values_after_lt() } else { - (Vec::new(), Vec::new()) + (Vec::new(), Vec::new(), Vec::new()) }; + if bindings.len() > 0 { + let last_span = self.last_span; + self.span_err(last_span, "type bindings are only permitted on trait paths"); + } + // expr.f() method call match self.token { token::OpenDelim(token::Paren) => { @@ -4041,16 +4070,51 @@ impl<'a> Parser<'a> { } } - fn parse_generic_values_after_lt(&mut self) -> (Vec<ast::Lifetime>, Vec<P<Ty>> ) { + fn parse_generic_values_after_lt(&mut self) + -> (Vec<ast::Lifetime>, Vec<P<Ty>>, Vec<P<TypeBinding>>) { let lifetimes = self.parse_lifetimes(token::Comma); - let result = self.parse_seq_to_gt( + + // First parse types. + let (types, returned) = self.parse_seq_to_gt_or_return( + Some(token::Comma), + |p| { + p.forbid_lifetime(); + if p.look_ahead(1, |t| t == &token::Eq) { + None + } else { + Some(p.parse_ty_sum()) + } + } + ); + + // If we found the `>`, don't continue. + if !returned { + return (lifetimes, types.into_vec(), Vec::new()); + } + + // Then parse type bindings. + let bindings = self.parse_seq_to_gt( Some(token::Comma), |p| { p.forbid_lifetime(); - p.parse_ty_sum() + let lo = p.span.lo; + let ident = p.parse_ident(); + let found_eq = p.eat(&token::Eq); + if !found_eq { + let span = p.span; + p.span_warn(span, "whoops, no =?"); + } + let ty = p.parse_ty(); + let hi = p.span.hi; + let span = mk_sp(lo, hi); + return P(TypeBinding{id: ast::DUMMY_NODE_ID, + ident: ident, + ty: ty, + span: span, + }); } ); - (lifetimes, result.into_vec()) + (lifetimes, types.into_vec(), bindings.into_vec()) } fn forbid_lifetime(&mut self) { @@ -4070,29 +4134,58 @@ impl<'a> Parser<'a> { let mut parsed_something = false; loop { let lo = self.span.lo; - let ident = match self.token { - token::Ident(..) => self.parse_ident(), + let path = match self.token { + token::Ident(..) => self.parse_path(NoTypesAllowed), _ => break, }; - self.expect(&token::Colon); - let bounds = self.parse_ty_param_bounds(); - let hi = self.span.hi; - let span = mk_sp(lo, hi); + if self.eat(&token::Colon) { + let bounds = self.parse_ty_param_bounds(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); - if bounds.len() == 0 { - self.span_err(span, - "each predicate in a `where` clause must have \ - at least one bound in it"); - } + if bounds.len() == 0 { + self.span_err(span, + "each predicate in a `where` clause must have \ + at least one bound in it"); + } - generics.where_clause.predicates.push(ast::WherePredicate { - id: ast::DUMMY_NODE_ID, - span: span, - ident: ident, - bounds: bounds, - }); - parsed_something = true; + let ident = match ast_util::path_to_ident(&path) { + Some(ident) => ident, + None => { + self.span_err(path.span, "expected a single identifier \ + in bound where clause"); + break; + } + }; + + generics.where_clause.predicates.push( + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + id: ast::DUMMY_NODE_ID, + span: span, + ident: ident, + bounds: bounds, + })); + parsed_something = true; + } else if self.eat(&token::Eq) { + let ty = self.parse_ty(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); + generics.where_clause.predicates.push( + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + id: ast::DUMMY_NODE_ID, + span: span, + path: path, + ty: ty, + })); + parsed_something = true; + // FIXME(#18433) + self.span_err(span, "equality constraints are not yet supported in where clauses"); + } else { + let last_span = self.last_span; + self.span_err(last_span, + "unexpected token in `where` clause"); + } if !self.eat(&token::Comma) { break diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index eab03f73091..26373d00aaf 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1976,6 +1976,18 @@ impl<'a> State<'a> { Inconsistent, data.types.as_slice(), |s, ty| s.print_type(&**ty))); + comma = true; + } + + for binding in data.bindings.iter() { + if comma { + try!(self.word_space(",")) + } + try!(self.print_ident(binding.ident)); + try!(space(&mut self.s)); + try!(self.word_space("=")); + try!(self.print_type(&*binding.ty)); + comma = true; } try!(word(&mut self.s, ">")) @@ -2437,8 +2449,20 @@ impl<'a> State<'a> { try!(self.word_space(",")); } - try!(self.print_ident(predicate.ident)); - try!(self.print_bounds(":", predicate.bounds.as_slice())); + match predicate { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ident, + ref bounds, + ..}) => { + try!(self.print_ident(ident)); + try!(self.print_bounds(":", bounds.as_slice())); + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { + try!(self.print_path(path, false)); + try!(space(&mut self.s)); + try!(self.word_space("=")); + try!(self.print_type(&**ty)); + } + } } Ok(()) diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f5e89dd61ff..a36f8b23ca3 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -573,8 +573,22 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics } walk_lifetime_decls_helper(visitor, &generics.lifetimes); for predicate in generics.where_clause.predicates.iter() { - visitor.visit_ident(predicate.span, predicate.ident); - walk_ty_param_bounds_helper(visitor, &predicate.bounds); + match predicate { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{span, + ident, + ref bounds, + ..}) => { + visitor.visit_ident(span, ident); + walk_ty_param_bounds_helper(visitor, bounds); + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, + ref path, + ref ty, + ..}) => { + visitor.visit_path(path, id); + visitor.visit_ty(&**ty); + } + } } } |
