diff options
| author | David Wood <david@davidtw.co> | 2019-03-13 17:10:27 +0100 |
|---|---|---|
| committer | David Wood <david@davidtw.co> | 2019-04-21 16:46:32 +0100 |
| commit | 9d7da824d6a691d58d486e22cc789c572e3d0bf0 (patch) | |
| tree | efd08de2dcfbfbf790fd4f3beb989c7d7eba7da7 | |
| parent | 92e72df2c1402d3d8fceac81e650b633c555a523 (diff) | |
| download | rust-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.rs | 10 | ||||
| -rw-r--r-- | src/librustc/hir/lowering.rs | 9 | ||||
| -rw-r--r-- | src/librustc/hir/mod.rs | 20 | ||||
| -rw-r--r-- | src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs | 15 | ||||
| -rw-r--r-- | src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs | 9 | ||||
| -rw-r--r-- | src/librustc/lint/context.rs | 3 | ||||
| -rw-r--r-- | src/librustc/middle/resolve_lifetime.rs | 2 | ||||
| -rw-r--r-- | src/librustc_privacy/lib.rs | 20 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 10 | ||||
| -rw-r--r-- | src/librustc_typeck/check/writeback.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/ast.rs | 11 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/mut_visit.rs | 14 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 3 |
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) |
