diff options
| author | Ben Blum <bblum@andrew.cmu.edu> | 2013-06-17 15:16:30 -0400 |
|---|---|---|
| committer | Ben Blum <bblum@andrew.cmu.edu> | 2013-06-23 14:40:14 -0400 |
| commit | ce857e3d60da1b5eff5d830dbd03f32a8890ad16 (patch) | |
| tree | 0874080aaf00735050a07a541f3f72b31818117d /src/libsyntax | |
| parent | 394f455b5edfe96b51bc713ccc65ad3db6bed92f (diff) | |
| download | rust-ce857e3d60da1b5eff5d830dbd03f32a8890ad16.tar.gz rust-ce857e3d60da1b5eff5d830dbd03f32a8890ad16.zip | |
Parse and typecheck (not kindcheck) bounds on trait paths.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/ty.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/pipec.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/ext/pipes/proto.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/parse/obsolete.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 63 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 17 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 10 |
13 files changed, 93 insertions, 60 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1758433aa73..2e3d557daa9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -797,7 +797,7 @@ pub enum ty_ { ty_closure(@TyClosure), ty_bare_fn(@TyBareFn), ty_tup(~[@Ty]), - ty_path(@Path, node_id), + ty_path(@Path, @OptVec<TyParamBound>, node_id), ty_mac(mac), // ty_infer means the type should be inferred instead of it having been // specified. This should only appear at the "top level" of a type and not diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 34c247662a4..24cf5662a36 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -473,7 +473,7 @@ pub fn id_visitor<T: Copy>(vfn: @fn(node_id, T)) -> visit::vt<T> { visit_ty: |ty, (t, vt)| { match ty.node { - ty_path(_, id) => vfn(id, copy t), + ty_path(_, _, id) => vfn(id, copy t), _ => { /* fall through */ } } visit::visit_ty(ty, (t, vt)); diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index dc31a248065..b6399794477 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -48,7 +48,7 @@ pub trait AstBuilder { fn ty_mt(&self, ty: @ast::Ty, mutbl: ast::mutability) -> ast::mt; fn ty(&self, span: span, ty: ast::ty_) -> @ast::Ty; - fn ty_path(&self, @ast::Path) -> @ast::Ty; + fn ty_path(&self, @ast::Path, @OptVec<ast::TyParamBound>) -> @ast::Ty; fn ty_ident(&self, span: span, idents: ast::ident) -> @ast::Ty; fn ty_rptr(&self, span: span, @@ -267,14 +267,17 @@ impl AstBuilder for @ExtCtxt { } } - fn ty_path(&self, path: @ast::Path) -> @ast::Ty { + fn ty_path(&self, path: @ast::Path, bounds: @OptVec<ast::TyParamBound>) + -> @ast::Ty { self.ty(path.span, - ast::ty_path(path, self.next_id())) + ast::ty_path(path, bounds, self.next_id())) } + // Might need to take bounds as an argument in the future, if you ever want + // to generate a bounded existential trait type. fn ty_ident(&self, span: span, ident: ast::ident) -> @ast::Ty { - self.ty_path(self.path_ident(span, ident)) + self.ty_path(self.path_ident(span, ident), @opt_vec::Empty) } fn ty_rptr(&self, @@ -304,7 +307,8 @@ impl AstBuilder for @ExtCtxt { self.ident_of("Option") ], None, - ~[ ty ])) + ~[ ty ]), + @opt_vec::Empty) } fn ty_field_imm(&self, span: span, name: ident, ty: @ast::Ty) -> ast::ty_field { @@ -342,7 +346,7 @@ impl AstBuilder for @ExtCtxt { fn ty_vars_global(&self, ty_params: &OptVec<ast::TyParam>) -> ~[@ast::Ty] { opt_vec::take_vec( ty_params.map(|p| self.ty_path( - self.path_global(dummy_sp(), ~[p.ident])))) + self.path_global(dummy_sp(), ~[p.ident]), @opt_vec::Empty))) } fn strip_bounds(&self, generics: &Generics) -> Generics { diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index dca1b7bbd59..981b28afd02 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -358,7 +358,8 @@ impl<'self> TraitDef<'self> { // Create the type of `self`. let self_type = cx.ty_path(cx.path_all(span, false, ~[ type_ident ], self_lifetime, - opt_vec::take_vec(self_ty_params))); + opt_vec::take_vec(self_ty_params)), + @opt_vec::Empty); let doc_attr = cx.attribute( span, diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs index 3b39cb691a6..d28613f52fa 100644 --- a/src/libsyntax/ext/deriving/ty.rs +++ b/src/libsyntax/ext/deriving/ty.rs @@ -65,7 +65,7 @@ impl<'self> Path<'self> { self_generics: &Generics) -> @ast::Ty { cx.ty_path(self.to_path(cx, span, - self_ty, self_generics)) + self_ty, self_generics), @opt_vec::Empty) } pub fn to_path(&self, cx: @ExtCtxt, @@ -144,7 +144,8 @@ impl<'self> Ty<'self> { } Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) } Self => { - cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) + cx.ty_path(self.to_path(cx, span, self_ty, self_generics), + @opt_vec::Empty) } Tuple(ref fields) => { let ty = if fields.is_empty() { diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs index 8478a827e85..a20528082ab 100644 --- a/src/libsyntax/ext/pipes/pipec.rs +++ b/src/libsyntax/ext/pipes/pipec.rs @@ -61,7 +61,7 @@ impl gen_send for message { let pipe_ty = cx.ty_path( path(~[this.data_name()], span) - .add_tys(cx.ty_vars(&this.generics.ty_params))); + .add_tys(cx.ty_vars(&this.generics.ty_params)), @opt_vec::Empty); let args_ast = vec::append( ~[cx.arg(span, cx.ident_of("pipe"), pipe_ty)], args_ast); @@ -117,7 +117,7 @@ impl gen_send for message { let mut rty = cx.ty_path(path(~[next.data_name()], span) - .add_tys(copy next_state.tys)); + .add_tys(copy next_state.tys), @opt_vec::Empty); if try { rty = cx.ty_option(rty); } @@ -146,7 +146,7 @@ impl gen_send for message { cx.ty_path( path(~[this.data_name()], span) .add_tys(cx.ty_vars( - &this.generics.ty_params))))], + &this.generics.ty_params)), @opt_vec::Empty))], args_ast); let message_args = if arg_names.len() == 0 { @@ -192,7 +192,7 @@ impl gen_send for message { fn to_ty(&mut self, cx: @ExtCtxt) -> @ast::Ty { cx.ty_path(path(~[cx.ident_of(self.name())], self.span()) - .add_tys(cx.ty_vars(&self.get_generics().ty_params))) + .add_tys(cx.ty_vars(&self.get_generics().ty_params)), @opt_vec::Empty) } } @@ -226,7 +226,7 @@ impl to_type_decls for state { cx.ty_path( path(~[cx.ident_of(dir), cx.ident_of(next_name)], span) - .add_tys(copy next_state.tys))) + .add_tys(copy next_state.tys), @opt_vec::Empty)) } None => tys }; @@ -279,7 +279,8 @@ impl to_type_decls for state { self.data_name()], dummy_sp()) .add_tys(cx.ty_vars( - &self.generics.ty_params))))), + &self.generics.ty_params)), @opt_vec::Empty)), + @opt_vec::Empty), cx.strip_bounds(&self.generics))); } else { @@ -298,8 +299,8 @@ impl to_type_decls for state { self.data_name()], dummy_sp()) .add_tys(cx.ty_vars_global( - &self.generics.ty_params))), - self.proto.buffer_ty_path(cx)])), + &self.generics.ty_params)), @opt_vec::Empty), + self.proto.buffer_ty_path(cx)]), @opt_vec::Empty), cx.strip_bounds(&self.generics))); }; items @@ -384,7 +385,7 @@ impl gen_init for protocol { cx.ty_path(path(~[cx.ident_of("super"), cx.ident_of("__Buffer")], copy self.span) - .add_tys(cx.ty_vars_global(¶ms))) + .add_tys(cx.ty_vars_global(¶ms)), @opt_vec::Empty) } fn gen_buffer_type(&self, cx: @ExtCtxt) -> @ast::item { diff --git a/src/libsyntax/ext/pipes/proto.rs b/src/libsyntax/ext/pipes/proto.rs index d00f1fd7746..87aaf7781fa 100644 --- a/src/libsyntax/ext/pipes/proto.rs +++ b/src/libsyntax/ext/pipes/proto.rs @@ -15,6 +15,7 @@ use codemap::span; use ext::base::ExtCtxt; use ext::build::AstBuilder; use ext::pipes::ast_builder::{append_types, path}; +use opt_vec; #[deriving(Eq)] pub enum direction { send, recv } @@ -101,7 +102,7 @@ impl state_ { pub fn to_ty(&self, cx: @ExtCtxt) -> @ast::Ty { cx.ty_path (path(~[cx.ident_of(self.name)],self.span).add_tys( - cx.ty_vars(&self.generics.ty_params))) + cx.ty_vars(&self.generics.ty_params)), @opt_vec::Empty) } /// Iterate over the states that can be reached in one message diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 568324bc599..4bd2c0a3de1 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -680,7 +680,9 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ { }) } ty_tup(ref tys) => ty_tup(tys.map(|ty| fld.fold_ty(*ty))), - ty_path(path, id) => ty_path(fld.fold_path(path), fld.new_id(id)), + ty_path(path, bounds, id) => + ty_path(fld.fold_path(path), + @bounds.map(|x| fold_ty_param_bound(x, fld)), fld.new_id(id)), ty_fixed_length_vec(ref mt, e) => { ty_fixed_length_vec( fold_mt(mt, fld), diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 5edd2ec4d47..0c5731c8b29 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -494,7 +494,7 @@ mod test { idents:~[str_to_ident("int")], rp: None, types: ~[]}, - 2), + @opt_vec::Empty, 2), span:sp(4,7)}, pat: @ast::pat{id:1, node: ast::pat_ident(ast::bind_infer, @@ -530,7 +530,7 @@ mod test { idents:~[str_to_ident("int")], rp: None, types: ~[]}, - 2), + @opt_vec::Empty, 2), span:sp(10,13)}, pat: @ast::pat{id:1, // fixme node: ast::pat_ident( diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index bb315bf2933..19b4d254580 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -46,7 +46,6 @@ pub enum ObsoleteSyntax { ObsoleteUnsafeBlock, ObsoleteUnenforcedBound, ObsoleteImplSyntax, - ObsoleteTraitBoundSeparator, ObsoleteMutOwnedPointer, ObsoleteMutVector, ObsoleteImplVisibility, @@ -143,10 +142,6 @@ impl Parser { "colon-separated impl syntax", "write `impl Trait for Type`" ), - ObsoleteTraitBoundSeparator => ( - "space-separated trait bounds", - "write `+` between trait bounds" - ), ObsoleteMutOwnedPointer => ( "const or mutable owned pointer", "mutability inherits through `~` pointers; place the `~` box diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 753c69b23d6..f2443f9e533 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -75,7 +75,7 @@ use parse::obsolete::{ObsoleteLet, ObsoleteFieldTerminator}; use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove, ObsoleteSwap}; use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds}; use parse::obsolete::{ObsoleteUnsafeBlock, ObsoleteImplSyntax}; -use parse::obsolete::{ObsoleteTraitBoundSeparator, ObsoleteMutOwnedPointer}; +use parse::obsolete::{ObsoleteMutOwnedPointer}; use parse::obsolete::{ObsoleteMutVector, ObsoleteImplVisibility}; use parse::obsolete::{ObsoleteRecordType, ObsoleteRecordPattern}; use parse::obsolete::{ObsoletePostFnTySigil}; @@ -710,8 +710,8 @@ impl Parser { } else if *self.token == token::MOD_SEP || is_ident_or_path(self.token) { // NAMED TYPE - let path = self.parse_path_with_tps(false); - ty_path(path, self.get_id()) + let (path, bounds) = self.parse_type_path(); + ty_path(path, @bounds, self.get_id()) } else { self.fatal(fmt!("expected type, found token %?", *self.token)); @@ -974,10 +974,8 @@ impl Parser { types: ~[] } } - // parse a path optionally with type parameters. If 'colons' - // is true, then type parameters must be preceded by colons, - // as in a::t::<t1,t2> - pub fn parse_path_with_tps(&self, colons: bool) -> @ast::Path { + pub fn parse_bounded_path_with_tps(&self, colons: bool, + before_tps: Option<&fn()>) -> @ast::Path { debug!("parse_path_with_tps(colons=%b)", colons); maybe_whole!(self, nt_path); @@ -987,6 +985,10 @@ impl Parser { return path; } + // If the path might have bounds on it, they should be parsed before + // the parameters, e.g. module::TraitName:B1+B2<T> + before_tps.map_consume(|callback| callback()); + // Parse the (obsolete) trailing region parameter, if any, which will // be written "foo/&x" let rp_slash = { @@ -1038,6 +1040,25 @@ impl Parser { .. copy *path } } + // parse a path optionally with type parameters. If 'colons' + // is true, then type parameters must be preceded by colons, + // as in a::t::<t1,t2> + pub fn parse_path_with_tps(&self, colons: bool) -> @ast::Path { + self.parse_bounded_path_with_tps(colons, None) + } + + // Like the above, but can also parse kind bounds in the case of a + // path to be used as a type that might be a trait. + pub fn parse_type_path(&self) -> (@ast::Path, OptVec<TyParamBound>) { + let mut bounds = opt_vec::Empty; + let path = self.parse_bounded_path_with_tps(false, Some(|| { + // Note: this closure might not even get called in the case of a + // macro-generated path. But that's the macro parser's job. + bounds = self.parse_optional_ty_param_bounds(); + })); + (path, bounds) + } + /// parses 0 or 1 lifetime pub fn parse_opt_lifetime(&self) -> Option<@ast::Lifetime> { match *self.token { @@ -2847,16 +2868,6 @@ impl Parser { spanned(lo, hi, bloc) } - fn mk_ty_path(&self, i: ident) -> @Ty { - @Ty { - id: self.get_id(), - node: ty_path( - ident_to_path(*self.last_span, i), - self.get_id()), - span: *self.last_span, - } - } - fn parse_optional_purity(&self) -> ast::purity { if self.eat_keyword(keywords::Pure) { self.obsolete(*self.last_span, ObsoletePurity); @@ -2921,13 +2932,8 @@ impl Parser { _ => break, } - if self.eat(&token::BINOP(token::PLUS)) { - loop; - } - - if is_ident_or_path(self.token) { - self.obsolete(*self.span, - ObsoleteTraitBoundSeparator); + if !self.eat(&token::BINOP(token::PLUS)) { + break; } } @@ -3284,14 +3290,19 @@ impl Parser { let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. let opt_trait_ref = match ty.node { - ty_path(path, node_id) => { + ty_path(path, @opt_vec::Empty, node_id) => { Some(@trait_ref { path: path, ref_id: node_id }) } + ty_path(*) => { + self.span_err(ty.span, + "bounded traits are only valid in type position"); + None + } _ => { - self.span_err(*self.span, "not a trait"); + self.span_err(ty.span, "not a trait"); None } }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 8e47df51010..fa22b7ceb71 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -422,7 +422,7 @@ pub fn print_type(s: @ps, ty: @ast::Ty) { f.purity, f.onceness, &f.decl, None, Some(&generics), None); } - ast::ty_path(path, _) => print_path(s, path, false), + ast::ty_path(path, bounds, _) => print_bounded_path(s, path, bounds), ast::ty_fixed_length_vec(ref mt, v) => { word(s.s, "["); match mt.mutbl { @@ -1483,7 +1483,8 @@ pub fn print_for_decl(s: @ps, loc: @ast::local, coll: @ast::expr) { print_expr(s, coll); } -pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) { +fn print_path_(s: @ps, path: @ast::Path, colons_before_params: bool, + opt_bounds: Option<@OptVec<ast::TyParamBound>>) { maybe_print_comment(s, path.span.lo); if path.global { word(s.s, "::"); } let mut first = true; @@ -1491,6 +1492,9 @@ pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) { if first { first = false; } else { word(s.s, "::"); } print_ident(s, *id); } + do opt_bounds.map_consume |bounds| { + print_bounds(s, bounds); + }; if path.rp.is_some() || !path.types.is_empty() { if colons_before_params { word(s.s, "::"); } @@ -1511,6 +1515,15 @@ pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) { } } +pub fn print_path(s: @ps, path: @ast::Path, colons_before_params: bool) { + print_path_(s, path, colons_before_params, None) +} + +pub fn print_bounded_path(s: @ps, path: @ast::Path, + bounds: @OptVec<ast::TyParamBound>) { + print_path_(s, path, false, Some(bounds)) +} + pub fn print_irrefutable_pat(s: @ps, pat: @ast::pat) { print_pat(s, pat, false) } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index e7afeb12a61..5aa38c0348c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -247,13 +247,17 @@ pub fn visit_ty<E: Copy>(t: @Ty, (e, v): (E, vt<E>)) { }, ty_closure(ref f) => { for f.decl.inputs.iter().advance |a| { (v.visit_ty)(a.ty, (copy e, v)); } - (v.visit_ty)(f.decl.output, (e, v)); + (v.visit_ty)(f.decl.output, (copy e, v)); + visit_ty_param_bounds(&f.bounds, (e, v)); }, ty_bare_fn(ref f) => { for f.decl.inputs.iter().advance |a| { (v.visit_ty)(a.ty, (copy e, v)); } (v.visit_ty)(f.decl.output, (e, v)); }, - ty_path(p, _) => visit_path(p, (e, v)), + ty_path(p, bounds, _) => { + visit_path(p, (copy e, v)); + visit_ty_param_bounds(bounds, (e, v)); + }, ty_fixed_length_vec(ref mt, ex) => { (v.visit_ty)(mt.ty, (copy e, v)); (v.visit_expr)(ex, (copy e, v)); @@ -328,7 +332,7 @@ pub fn visit_foreign_item<E: Copy>(ni: @foreign_item, (e, v): (E, vt<E>)) { } } -pub fn visit_ty_param_bounds<E: Copy>(bounds: @OptVec<TyParamBound>, +pub fn visit_ty_param_bounds<E: Copy>(bounds: &OptVec<TyParamBound>, (e, v): (E, vt<E>)) { for bounds.each |bound| { match *bound { |
