diff options
| author | bors <bors@rust-lang.org> | 2019-08-10 06:14:13 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-08-10 06:14:13 +0000 |
| commit | d19a359444295bab01de7ff44a9d72302e573bc9 (patch) | |
| tree | c3765064c4bae63df68e165a6ca406e6a2eedd85 /src/libsyntax | |
| parent | be8bbb06976c8065425b18e9cbe24a6d1d4e7515 (diff) | |
| parent | 019f6fed2855ff67adcf74176c16817c279e89de (diff) | |
| download | rust-d19a359444295bab01de7ff44a9d72302e573bc9.tar.gz rust-d19a359444295bab01de7ff44a9d72302e573bc9.zip | |
Auto merge of #63428 - Centril:rollup-c2ru1z1, r=Centril
Rollup of 7 pull requests Successful merges: - #63056 (Give built-in macros stable addresses in the standard library) - #63337 (Tweak mismatched types error) - #63350 (Use associated_type_bounds where applicable - closes #61738) - #63394 (Add test for issue 36804) - #63399 (More explicit diagnostic when using a `vec![]` in a pattern) - #63419 (check against more collisions for TypeId of fn pointer) - #63423 (Mention that tuple structs are private if any of their fields are) Failed merges: r? @ghost
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 40 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 70 |
3 files changed, 98 insertions, 27 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 964c81dd466..9a3195b1165 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -6,6 +6,7 @@ use crate::config::StripUnconfigured; use crate::ext::base::*; use crate::ext::proc_macro::collect_derives; use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind}; +use crate::ext::tt::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use crate::mut_visit::*; @@ -686,12 +687,13 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ); } - fn parse_ast_fragment(&mut self, - toks: TokenStream, - kind: AstFragmentKind, - path: &Path, - span: Span) - -> AstFragment { + fn parse_ast_fragment( + &mut self, + toks: TokenStream, + kind: AstFragmentKind, + path: &Path, + span: Span, + ) -> AstFragment { let mut parser = self.cx.new_parser_from_tts(&toks.into_trees().collect::<Vec<_>>()); match parser.parse_ast_fragment(kind, false) { Ok(fragment) => { @@ -700,6 +702,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } Err(mut err) => { err.set_span(span); + annotate_err_with_kind(&mut err, kind, span); err.emit(); self.cx.trace_macros_diag(); kind.dummy(span) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 7401f256412..b057a9ad44d 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -17,7 +17,7 @@ use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; use crate::{ast, attr, attr::TransparencyError}; -use errors::FatalError; +use errors::{DiagnosticBuilder, FatalError}; use log::debug; use syntax_pos::Span; @@ -43,6 +43,18 @@ pub struct ParserAnyMacro<'a> { arm_span: Span, } +pub fn annotate_err_with_kind(err: &mut DiagnosticBuilder<'_>, kind: AstFragmentKind, span: Span) { + match kind { + AstFragmentKind::Ty => { + err.span_label(span, "this macro call doesn't expand to a type"); + } + AstFragmentKind::Pat => { + err.span_label(span, "this macro call doesn't expand to a pattern"); + } + _ => {} + }; +} + impl<'a> ParserAnyMacro<'a> { pub fn make(mut self: Box<ParserAnyMacro<'a>>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; @@ -70,6 +82,32 @@ impl<'a> ParserAnyMacro<'a> { } else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() { e.span_label(site_span, "in this macro invocation"); } + match kind { + AstFragmentKind::Pat if macro_ident.name == sym::vec => { + let mut suggestion = None; + if let Ok(code) = parser.sess.source_map().span_to_snippet(site_span) { + if let Some(bang) = code.find('!') { + suggestion = Some(code[bang + 1..].to_string()); + } + } + if let Some(suggestion) = suggestion { + e.span_suggestion( + site_span, + "use a slice pattern here instead", + suggestion, + Applicability::MachineApplicable, + ); + } else { + e.span_label( + site_span, + "use a slice pattern here instead", + ); + } + e.help("for more information, see https://doc.rust-lang.org/edition-guide/\ + rust-2018/slice-patterns.html"); + } + _ => annotate_err_with_kind(&mut e, kind, site_span), + }; e })); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d85c2df16a3..30e16592113 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2052,9 +2052,23 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Paren) { es.push(match self.parse_expr() { Ok(es) => es, - Err(err) => { + Err(mut err) => { // recover from parse error in tuple list - return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err))); + match self.token.kind { + token::Ident(name, false) + if name == kw::Underscore && self.look_ahead(1, |t| { + t == &token::Comma + }) => { + // Special-case handling of `Foo<(_, _, _)>` + err.emit(); + let sp = self.token.span; + self.bump(); + self.mk_expr(sp, ExprKind::Err, ThinVec::new()) + } + _ => return Ok( + self.recover_seq_parse_error(token::Paren, lo, Err(err)), + ), + } } }); recovered = self.expect_one_of( @@ -2456,9 +2470,10 @@ impl<'a> Parser<'a> { } /// Parses `a.b` or `a(13)` or `a[4]` or just `a`. - fn parse_dot_or_call_expr(&mut self, - already_parsed_attrs: Option<ThinVec<Attribute>>) - -> PResult<'a, P<Expr>> { + fn parse_dot_or_call_expr( + &mut self, + already_parsed_attrs: Option<ThinVec<Attribute>>, + ) -> PResult<'a, P<Expr>> { let attrs = self.parse_or_use_outer_attributes(already_parsed_attrs)?; let b = self.parse_bottom_expr(); @@ -2466,16 +2481,16 @@ impl<'a> Parser<'a> { self.parse_dot_or_call_expr_with(b, span, attrs) } - fn parse_dot_or_call_expr_with(&mut self, - e0: P<Expr>, - lo: Span, - mut attrs: ThinVec<Attribute>) - -> PResult<'a, P<Expr>> { + fn parse_dot_or_call_expr_with( + &mut self, + e0: P<Expr>, + lo: Span, + mut attrs: ThinVec<Attribute>, + ) -> PResult<'a, P<Expr>> { // Stitch the list of outer attributes onto the return value. // A little bit ugly, but the best way given the current code // structure - self.parse_dot_or_call_expr_with_(e0, lo) - .map(|expr| + self.parse_dot_or_call_expr_with_(e0, lo).map(|expr| expr.map(|mut expr| { attrs.extend::<Vec<_>>(expr.attrs.into()); expr.attrs = attrs; @@ -2483,10 +2498,7 @@ impl<'a> Parser<'a> { ExprKind::If(..) if !expr.attrs.is_empty() => { // Just point to the first attribute in there... let span = expr.attrs[0].span; - - self.span_err(span, - "attributes are not yet allowed on `if` \ - expressions"); + self.span_err(span, "attributes are not yet allowed on `if` expressions"); } _ => {} } @@ -2624,7 +2636,24 @@ impl<'a> Parser<'a> { } fn parse_paren_expr_seq(&mut self) -> PResult<'a, Vec<P<Expr>>> { - self.parse_paren_comma_seq(|p| p.parse_expr()).map(|(r, _)| r) + self.parse_paren_comma_seq(|p| { + match p.parse_expr() { + Ok(expr) => Ok(expr), + Err(mut err) => match p.token.kind { + token::Ident(name, false) + if name == kw::Underscore && p.look_ahead(1, |t| { + t == &token::Comma + }) => { + // Special-case handling of `foo(_, _, _)` + err.emit(); + let sp = p.token.span; + p.bump(); + Ok(p.mk_expr(sp, ExprKind::Err, ThinVec::new())) + } + _ => Err(err), + }, + } + }).map(|(r, _)| r) } crate fn process_potential_macro_variable(&mut self) { @@ -2806,9 +2835,10 @@ impl<'a> Parser<'a> { /// This parses an expression accounting for associativity and precedence of the operators in /// the expression. #[inline] - fn parse_assoc_expr(&mut self, - already_parsed_attrs: Option<ThinVec<Attribute>>) - -> PResult<'a, P<Expr>> { + fn parse_assoc_expr( + &mut self, + already_parsed_attrs: Option<ThinVec<Attribute>>, + ) -> PResult<'a, P<Expr>> { self.parse_assoc_expr_with(0, already_parsed_attrs.into()) } |
