about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2019-03-13 17:10:27 +0100
committerDavid Wood <david@davidtw.co>2019-04-21 16:46:32 +0100
commit9d7da824d6a691d58d486e22cc789c572e3d0bf0 (patch)
treeefd08de2dcfbfbf790fd4f3beb989c7d7eba7da7
parent92e72df2c1402d3d8fceac81e650b633c555a523 (diff)
downloadrust-9d7da824d6a691d58d486e22cc789c572e3d0bf0.tar.gz
rust-9d7da824d6a691d58d486e22cc789c572e3d0bf0.zip
Introduce `ArgSource` for diagnostics.
This commit introduces an `ArgSource` enum that is lowered into the HIR
so that diagnostics can correctly refer to the argument pattern's
original name rather than the generated pattern.
-rw-r--r--src/librustc/hir/intravisit.rs10
-rw-r--r--src/librustc/hir/lowering.rs9
-rw-r--r--src/librustc/hir/mod.rs20
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs15
-rw-r--r--src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs9
-rw-r--r--src/librustc/lint/context.rs3
-rw-r--r--src/librustc/middle/resolve_lifetime.rs2
-rw-r--r--src/librustc_privacy/lib.rs20
-rw-r--r--src/librustc_typeck/check/mod.rs10
-rw-r--r--src/librustc_typeck/check/writeback.rs10
-rw-r--r--src/libsyntax/ast.rs11
-rw-r--r--src/libsyntax/ext/build.rs3
-rw-r--r--src/libsyntax/mut_visit.rs14
-rw-r--r--src/libsyntax/parse/parser.rs10
-rw-r--r--src/libsyntax/visit.rs3
15 files changed, 128 insertions, 21 deletions
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index b653093c1f8..a0c9e5983a1 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -262,6 +262,9 @@ pub trait Visitor<'v> : Sized {
     fn visit_pat(&mut self, p: &'v Pat) {
         walk_pat(self, p)
     }
+    fn visit_argument_source(&mut self, s: &'v ArgSource) {
+        walk_argument_source(self, s)
+    }
     fn visit_anon_const(&mut self, c: &'v AnonConst) {
         walk_anon_const(self, c)
     }
@@ -399,10 +402,17 @@ pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
     for argument in &body.arguments {
         visitor.visit_id(argument.hir_id);
         visitor.visit_pat(&argument.pat);
+        visitor.visit_argument_source(&argument.source);
     }
     visitor.visit_expr(&body.value);
 }
 
+pub fn walk_argument_source<'v, V: Visitor<'v>>(visitor: &mut V, source: &'v ArgSource) {
+    if let ArgSource::AsyncFn(pat) = source {
+        visitor.visit_pat(pat);
+    }
+}
+
 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
     // Intentionally visiting the expr first - the initialization expr
     // dominates the local's definition.
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 5afac999fc0..28899af629b 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -465,6 +465,7 @@ impl<'a> LoweringContext<'a> {
                     // Don't visit the original pattern for async functions as it will be
                     // replaced.
                     for arg in &fd.inputs {
+                        if let ArgSource::AsyncFn(pat) = &arg.source { self.visit_pat(pat); }
                         self.visit_ty(&arg.ty)
                     }
                     self.visit_fn_ret_ty(&fd.output);
@@ -2271,6 +2272,14 @@ impl<'a> LoweringContext<'a> {
         hir::Arg {
             hir_id,
             pat: self.lower_pat(&arg.pat),
+            source: self.lower_arg_source(&arg.source),
+        }
+    }
+
+    fn lower_arg_source(&mut self, source: &ArgSource) -> hir::ArgSource {
+        match source {
+            ArgSource::Normal => hir::ArgSource::Normal,
+            ArgSource::AsyncFn(pat) => hir::ArgSource::AsyncFn(self.lower_pat(pat)),
         }
     }
 
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index e873663a613..1ebaa60fc88 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1894,6 +1894,26 @@ pub struct InlineAsm {
 pub struct Arg {
     pub pat: P<Pat>,
     pub hir_id: HirId,
+    pub source: ArgSource,
+}
+
+impl Arg {
+    /// Returns the pattern representing the original binding for this argument.
+    pub fn original_pat(&self) -> &P<Pat> {
+        match &self.source {
+            ArgSource::Normal => &self.pat,
+            ArgSource::AsyncFn(pat) => &pat,
+        }
+    }
+}
+
+/// Represents the source of an argument in a function header.
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
+pub enum ArgSource {
+    /// Argument as specified by the user.
+    Normal,
+    /// Generated argument from `async fn` lowering, contains the original binding pattern.
+    AsyncFn(P<Pat>),
 }
 
 /// Represents the header (not the body) of a function declaration.
diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
index 86d7a19bc83..944cc8a8b19 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -86,19 +86,16 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
         let sub_is_ret_type =
             self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
 
-        let span_label_var1 = if let Some(simple_ident) = anon_arg_sup.pat.simple_ident() {
-            format!(" from `{}`", simple_ident)
-        } else {
-            String::new()
+        let span_label_var1 = match anon_arg_sup.original_pat().simple_ident() {
+            Some(simple_ident) => format!(" from `{}`", simple_ident),
+            None => String::new(),
         };
 
-        let span_label_var2 = if let Some(simple_ident) = anon_arg_sub.pat.simple_ident() {
-            format!(" into `{}`", simple_ident)
-        } else {
-            String::new()
+        let span_label_var2 = match anon_arg_sub.original_pat().simple_ident() {
+            Some(simple_ident) => format!(" into `{}`", simple_ident),
+            None => String::new(),
         };
 
-
         let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
             (None, None) => {
                 let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {
diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index 7403a5d7dbb..2d7587b11b6 100644
--- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -95,13 +95,12 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
             }
         }
 
-        let (error_var, span_label_var) = if let Some(simple_ident) = arg.pat.simple_ident() {
-            (
+        let (error_var, span_label_var) = match arg.original_pat().simple_ident() {
+            Some(simple_ident) => (
                 format!("the type of `{}`", simple_ident),
                 format!("the type of `{}`", simple_ident),
-            )
-        } else {
-            ("parameter type".to_owned(), "type".to_owned())
+            ),
+            None => ("parameter type".to_owned(), "type".to_owned()),
         };
 
         let mut diag = struct_span_err!(
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 709e5c4cce4..d7f97f7a58e 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -1337,6 +1337,9 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
             for a in arguments {
                 // Visit the argument..
                 self.visit_pat(&a.arg.pat);
+                if let ast::ArgSource::AsyncFn(pat) = &a.arg.source {
+                    self.visit_pat(pat);
+                }
                 self.visit_ty(&a.arg.ty);
 
                 // ..and the statement.
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 3306bcae212..814776c21bd 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -2421,7 +2421,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
 
             let help_name = if let Some(body) = parent {
                 let arg = &self.tcx.hir().body(body).arguments[index];
-                format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.pat.hir_id))
+                format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.original_pat().hir_id))
             } else {
                 format!("argument {}", index + 1)
             };
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index edb3efb78a3..57e17eb6878 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -948,6 +948,16 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
 
         intravisit::walk_pat(self, pat);
     }
+
+    fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) {
+        match s {
+            // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
+            // a `NodeId` w/out a type, as it is only used for getting the name of the original
+            // pattern for diagnostics where only an `hir::Arg` is present.
+            hir::ArgSource::AsyncFn(..) => {},
+            _ => intravisit::walk_argument_source(self, s),
+        }
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////
@@ -1133,6 +1143,16 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
         intravisit::walk_pat(self, pattern);
     }
 
+    fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) {
+        match s {
+            // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
+            // a `NodeId` w/out a type, as it is only used for getting the name of the original
+            // pattern for diagnostics where only an `hir::Arg` is present.
+            hir::ArgSource::AsyncFn(..) => {},
+            _ => intravisit::walk_argument_source(self, s),
+        }
+    }
+
     fn visit_local(&mut self, local: &'tcx hir::Local) {
         if let Some(ref init) = local.init {
             if self.check_expr_pat_type(init.hir_id, init.span) {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 15190f56965..79477b6fea8 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1005,6 +1005,16 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
     // Don't descend into the bodies of nested closures
     fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
                 _: hir::BodyId, _: Span, _: hir::HirId) { }
+
+    fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
+        match s {
+            // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
+            // a `NodeId` w/out a type, as it is only used for getting the name of the original
+            // pattern for diagnostics where only an `hir::Arg` is present.
+            hir::ArgSource::AsyncFn(..) => {},
+            _ => intravisit::walk_argument_source(self, s),
+        }
+    }
 }
 
 /// When `check_fn` is invoked on a generator (i.e., a body that
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index d9df4672f14..efff08f6696 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -297,6 +297,16 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
         let ty = self.resolve(&ty, &hir_ty.span);
         self.write_ty_to_tables(hir_ty.hir_id, ty);
     }
+
+    fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
+        match s {
+            // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
+            // a `NodeId` w/out a type, as it is only used for getting the name of the original
+            // pattern for diagnostics where only an `hir::Arg` is present.
+            hir::ArgSource::AsyncFn(..) => {},
+            _ => intravisit::walk_argument_source(self, s),
+        }
+    }
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index e6669e0d6ed..81d8cfd8622 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1736,6 +1736,16 @@ pub struct Arg {
     pub ty: P<Ty>,
     pub pat: P<Pat>,
     pub id: NodeId,
+    pub source: ArgSource,
+}
+
+/// The source of an argument in a function header.
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum ArgSource {
+    /// Argument as written by the user.
+    Normal,
+    /// Argument from `async fn` lowering, contains the original binding pattern.
+    AsyncFn(P<Pat>),
 }
 
 /// Alternative representation for `Arg`s describing `self` parameter of methods.
@@ -1795,6 +1805,7 @@ impl Arg {
             }),
             ty,
             id: DUMMY_NODE_ID,
+            source: ArgSource::Normal,
         };
         match eself.node {
             SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 029c45eaa72..40dd187ed28 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -979,7 +979,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         ast::Arg {
             ty,
             pat: arg_pat,
-            id: ast::DUMMY_NODE_ID
+            id: ast::DUMMY_NODE_ID,
+            source: ast::ArgSource::Normal,
         }
     }
 
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index bb9116e678e..d3441a2039b 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -235,6 +235,10 @@ pub trait MutVisitor: Sized {
         noop_visit_arg(a, self);
     }
 
+    fn visit_arg_source(&mut self, a: &mut ArgSource) {
+        noop_visit_arg_source(a, self);
+    }
+
     fn visit_generics(&mut self, generics: &mut Generics) {
         noop_visit_generics(generics, self);
     }
@@ -564,10 +568,18 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty }: &mut Arg, vis: &mut T) {
+pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty, source }: &mut Arg, vis: &mut T) {
     vis.visit_id(id);
     vis.visit_pat(pat);
     vis.visit_ty(ty);
+    vis.visit_arg_source(source);
+}
+
+pub fn noop_visit_arg_source<T: MutVisitor>(source: &mut ArgSource, vis: &mut T) {
+    match source {
+        ArgSource::Normal => {},
+        ArgSource::AsyncFn(pat) => vis.visit_pat(pat),
+    }
 }
 
 pub fn noop_visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 172d5c38c77..d7330ff55ad 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1,7 +1,7 @@
 use crate::ast::{AngleBracketedArgs, AsyncArgument, ParenthesizedArgs, AttrStyle, BareFnTy};
 use crate::ast::{GenericBound, TraitBoundModifier};
 use crate::ast::Unsafety;
-use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
+use crate::ast::{Mod, AnonConst, Arg, ArgSource, Arm, Guard, Attribute, BindingMode, TraitItemKind};
 use crate::ast::Block;
 use crate::ast::{BlockCheckMode, CaptureBy, Movability};
 use crate::ast::{Constness, Crate};
@@ -550,7 +550,7 @@ fn dummy_arg(span: Span) -> Arg {
         span,
         id: ast::DUMMY_NODE_ID
     };
-    Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
+    Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal }
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -2126,7 +2126,7 @@ impl<'a> Parser<'a> {
             }
         };
 
-        Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID })
+        Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal })
     }
 
     /// Parses a single function argument.
@@ -2149,7 +2149,8 @@ impl<'a> Parser<'a> {
         Ok(Arg {
             ty: t,
             pat,
-            id: ast::DUMMY_NODE_ID
+            id: ast::DUMMY_NODE_ID,
+            source: ast::ArgSource::Normal,
         })
     }
 
@@ -8856,6 +8857,7 @@ impl<'a> Parser<'a> {
                         ),
                         span,
                     }),
+                    source: ArgSource::AsyncFn(input.pat.clone()),
                 };
 
                 // Construct a `let <pat> = __argN;` statement to insert at the top of the
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index fe74cbd6496..fc99d10b0b6 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -544,6 +544,9 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR
 pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
     for argument in &function_declaration.inputs {
         visitor.visit_pat(&argument.pat);
+        if let ArgSource::AsyncFn(pat) = &argument.source {
+            visitor.visit_pat(pat);
+        }
         visitor.visit_ty(&argument.ty)
     }
     visitor.visit_fn_ret_ty(&function_declaration.output)