about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-08-10 06:14:13 +0000
committerbors <bors@rust-lang.org>2019-08-10 06:14:13 +0000
commitd19a359444295bab01de7ff44a9d72302e573bc9 (patch)
treec3765064c4bae63df68e165a6ca406e6a2eedd85 /src/libsyntax
parentbe8bbb06976c8065425b18e9cbe24a6d1d4e7515 (diff)
parent019f6fed2855ff67adcf74176c16817c279e89de (diff)
downloadrust-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.rs15
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs40
-rw-r--r--src/libsyntax/parse/parser.rs70
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())
     }