Skip to content

Commit 1e5f496

Browse files
committed
rustc: async fn drop order lowering in HIR
This commit re-implements the async fn drop order lowering changes so that it all takes place in HIR lowering, building atop the work done by `@eddyb` to refactor `Res::Upvar`. Previously, this types involved in the lowering were constructed in libsyntax as they had to be used during name resolution and HIR lowering. This was awful because none of that logic should have existed in libsyntax. This commit also changes `ArgSource` to keep a `HirId` to the original argument pattern rather than a cloned copy of the pattern.
1 parent 3277107 commit 1e5f496

File tree

14 files changed

+317
-155
lines changed

14 files changed

+317
-155
lines changed

src/librustc/hir/intravisit.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,6 @@ 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-
}
268265
fn visit_anon_const(&mut self, c: &'v AnonConst) {
269266
walk_anon_const(self, c)
270267
}
@@ -402,17 +399,10 @@ pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
402399
for argument in &body.arguments {
403400
visitor.visit_id(argument.hir_id);
404401
visitor.visit_pat(&argument.pat);
405-
visitor.visit_argument_source(&argument.source);
406402
}
407403
visitor.visit_expr(&body.value);
408404
}
409405

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-
416406
pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
417407
// Intentionally visiting the expr first - the initialization expr
418408
// dominates the local's definition.

src/librustc/hir/lowering.rs

Lines changed: 226 additions & 68 deletions
Large diffs are not rendered by default.

src/librustc/hir/map/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,19 @@ impl<'hir> Map<'hir> {
699699
}
700700
}
701701

702+
/// Returns the `HirId` of this pattern, or, if this is an `async fn` desugaring, the `HirId`
703+
/// of the original pattern that the user wrote.
704+
pub fn original_pat_of_argument(&self, arg: &'hir Arg) -> &'hir Pat {
705+
match &arg.source {
706+
ArgSource::Normal => &*arg.pat,
707+
ArgSource::AsyncFn(hir_id) => match self.find_by_hir_id(*hir_id) {
708+
Some(Node::Pat(pat)) | Some(Node::Binding(pat)) => &pat,
709+
Some(Node::Local(local)) => &*local.pat,
710+
x => bug!("ArgSource::AsyncFn HirId not a pattern/binding/local: {:?}", x),
711+
},
712+
}
713+
}
714+
702715
pub fn is_const_scope(&self, hir_id: HirId) -> bool {
703716
self.walk_parent_nodes(hir_id, |node| match *node {
704717
Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true,

src/librustc/hir/mod.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,23 +1932,13 @@ pub struct Arg {
19321932
pub source: ArgSource,
19331933
}
19341934

1935-
impl Arg {
1936-
/// Returns the pattern representing the original binding for this argument.
1937-
pub fn original_pat(&self) -> &P<Pat> {
1938-
match &self.source {
1939-
ArgSource::Normal => &self.pat,
1940-
ArgSource::AsyncFn(pat) => &pat,
1941-
}
1942-
}
1943-
}
1944-
19451935
/// Represents the source of an argument in a function header.
19461936
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
19471937
pub enum ArgSource {
19481938
/// Argument as specified by the user.
19491939
Normal,
1950-
/// Generated argument from `async fn` lowering, contains the original binding pattern.
1951-
AsyncFn(P<Pat>),
1940+
/// Generated argument from `async fn` lowering, `HirId` is the original pattern.
1941+
AsyncFn(HirId),
19521942
}
19531943

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

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,14 @@ 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 = match anon_arg_sup.original_pat().simple_ident() {
89+
let arg_sup_pat = self.tcx().hir().original_pat_of_argument(anon_arg_sup);
90+
let span_label_var1 = match arg_sup_pat.simple_ident() {
9091
Some(simple_ident) => format!(" from `{}`", simple_ident),
9192
None => String::new(),
9293
};
9394

94-
let span_label_var2 = match anon_arg_sub.original_pat().simple_ident() {
95+
let arg_sub_pat = self.tcx().hir().original_pat_of_argument(anon_arg_sub);
96+
let span_label_var2 = match arg_sub_pat.simple_ident() {
9597
Some(simple_ident) => format!(" into `{}`", simple_ident),
9698
None => String::new(),
9799
};

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> {
9595
}
9696
}
9797

98-
let (error_var, span_label_var) = match arg.original_pat().simple_ident() {
98+
let arg_pat = self.tcx().hir().original_pat_of_argument(arg);
99+
let (error_var, span_label_var) = match arg_pat.simple_ident() {
99100
Some(simple_ident) => (
100101
format!("the type of `{}`", simple_ident),
101102
format!("the type of `{}`", simple_ident),

src/librustc/middle/resolve_lifetime.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2416,7 +2416,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
24162416

24172417
let help_name = if let Some(body) = parent {
24182418
let arg = &self.tcx.hir().body(body).arguments[index];
2419-
format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.original_pat().hir_id))
2419+
let original_pat = self.tcx.hir().original_pat_of_argument(arg);
2420+
format!("`{}`", self.tcx.hir().hir_to_pretty_string(original_pat.hir_id))
24202421
} else {
24212422
format!("argument {}", index + 1)
24222423
};

src/librustc_mir/build/mod.rs

Lines changed: 46 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,23 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<'
8484
// HACK(eddyb) Avoid having RustCall on closures,
8585
// as it adds unnecessary (and wrong) auto-tupling.
8686
abi = Abi::Rust;
87-
Some(ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None))
87+
Some(ArgInfo {
88+
ty: liberated_closure_env_ty(tcx, id, body_id),
89+
span: None,
90+
pattern: None,
91+
user_pattern: None,
92+
self_kind: None,
93+
})
8894
}
8995
ty::Generator(..) => {
9096
let gen_ty = tcx.body_tables(body_id).node_type(id);
91-
Some(ArgInfo(gen_ty, None, None, None))
97+
Some(ArgInfo {
98+
ty: gen_ty,
99+
span: None,
100+
pattern: None,
101+
user_pattern: None,
102+
self_kind: None,
103+
})
92104
}
93105
_ => None,
94106
};
@@ -126,7 +138,15 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<'
126138
opt_ty_info = None;
127139
self_arg = None;
128140
}
129-
ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
141+
142+
let original_pat = tcx.hir().original_pat_of_argument(arg);
143+
ArgInfo {
144+
ty: fn_sig.inputs()[index],
145+
span: opt_ty_info,
146+
pattern: Some(&*arg.pat),
147+
user_pattern: Some(&original_pat),
148+
self_kind: self_arg,
149+
}
130150
});
131151

132152
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
@@ -614,10 +634,13 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
614634
///////////////////////////////////////////////////////////////////////////
615635
/// the main entry point for building MIR for a function
616636
617-
struct ArgInfo<'gcx>(Ty<'gcx>,
618-
Option<Span>,
619-
Option<&'gcx hir::Pat>,
620-
Option<ImplicitSelfKind>);
637+
struct ArgInfo<'gcx> {
638+
ty: Ty<'gcx>,
639+
span: Option<Span>,
640+
pattern: Option<&'gcx hir::Pat>,
641+
user_pattern: Option<&'gcx hir::Pat>,
642+
self_kind: Option<ImplicitSelfKind>,
643+
}
621644

622645
fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
623646
fn_id: hir::HirId,
@@ -878,26 +901,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
878901
-> BlockAnd<()>
879902
{
880903
// Allocate locals for the function arguments
881-
for &ArgInfo(ty, _, pattern, _) in arguments.iter() {
904+
for &ArgInfo { ty, span: _, pattern, user_pattern, self_kind: _ } in arguments.iter() {
882905
// If this is a simple binding pattern, give the local a name for
883906
// debuginfo and so that error reporting knows that this is a user
884907
// variable. For any other pattern the pattern introduces new
885908
// variables which will be named instead.
886-
let mut name = None;
887-
if let Some(pat) = pattern {
909+
let (name, span) = if let Some(pat) = user_pattern {
888910
match pat.node {
889911
hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _)
890-
| hir::PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, _) => {
891-
name = Some(ident.name);
892-
}
893-
_ => (),
912+
| hir::PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, _) =>
913+
(Some(ident.name), pat.span),
914+
_ => (None, pattern.map_or(self.fn_span, |pat| pat.span))
894915
}
895-
}
896-
897-
let source_info = SourceInfo {
898-
scope: OUTERMOST_SOURCE_SCOPE,
899-
span: pattern.map_or(self.fn_span, |pat| pat.span)
916+
} else {
917+
(None, self.fn_span)
900918
};
919+
920+
let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span, };
901921
self.local_decls.push(LocalDecl {
902922
mutability: Mutability::Mut,
903923
ty,
@@ -917,7 +937,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
917937
// Function arguments always get the first Local indices after the return place
918938
let local = Local::new(index + 1);
919939
let place = Place::Base(PlaceBase::Local(local));
920-
let &ArgInfo(ty, opt_ty_info, pattern, ref self_binding) = arg_info;
940+
let &ArgInfo {
941+
ty,
942+
span: opt_ty_info,
943+
pattern,
944+
user_pattern: _,
945+
self_kind: ref self_binding
946+
} = arg_info;
921947

922948
// Make sure we drop (parts of) the argument even when not matched on.
923949
self.schedule_drop(

src/librustc_privacy/lib.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -948,16 +948,6 @@ 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-
}
961951
}
962952

963953
////////////////////////////////////////////////////////////////////////////////////////////
@@ -1147,16 +1137,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
11471137
intravisit::walk_pat(self, pattern);
11481138
}
11491139

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

src/librustc_typeck/check/mod.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,16 +1009,6 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
10091009
// Don't descend into the bodies of nested closures
10101010
fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
10111011
_: hir::BodyId, _: Span, _: hir::HirId) { }
1012-
1013-
fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
1014-
match s {
1015-
// Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
1016-
// a `NodeId` w/out a type, as it is only used for getting the name of the original
1017-
// pattern for diagnostics where only an `hir::Arg` is present.
1018-
hir::ArgSource::AsyncFn(..) => {},
1019-
_ => intravisit::walk_argument_source(self, s),
1020-
}
1021-
}
10221012
}
10231013

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

0 commit comments

Comments
 (0)