diff options
| author | Dustin Speckhals <dustin1114@gmail.com> | 2017-10-24 19:37:15 -0400 |
|---|---|---|
| committer | Dustin Speckhals <dustin1114@gmail.com> | 2017-10-24 19:37:15 -0400 |
| commit | bca47e42b2c878eafb109c59cf0c8074043c1251 (patch) | |
| tree | 968a99f37f9099c4ed0b68b8020400322e94b667 /src/libsyntax | |
| parent | 69ba6738eb6bf9b6d11ebb81af2599648eb0bc04 (diff) | |
| parent | c2799fc9a5c631a790744ceb9cd08259af338c0c (diff) | |
| download | rust-bca47e42b2c878eafb109c59cf0c8074043c1251.tar.gz rust-bca47e42b2c878eafb109c59cf0c8074043c1251.zip | |
Merge branch 'master' into update-rls-data-for-save-analysis
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax/codemap.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/placeholders.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 22 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/parse/lexer/unicode_chars.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 150 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 6 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 17 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 16 |
10 files changed, 184 insertions, 75 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 021f96aff8c..090fc193b38 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1178,7 +1178,6 @@ pub struct MethodSig { pub constness: Spanned<Constness>, pub abi: Abi, pub decl: P<FnDecl>, - pub generics: Generics, } /// Represents an item declaration within a trait declaration, @@ -1190,6 +1189,7 @@ pub struct TraitItem { pub id: NodeId, pub ident: Ident, pub attrs: Vec<Attribute>, + pub generics: Generics, pub node: TraitItemKind, pub span: Span, /// See `Item::tokens` for what this is @@ -1211,6 +1211,7 @@ pub struct ImplItem { pub vis: Visibility, pub defaultness: Defaultness, pub attrs: Vec<Attribute>, + pub generics: Generics, pub node: ImplItemKind, pub span: Span, /// See `Item::tokens` for what this is @@ -1419,7 +1420,7 @@ pub enum TyKind { Path(Option<QSelf>, Path), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. - TraitObject(TyParamBounds), + TraitObject(TyParamBounds, TraitObjectSyntax), /// An `impl Bound1 + Bound2 + Bound3` type /// where `Bound` is a trait or a lifetime. ImplTrait(TyParamBounds), @@ -1438,6 +1439,13 @@ pub enum TyKind { Err, } +/// Syntax used to declare a trait object. +#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum TraitObjectSyntax { + Dyn, + None, +} + /// Inline assembly dialect. /// /// E.g. `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`` @@ -1780,10 +1788,19 @@ impl PolyTraitRef { } } +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum CrateSugar { + /// Source is `pub(crate)` + PubCrate, + + /// Source is (just) `crate` + JustCrate, +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum Visibility { Public, - Crate(Span), + Crate(Span, CrateSugar), Restricted { path: P<Path>, id: NodeId }, Inherited, } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index efaa5e5e3da..dd46903bb88 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -471,6 +471,17 @@ impl CodeMap { } } + /// Given a `Span`, try to get a shorter span ending just after the first + /// occurrence of `char` `c`. + pub fn span_through_char(&self, sp: Span, c: char) -> Span { + if let Ok(snippet) = self.span_to_snippet(sp) { + if let Some(offset) = snippet.find(c) { + return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32)); + } + } + sp + } + pub fn def_span(&self, sp: Span) -> Span { self.span_until_char(sp, '{') } diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 4fc2b92d3cd..2f5b386346b 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -32,6 +32,7 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { let ident = keywords::Invalid.ident(); let attrs = Vec::new(); + let generics = ast::Generics::default(); let vis = ast::Visibility::Inherited; let span = DUMMY_SP; let expr_placeholder = || P(ast::Expr { @@ -49,12 +50,12 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { tokens: None, }))), ExpansionKind::TraitItems => Expansion::TraitItems(SmallVector::one(ast::TraitItem { - id, span, ident, attrs, + id, span, ident, attrs, generics, node: ast::TraitItemKind::Macro(mac_placeholder()), tokens: None, })), ExpansionKind::ImplItems => Expansion::ImplItems(SmallVector::one(ast::ImplItem { - id, span, ident, vis, attrs, + id, span, ident, vis, attrs, generics, node: ast::ImplItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a2f29181a20..02aba8a3612 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -398,6 +398,12 @@ declare_features! ( // Default match binding modes (RFC 2005) (active, match_default_bindings, "1.22.0", Some(42640)), + + // Trait object syntax with `dyn` prefix + (active, dyn_trait, "1.22.0", Some(44662)), + + // `crate` as visibility modifier, synonymous to `pub(crate)` + (active, crate_visibility_modifier, "1.23.0", Some(45388)), ); declare_features! ( @@ -1417,6 +1423,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, never_type, ty.span, "The `!` type is experimental"); }, + ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => { + gate_feature_post!(&self, dyn_trait, ty.span, + "`dyn Trait` syntax is unstable"); + } _ => {} } visit::walk_ty(self, ty) @@ -1519,7 +1529,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { span: Span, _node_id: NodeId) { // check for const fn declarations - if let FnKind::ItemFn(_, _, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) = + if let FnKind::ItemFn(_, _, Spanned { node: ast::Constness::Const, .. }, _, _, _) = fn_kind { gate_feature_post!(&self, const_fn, span, "const fn is unstable"); } @@ -1529,7 +1539,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { // point. match fn_kind { - FnKind::ItemFn(_, _, _, _, abi, _, _) | + FnKind::ItemFn(_, _, _, abi, _, _) | FnKind::Method(_, &ast::MethodSig { abi, .. }, _, _) => { self.check_abi(abi, span); } @@ -1575,6 +1585,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_impl_item(self, ii); } + fn visit_vis(&mut self, vis: &'a ast::Visibility) { + if let ast::Visibility::Crate(span, ast::CrateSugar::JustCrate) = *vis { + gate_feature_post!(&self, crate_visibility_modifier, span, + "`crate` visibility modifier is experimental"); + } + visit::walk_vis(self, vis); + } + fn visit_generics(&mut self, g: &'a ast::Generics) { for t in &g.ty_params { if !t.attrs.is_empty() { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 03c47b71d02..518386a2ad2 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -400,8 +400,8 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { TyKind::Typeof(expr) => { TyKind::Typeof(fld.fold_expr(expr)) } - TyKind::TraitObject(bounds) => { - TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b))) + TyKind::TraitObject(bounds, syntax) => { + TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax) } TyKind::ImplTrait(bounds) => { TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b))) @@ -943,6 +943,7 @@ pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T) id: folder.new_id(i.id), ident: folder.fold_ident(i.ident), attrs: fold_attrs(i.attrs, folder), + generics: folder.fold_generics(i.generics), node: match i.node { TraitItemKind::Const(ty, default) => { TraitItemKind::Const(folder.fold_ty(ty), @@ -972,6 +973,7 @@ pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T) vis: folder.fold_vis(i.vis), ident: folder.fold_ident(i.ident), attrs: fold_attrs(i.attrs, folder), + generics: folder.fold_generics(i.generics), defaultness: i.defaultness, node: match i.node { ast::ImplItemKind::Const(ty, expr) => { @@ -1074,7 +1076,6 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: ForeignItem, folder: &mut T) -> For pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> MethodSig { MethodSig { - generics: folder.fold_generics(sig.generics), abi: sig.abi, unsafety: sig.unsafety, constness: sig.constness, diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index 39b5482a066..35afe8dd56d 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -144,7 +144,7 @@ const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[ ('‵', "Reversed Prime", '\''), ('՚', "Armenian Apostrophe", '\''), ('׳', "Hebrew Punctuation Geresh", '\''), - ('`', "Greek Accent", '\''), + ('`', "Grave Accent", '\''), ('`', "Greek Varia", '\''), ('`', "Fullwidth Grave Accent", '\''), ('´', "Acute Accent", '\''), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 65dabe98a06..a2c431dc8b1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -33,10 +33,10 @@ use ast::{Stmt, StmtKind}; use ast::{VariantData, StructField}; use ast::StrStyle; use ast::SelfKind; -use ast::{TraitItem, TraitRef}; +use ast::{TraitItem, TraitRef, TraitObjectSyntax}; use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; -use ast::{Visibility, WhereClause}; +use ast::{Visibility, WhereClause, CrateSugar}; use ast::{BinOpKind, UnOp}; use ast::{RangeEnd, RangeSyntax}; use {ast, attr}; @@ -364,6 +364,13 @@ fn is_ident_or_underscore(t: &token::Token) -> bool { t.is_ident() || *t == token::Underscore } +// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`, +// `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`. +fn can_continue_type_after_ident(t: &token::Token) -> bool { + t == &token::ModSep || t == &token::Lt || + t == &token::BinOp(token::Shl) || t == &token::OpenDelim(token::Paren) +} + /// Information about the path to a module. pub struct ModulePath { pub name: String, @@ -1280,10 +1287,10 @@ impl<'a> Parser<'a> { mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> { let lo = self.span; - let (name, node) = if self.eat_keyword(keywords::Type) { + let (name, node, generics) = if self.eat_keyword(keywords::Type) { let TyParam {ident, bounds, default, ..} = self.parse_ty_param(vec![])?; self.expect(&token::Semi)?; - (ident, TraitItemKind::Type(bounds, default)) + (ident, TraitItemKind::Type(bounds, default), ast::Generics::default()) } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let ident = self.parse_ident()?; @@ -1298,7 +1305,7 @@ impl<'a> Parser<'a> { self.expect(&token::Semi)?; None }; - (ident, TraitItemKind::Const(ty, default)) + (ident, TraitItemKind::Const(ty, default), ast::Generics::default()) } else if self.token.is_path_start() { // trait item macro. // code copied from parse_macro_use_or_failure... abstraction! @@ -1321,7 +1328,7 @@ impl<'a> Parser<'a> { } let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts }); - (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac)) + (keywords::Invalid.ident(), ast::TraitItemKind::Macro(mac), ast::Generics::default()) } else { let (constness, unsafety, abi) = self.parse_fn_front_matter()?; @@ -1334,13 +1341,12 @@ impl<'a> Parser<'a> { // definition... p.parse_arg_general(false) })?; - generics.where_clause = self.parse_where_clause()?; + let sig = ast::MethodSig { unsafety, constness, decl: d, - generics, abi, }; @@ -1363,13 +1369,14 @@ impl<'a> Parser<'a> { return Err(self.fatal(&format!("expected `;` or `{{`, found `{}`", token_str))); } }; - (ident, ast::TraitItemKind::Method(sig, body)) + (ident, ast::TraitItemKind::Method(sig, body), generics) }; Ok(TraitItem { id: ast::DUMMY_NODE_ID, ident: name, attrs, + generics, node, span: lo.to(self.prev_span), tokens: None, @@ -1428,7 +1435,7 @@ impl<'a> Parser<'a> { TyKind::Path(None, ref path) if maybe_bounds => { self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)? } - TyKind::TraitObject(ref bounds) + TyKind::TraitObject(ref bounds, TraitObjectSyntax::None) if maybe_bounds && bounds.len() == 1 && !trailing_plus => { let path = match bounds[0] { TraitTyParamBound(ref pt, ..) => pt.trait_ref.path.clone(), @@ -1472,27 +1479,6 @@ impl<'a> Parser<'a> { } else if self.eat(&token::Underscore) { // A type to be inferred `_` TyKind::Infer - } else if self.eat_lt() { - // Qualified path - let (qself, path) = self.parse_qpath(PathStyle::Type)?; - TyKind::Path(Some(qself), path) - } else if self.token.is_path_start() { - // Simple path - let path = self.parse_path(PathStyle::Type)?; - if self.eat(&token::Not) { - // Macro invocation in type position - let (_, tts) = self.expect_delimited_token_tree()?; - TyKind::Mac(respan(lo.to(self.span), Mac_ { path: path, tts: tts })) - } else { - // Just a type path or bound list (trait object type) starting with a trait. - // `Type` - // `Trait1 + Trait2 + 'a` - if allow_plus && self.check(&token::BinOp(token::Plus)) { - self.parse_remaining_bounds(Vec::new(), path, lo, true)? - } else { - TyKind::Path(None, path) - } - } } else if self.token_is_bare_fn_keyword() { // Function pointer type self.parse_ty_bare_fn(Vec::new())? @@ -1512,10 +1498,37 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(keywords::Impl) { // FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511). TyKind::ImplTrait(self.parse_ty_param_bounds()?) + } else if self.check_keyword(keywords::Dyn) && + self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_ident(t)) { + // FIXME: figure out priority of `+` in `dyn Trait1 + Trait2` (#34511). + self.bump(); // `dyn` + TyKind::TraitObject(self.parse_ty_param_bounds()?, TraitObjectSyntax::Dyn) } else if self.check(&token::Question) || - self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)){ + self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)) { // Bound list (trait object type) - TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?) + TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?, + TraitObjectSyntax::None) + } else if self.eat_lt() { + // Qualified path + let (qself, path) = self.parse_qpath(PathStyle::Type)?; + TyKind::Path(Some(qself), path) + } else if self.token.is_path_start() { + // Simple path + let path = self.parse_path(PathStyle::Type)?; + if self.eat(&token::Not) { + // Macro invocation in type position + let (_, tts) = self.expect_delimited_token_tree()?; + TyKind::Mac(respan(lo.to(self.span), Mac_ { path: path, tts: tts })) + } else { + // Just a type path or bound list (trait object type) starting with a trait. + // `Type` + // `Trait1 + Trait2 + 'a` + if allow_plus && self.check(&token::BinOp(token::Plus)) { + self.parse_remaining_bounds(Vec::new(), path, lo, true)? + } else { + TyKind::Path(None, path) + } + } } else { let msg = format!("expected type, found {}", self.this_token_descr()); return Err(self.fatal(&msg)); @@ -1538,7 +1551,7 @@ impl<'a> Parser<'a> { self.bump(); // `+` bounds.append(&mut self.parse_ty_param_bounds()?); } - Ok(TyKind::TraitObject(bounds)) + Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PResult<'a, ()> { @@ -2314,6 +2327,7 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Brace) { if self.eat(&token::DotDot) { + let exp_span = self.prev_span; match self.parse_expr() { Ok(e) => { base = Some(e); @@ -2323,6 +2337,16 @@ impl<'a> Parser<'a> { self.recover_stmt(); } } + if self.token == token::Comma { + let mut err = self.sess.span_diagnostic.mut_span_err( + exp_span.to(self.prev_span), + "cannot use a comma after the base struct", + ); + err.span_suggestion_short(self.span, "remove this comma", "".to_owned()); + err.note("the base struct must always be the last field"); + err.emit(); + self.recover_stmt(); + } break; } @@ -2890,17 +2914,30 @@ impl<'a> Parser<'a> { match self.parse_path(PathStyle::Expr) { Ok(path) => { + let (op_noun, op_verb) = match self.token { + token::Lt => ("comparison", "comparing"), + token::BinOp(token::Shl) => ("shift", "shifting"), + _ => { + // We can end up here even without `<` being the next token, for + // example because `parse_ty_no_plus` returns `Err` on keywords, + // but `parse_path` returns `Ok` on them due to error recovery. + // Return original error and parser state. + mem::replace(self, parser_snapshot_after_type); + return Err(type_err); + } + }; + // Successfully parsed the type path leaving a `<` yet to parse. type_err.cancel(); // Report non-fatal diagnostics, keep `x as usize` as an expression // in AST and continue parsing. let msg = format!("`<` is interpreted as a start of generic \ - arguments for `{}`, not a comparison", path); + arguments for `{}`, not a {}", path, op_noun); let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg); err.span_label(self.look_ahead_span(1).to(parser_snapshot_after_type.span), "interpreted as generic arguments"); - err.span_label(self.span, "not interpreted as comparison"); + err.span_label(self.span, format!("not interpreted as {}", op_noun)); let expr = mk_expr(self, P(Ty { span: path.span, @@ -2911,7 +2948,7 @@ impl<'a> Parser<'a> { let expr_str = self.sess.codemap().span_to_snippet(expr.span) .unwrap_or(pprust::expr_to_string(&expr)); err.span_suggestion(expr.span, - "try comparing the casted value", + &format!("try {} the casted value", op_verb), format!("({})", expr_str)); err.emit(); @@ -2947,6 +2984,7 @@ impl<'a> Parser<'a> { { // Foo<Bar<Baz<Qux, ()>>> err.help( "use `::<...>` instead of `<...>` if you meant to specify type arguments"); + err.help("or use `(...)` if you meant to specify fn arguments"); } err.emit(); } @@ -3671,12 +3709,17 @@ impl<'a> Parser<'a> { None }; let init = self.parse_initializer()?; + let hi = if self.token == token::Semi { + self.span + } else { + self.prev_span + }; Ok(P(ast::Local { ty, pat, init, id: ast::DUMMY_NODE_ID, - span: lo.to(self.prev_span), + span: lo.to(hi), attrs, })) } @@ -4045,11 +4088,11 @@ impl<'a> Parser<'a> { node: StmtKind::Item(i), }, None => { - let unused_attrs = |attrs: &[_], s: &mut Self| { + let unused_attrs = |attrs: &[Attribute], s: &mut Self| { if !attrs.is_empty() { if s.prev_token_kind == PrevTokenKind::DocComment { s.span_fatal_err(s.prev_span, Error::UselessDocComment).emit(); - } else { + } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) { s.span_err(s.span, "expected statement after outer attribute"); } } @@ -4226,6 +4269,7 @@ impl<'a> Parser<'a> { fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> { let mut bounds = Vec::new(); loop { + // This needs to be syncronized with `Token::can_begin_bound`. let is_bound_start = self.check_path() || self.check_lifetime() || self.check(&token::Question) || self.check_keyword(keywords::For) || @@ -4857,12 +4901,12 @@ impl<'a> Parser<'a> { let lo = self.span; let vis = self.parse_visibility(false)?; let defaultness = self.parse_defaultness()?; - let (name, node) = if self.eat_keyword(keywords::Type) { + let (name, node, generics) = if self.eat_keyword(keywords::Type) { let name = self.parse_ident()?; self.expect(&token::Eq)?; let typ = self.parse_ty()?; self.expect(&token::Semi)?; - (name, ast::ImplItemKind::Type(typ)) + (name, ast::ImplItemKind::Type(typ), ast::Generics::default()) } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let name = self.parse_ident()?; @@ -4871,11 +4915,11 @@ impl<'a> Parser<'a> { self.expect(&token::Eq)?; let expr = self.parse_expr()?; self.expect(&token::Semi)?; - (name, ast::ImplItemKind::Const(typ, expr)) + (name, ast::ImplItemKind::Const(typ, expr), ast::Generics::default()) } else { - let (name, inner_attrs, node) = self.parse_impl_method(&vis, at_end)?; + let (name, inner_attrs, generics, node) = self.parse_impl_method(&vis, at_end)?; attrs.extend(inner_attrs); - (name, node) + (name, node, generics) }; Ok(ImplItem { @@ -4885,6 +4929,7 @@ impl<'a> Parser<'a> { vis, defaultness, attrs, + generics, node, tokens: None, }) @@ -4942,7 +4987,8 @@ impl<'a> Parser<'a> { /// Parse a method or a macro invocation in a trait impl. fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool) - -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> { + -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::Generics, + ast::ImplItemKind)> { // code copied from parse_macro_use_or_failure... abstraction! if self.token.is_path_start() { // Method macro. @@ -4969,7 +5015,8 @@ impl<'a> Parser<'a> { } let mac = respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts }); - Ok((keywords::Invalid.ident(), vec![], ast::ImplItemKind::Macro(mac))) + Ok((keywords::Invalid.ident(), vec![], ast::Generics::default(), + ast::ImplItemKind::Macro(mac))) } else { let (constness, unsafety, abi) = self.parse_fn_front_matter()?; let ident = self.parse_ident()?; @@ -4978,8 +5025,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - Ok((ident, inner_attrs, ast::ImplItemKind::Method(ast::MethodSig { - generics, + Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(ast::MethodSig { abi, unsafety, constness, @@ -5281,6 +5327,10 @@ impl<'a> Parser<'a> { pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { maybe_whole!(self, NtVis, |x| x); + if self.eat_keyword(keywords::Crate) { + return Ok(Visibility::Crate(self.prev_span, CrateSugar::JustCrate)); + } + if !self.eat_keyword(keywords::Pub) { return Ok(Visibility::Inherited) } @@ -5294,7 +5344,7 @@ impl<'a> Parser<'a> { // `pub(crate)` self.bump(); // `(` self.bump(); // `crate` - let vis = Visibility::Crate(self.prev_span); + let vis = Visibility::Crate(self.prev_span, CrateSugar::PubCrate); self.expect(&token::CloseDelim(token::Paren))?; // `)` return Ok(vis) } else if self.look_ahead(1, |t| t.is_keyword(keywords::In)) { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 4888654fac9..20db87cfc82 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -258,6 +258,12 @@ impl Token { } } + /// Returns `true` if the token can appear at the start of a generic bound. + pub fn can_begin_bound(&self) -> bool { + self.is_path_start() || self.is_lifetime() || self.is_keyword(keywords::For) || + self == &Question || self == &OpenDelim(Paren) + } + /// Returns `true` if the token is any literal pub fn is_lit(&self) -> bool { match *self { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 959dd4ef30f..656a51c6637 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1049,8 +1049,9 @@ impl<'a> State<'a> { ast::TyKind::Path(Some(ref qself), ref path) => { self.print_qpath(path, qself, false)? } - ast::TyKind::TraitObject(ref bounds) => { - self.print_bounds("", &bounds[..])?; + ast::TyKind::TraitObject(ref bounds, syntax) => { + let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn " } else { "" }; + self.print_bounds(prefix, &bounds[..])?; } ast::TyKind::ImplTrait(ref bounds) => { self.print_bounds("impl ", &bounds[..])?; @@ -1439,7 +1440,10 @@ impl<'a> State<'a> { pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> { match *vis { ast::Visibility::Public => self.word_nbsp("pub"), - ast::Visibility::Crate(_) => self.word_nbsp("pub(crate)"), + ast::Visibility::Crate(_, sugar) => match sugar { + ast::CrateSugar::PubCrate => self.word_nbsp("pub(crate)"), + ast::CrateSugar::JustCrate => self.word_nbsp("crate") + } ast::Visibility::Restricted { ref path, .. } => { let path = to_string(|s| s.print_path(path, false, 0, true)); if path == "self" || path == "super" { @@ -1524,6 +1528,7 @@ impl<'a> State<'a> { pub fn print_method_sig(&mut self, ident: ast::Ident, + generics: &ast::Generics, m: &ast::MethodSig, vis: &ast::Visibility) -> io::Result<()> { @@ -1532,7 +1537,7 @@ impl<'a> State<'a> { m.constness.node, m.abi, Some(ident), - &m.generics, + &generics, vis) } @@ -1552,7 +1557,7 @@ impl<'a> State<'a> { if body.is_some() { self.head("")?; } - self.print_method_sig(ti.ident, sig, &ast::Visibility::Inherited)?; + self.print_method_sig(ti.ident, &ti.generics, sig, &ast::Visibility::Inherited)?; if let Some(ref body) = *body { self.nbsp()?; self.print_block_with_attrs(body, &ti.attrs)?; @@ -1591,7 +1596,7 @@ impl<'a> State<'a> { } ast::ImplItemKind::Method(ref sig, ref body) => { self.head("")?; - self.print_method_sig(ii.ident, sig, &ii.vis)?; + self.print_method_sig(ii.ident, &ii.generics, sig, &ii.vis)?; self.nbsp()?; self.print_block_with_attrs(body, &ii.attrs)?; } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 05077d42a0b..078a63cba20 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -31,7 +31,7 @@ use codemap::Spanned; #[derive(Copy, Clone, PartialEq, Eq)] pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() - ItemFn(Ident, &'a Generics, Unsafety, Spanned<Constness>, Abi, &'a Visibility, &'a Block), + ItemFn(Ident, Unsafety, Spanned<Constness>, Abi, &'a Visibility, &'a Block), /// fn foo(&self) Method(Ident, &'a MethodSig, Option<&'a Visibility>, &'a Block), @@ -247,7 +247,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_expr(expr); } ItemKind::Fn(ref declaration, unsafety, constness, abi, ref generics, ref body) => { - visitor.visit_fn(FnKind::ItemFn(item.ident, generics, unsafety, + visitor.visit_generics(generics); + visitor.visit_fn(FnKind::ItemFn(item.ident, unsafety, constness, abi, &item.vis, body), declaration, item.span, @@ -348,7 +349,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { visitor.visit_ty(ty); visitor.visit_expr(expression) } - TyKind::TraitObject(ref bounds) | + TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(ref bounds) => { walk_list!(visitor, visit_ty_param_bound, bounds); } @@ -538,13 +539,11 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl where V: Visitor<'a>, { match kind { - FnKind::ItemFn(_, generics, _, _, _, _, body) => { - visitor.visit_generics(generics); + FnKind::ItemFn(_, _, _, _, _, body) => { walk_fn_decl(visitor, declaration); visitor.visit_block(body); } - FnKind::Method(_, sig, _, body) => { - visitor.visit_generics(&sig.generics); + FnKind::Method(_, _, _, body) => { walk_fn_decl(visitor, declaration); visitor.visit_block(body); } @@ -558,13 +557,13 @@ pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a TraitItem) { visitor.visit_ident(trait_item.span, trait_item.ident); walk_list!(visitor, visit_attribute, &trait_item.attrs); + visitor.visit_generics(&trait_item.generics); match trait_item.node { TraitItemKind::Const(ref ty, ref default) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, default); } TraitItemKind::Method(ref sig, None) => { - visitor.visit_generics(&sig.generics); walk_fn_decl(visitor, &sig.decl); } TraitItemKind::Method(ref sig, Some(ref body)) => { @@ -585,6 +584,7 @@ pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, impl_item: &'a ImplIt visitor.visit_vis(&impl_item.vis); visitor.visit_ident(impl_item.span, impl_item.ident); walk_list!(visitor, visit_attribute, &impl_item.attrs); + visitor.visit_generics(&impl_item.generics); match impl_item.node { ImplItemKind::Const(ref ty, ref expr) => { visitor.visit_ty(ty); |
