Skip to content

Commit

Permalink
Introduce ArgSource for diagnostics.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
davidtwco committed Mar 24, 2019
1 parent ea93cb5 commit 468bbb8
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 21 deletions.
10 changes: 10 additions & 0 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,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)
}
Expand Down Expand Up @@ -391,10 +394,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.
Expand Down
8 changes: 8 additions & 0 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2048,6 +2048,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)),
}
}

Expand Down
20 changes: 20 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,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!(
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2420,7 +2420,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)
};
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_typeck/check/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,12 @@ 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, _: &'gcx hir::ArgSource) {
// Don't visit the argument source, in `async fn`s it can contain 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.
}
}

impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
Expand Down
11 changes: 11 additions & 0 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1724,6 +1724,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.
Expand Down Expand Up @@ -1783,6 +1793,7 @@ impl Arg {
}),
ty,
id: DUMMY_NODE_ID,
source: ArgSource::Normal,
};
match eself.node {
SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),
Expand Down
3 changes: 2 additions & 1 deletion src/libsyntax/ext/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down
14 changes: 13 additions & 1 deletion src/libsyntax/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -563,10 +567,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) {
Expand Down
10 changes: 6 additions & 4 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -2101,7 +2101,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.
Expand All @@ -2124,7 +2124,8 @@ impl<'a> Parser<'a> {
Ok(Arg {
ty: t,
pat,
id: ast::DUMMY_NODE_ID
id: ast::DUMMY_NODE_ID,
source: ast::ArgSource::Normal,
})
}

Expand Down Expand Up @@ -8689,6 +8690,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
Expand Down
3 changes: 3 additions & 0 deletions src/libsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,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)
Expand Down

0 comments on commit 468bbb8

Please sign in to comment.