Skip to content

Commit 9d7da82

Browse files
committed
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.
1 parent 92e72df commit 9d7da82

File tree

15 files changed

+128
-21
lines changed

15 files changed

+128
-21
lines changed

src/librustc/hir/intravisit.rs

+10
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ pub trait Visitor<'v> : Sized {
262262
fn visit_pat(&mut self, p: &'v Pat) {
263263
walk_pat(self, p)
264264
}
265+
fn visit_argument_source(&mut self, s: &'v ArgSource) {
266+
walk_argument_source(self, s)
267+
}
265268
fn visit_anon_const(&mut self, c: &'v AnonConst) {
266269
walk_anon_const(self, c)
267270
}
@@ -399,10 +402,17 @@ pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
399402
for argument in &body.arguments {
400403
visitor.visit_id(argument.hir_id);
401404
visitor.visit_pat(&argument.pat);
405+
visitor.visit_argument_source(&argument.source);
402406
}
403407
visitor.visit_expr(&body.value);
404408
}
405409

410+
pub fn walk_argument_source<'v, V: Visitor<'v>>(visitor: &mut V, source: &'v ArgSource) {
411+
if let ArgSource::AsyncFn(pat) = source {
412+
visitor.visit_pat(pat);
413+
}
414+
}
415+
406416
pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
407417
// Intentionally visiting the expr first - the initialization expr
408418
// dominates the local's definition.

src/librustc/hir/lowering.rs

+9
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ impl<'a> LoweringContext<'a> {
465465
// Don't visit the original pattern for async functions as it will be
466466
// replaced.
467467
for arg in &fd.inputs {
468+
if let ArgSource::AsyncFn(pat) = &arg.source { self.visit_pat(pat); }
468469
self.visit_ty(&arg.ty)
469470
}
470471
self.visit_fn_ret_ty(&fd.output);
@@ -2271,6 +2272,14 @@ impl<'a> LoweringContext<'a> {
22712272
hir::Arg {
22722273
hir_id,
22732274
pat: self.lower_pat(&arg.pat),
2275+
source: self.lower_arg_source(&arg.source),
2276+
}
2277+
}
2278+
2279+
fn lower_arg_source(&mut self, source: &ArgSource) -> hir::ArgSource {
2280+
match source {
2281+
ArgSource::Normal => hir::ArgSource::Normal,
2282+
ArgSource::AsyncFn(pat) => hir::ArgSource::AsyncFn(self.lower_pat(pat)),
22742283
}
22752284
}
22762285

src/librustc/hir/mod.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1894,6 +1894,26 @@ pub struct InlineAsm {
18941894
pub struct Arg {
18951895
pub pat: P<Pat>,
18961896
pub hir_id: HirId,
1897+
pub source: ArgSource,
1898+
}
1899+
1900+
impl Arg {
1901+
/// Returns the pattern representing the original binding for this argument.
1902+
pub fn original_pat(&self) -> &P<Pat> {
1903+
match &self.source {
1904+
ArgSource::Normal => &self.pat,
1905+
ArgSource::AsyncFn(pat) => &pat,
1906+
}
1907+
}
1908+
}
1909+
1910+
/// Represents the source of an argument in a function header.
1911+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
1912+
pub enum ArgSource {
1913+
/// Argument as specified by the user.
1914+
Normal,
1915+
/// Generated argument from `async fn` lowering, contains the original binding pattern.
1916+
AsyncFn(P<Pat>),
18971917
}
18981918

18991919
/// Represents the header (not the body) of a function declaration.

src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,16 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
8686
let sub_is_ret_type =
8787
self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
8888

89-
let span_label_var1 = if let Some(simple_ident) = anon_arg_sup.pat.simple_ident() {
90-
format!(" from `{}`", simple_ident)
91-
} else {
92-
String::new()
89+
let span_label_var1 = match anon_arg_sup.original_pat().simple_ident() {
90+
Some(simple_ident) => format!(" from `{}`", simple_ident),
91+
None => String::new(),
9392
};
9493

95-
let span_label_var2 = if let Some(simple_ident) = anon_arg_sub.pat.simple_ident() {
96-
format!(" into `{}`", simple_ident)
97-
} else {
98-
String::new()
94+
let span_label_var2 = match anon_arg_sub.original_pat().simple_ident() {
95+
Some(simple_ident) => format!(" into `{}`", simple_ident),
96+
None => String::new(),
9997
};
10098

101-
10299
let (span_1, span_2, main_label, span_label) = match (sup_is_ret_type, sub_is_ret_type) {
103100
(None, None) => {
104101
let (main_label_1, span_label_1) = if ty_sup.hir_id == ty_sub.hir_id {

src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,12 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
9595
}
9696
}
9797

98-
let (error_var, span_label_var) = if let Some(simple_ident) = arg.pat.simple_ident() {
99-
(
98+
let (error_var, span_label_var) = match arg.original_pat().simple_ident() {
99+
Some(simple_ident) => (
100100
format!("the type of `{}`", simple_ident),
101101
format!("the type of `{}`", simple_ident),
102-
)
103-
} else {
104-
("parameter type".to_owned(), "type".to_owned())
102+
),
103+
None => ("parameter type".to_owned(), "type".to_owned()),
105104
};
106105

107106
let mut diag = struct_span_err!(

src/librustc/lint/context.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,9 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
13371337
for a in arguments {
13381338
// Visit the argument..
13391339
self.visit_pat(&a.arg.pat);
1340+
if let ast::ArgSource::AsyncFn(pat) = &a.arg.source {
1341+
self.visit_pat(pat);
1342+
}
13401343
self.visit_ty(&a.arg.ty);
13411344

13421345
// ..and the statement.

src/librustc/middle/resolve_lifetime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2421,7 +2421,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
24212421

24222422
let help_name = if let Some(body) = parent {
24232423
let arg = &self.tcx.hir().body(body).arguments[index];
2424-
format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.pat.hir_id))
2424+
format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.original_pat().hir_id))
24252425
} else {
24262426
format!("argument {}", index + 1)
24272427
};

src/librustc_privacy/lib.rs

+20
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,16 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> {
948948

949949
intravisit::walk_pat(self, pat);
950950
}
951+
952+
fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) {
953+
match s {
954+
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
955+
// a `NodeId` w/out a type, as it is only used for getting the name of the original
956+
// pattern for diagnostics where only an `hir::Arg` is present.
957+
hir::ArgSource::AsyncFn(..) => {},
958+
_ => intravisit::walk_argument_source(self, s),
959+
}
960+
}
951961
}
952962

953963
////////////////////////////////////////////////////////////////////////////////////////////
@@ -1133,6 +1143,16 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
11331143
intravisit::walk_pat(self, pattern);
11341144
}
11351145

1146+
fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) {
1147+
match s {
1148+
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
1149+
// a `NodeId` w/out a type, as it is only used for getting the name of the original
1150+
// pattern for diagnostics where only an `hir::Arg` is present.
1151+
hir::ArgSource::AsyncFn(..) => {},
1152+
_ => intravisit::walk_argument_source(self, s),
1153+
}
1154+
}
1155+
11361156
fn visit_local(&mut self, local: &'tcx hir::Local) {
11371157
if let Some(ref init) = local.init {
11381158
if self.check_expr_pat_type(init.hir_id, init.span) {

src/librustc_typeck/check/mod.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,16 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
10051005
// Don't descend into the bodies of nested closures
10061006
fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
10071007
_: hir::BodyId, _: Span, _: hir::HirId) { }
1008+
1009+
fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
1010+
match s {
1011+
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
1012+
// a `NodeId` w/out a type, as it is only used for getting the name of the original
1013+
// pattern for diagnostics where only an `hir::Arg` is present.
1014+
hir::ArgSource::AsyncFn(..) => {},
1015+
_ => intravisit::walk_argument_source(self, s),
1016+
}
1017+
}
10081018
}
10091019

10101020
/// When `check_fn` is invoked on a generator (i.e., a body that

src/librustc_typeck/check/writeback.rs

+10
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,16 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> {
297297
let ty = self.resolve(&ty, &hir_ty.span);
298298
self.write_ty_to_tables(hir_ty.hir_id, ty);
299299
}
300+
301+
fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
302+
match s {
303+
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
304+
// a `NodeId` w/out a type, as it is only used for getting the name of the original
305+
// pattern for diagnostics where only an `hir::Arg` is present.
306+
hir::ArgSource::AsyncFn(..) => {},
307+
_ => intravisit::walk_argument_source(self, s),
308+
}
309+
}
300310
}
301311

302312
impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {

src/libsyntax/ast.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1736,6 +1736,16 @@ pub struct Arg {
17361736
pub ty: P<Ty>,
17371737
pub pat: P<Pat>,
17381738
pub id: NodeId,
1739+
pub source: ArgSource,
1740+
}
1741+
1742+
/// The source of an argument in a function header.
1743+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1744+
pub enum ArgSource {
1745+
/// Argument as written by the user.
1746+
Normal,
1747+
/// Argument from `async fn` lowering, contains the original binding pattern.
1748+
AsyncFn(P<Pat>),
17391749
}
17401750

17411751
/// Alternative representation for `Arg`s describing `self` parameter of methods.
@@ -1795,6 +1805,7 @@ impl Arg {
17951805
}),
17961806
ty,
17971807
id: DUMMY_NODE_ID,
1808+
source: ArgSource::Normal,
17981809
};
17991810
match eself.node {
18001811
SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),

src/libsyntax/ext/build.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
979979
ast::Arg {
980980
ty,
981981
pat: arg_pat,
982-
id: ast::DUMMY_NODE_ID
982+
id: ast::DUMMY_NODE_ID,
983+
source: ast::ArgSource::Normal,
983984
}
984985
}
985986

src/libsyntax/mut_visit.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ pub trait MutVisitor: Sized {
235235
noop_visit_arg(a, self);
236236
}
237237

238+
fn visit_arg_source(&mut self, a: &mut ArgSource) {
239+
noop_visit_arg_source(a, self);
240+
}
241+
238242
fn visit_generics(&mut self, generics: &mut Generics) {
239243
noop_visit_generics(generics, self);
240244
}
@@ -564,10 +568,18 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
564568
vis.visit_span(span);
565569
}
566570

567-
pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty }: &mut Arg, vis: &mut T) {
571+
pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty, source }: &mut Arg, vis: &mut T) {
568572
vis.visit_id(id);
569573
vis.visit_pat(pat);
570574
vis.visit_ty(ty);
575+
vis.visit_arg_source(source);
576+
}
577+
578+
pub fn noop_visit_arg_source<T: MutVisitor>(source: &mut ArgSource, vis: &mut T) {
579+
match source {
580+
ArgSource::Normal => {},
581+
ArgSource::AsyncFn(pat) => vis.visit_pat(pat),
582+
}
571583
}
572584

573585
pub fn noop_visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {

src/libsyntax/parse/parser.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::ast::{AngleBracketedArgs, AsyncArgument, ParenthesizedArgs, AttrStyle, BareFnTy};
22
use crate::ast::{GenericBound, TraitBoundModifier};
33
use crate::ast::Unsafety;
4-
use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
4+
use crate::ast::{Mod, AnonConst, Arg, ArgSource, Arm, Guard, Attribute, BindingMode, TraitItemKind};
55
use crate::ast::Block;
66
use crate::ast::{BlockCheckMode, CaptureBy, Movability};
77
use crate::ast::{Constness, Crate};
@@ -550,7 +550,7 @@ fn dummy_arg(span: Span) -> Arg {
550550
span,
551551
id: ast::DUMMY_NODE_ID
552552
};
553-
Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
553+
Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal }
554554
}
555555

556556
#[derive(Copy, Clone, Debug)]
@@ -2126,7 +2126,7 @@ impl<'a> Parser<'a> {
21262126
}
21272127
};
21282128

2129-
Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID })
2129+
Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal })
21302130
}
21312131

21322132
/// Parses a single function argument.
@@ -2149,7 +2149,8 @@ impl<'a> Parser<'a> {
21492149
Ok(Arg {
21502150
ty: t,
21512151
pat,
2152-
id: ast::DUMMY_NODE_ID
2152+
id: ast::DUMMY_NODE_ID,
2153+
source: ast::ArgSource::Normal,
21532154
})
21542155
}
21552156

@@ -8856,6 +8857,7 @@ impl<'a> Parser<'a> {
88568857
),
88578858
span,
88588859
}),
8860+
source: ArgSource::AsyncFn(input.pat.clone()),
88598861
};
88608862

88618863
// Construct a `let <pat> = __argN;` statement to insert at the top of the

src/libsyntax/visit.rs

+3
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,9 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR
544544
pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
545545
for argument in &function_declaration.inputs {
546546
visitor.visit_pat(&argument.pat);
547+
if let ArgSource::AsyncFn(pat) = &argument.source {
548+
visitor.visit_pat(pat);
549+
}
547550
visitor.visit_ty(&argument.ty)
548551
}
549552
visitor.visit_fn_ret_ty(&function_declaration.output)

0 commit comments

Comments
 (0)