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

Lines changed: 10 additions & 0 deletions
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

Lines changed: 9 additions & 0 deletions
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

Lines changed: 20 additions & 0 deletions
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

Lines changed: 6 additions & 9 deletions
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

Lines changed: 4 additions & 5 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 20 additions & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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> {

0 commit comments

Comments
 (0)