Skip to content

Commit 692064b

Browse files
committed
Also compute implicit params in THIR.
1 parent 609a90d commit 692064b

File tree

3 files changed

+98
-84
lines changed

3 files changed

+98
-84
lines changed

compiler/rustc_middle/src/thir.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ macro_rules! thir_with_elements {
7373
}
7474
}
7575

76+
pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
77+
7678
thir_with_elements! {
7779
arms: ArmId => Arm<'tcx> => "a{}",
7880
blocks: BlockId => Block => "b{}",
@@ -84,16 +86,16 @@ thir_with_elements! {
8486
/// Description of a type-checked function parameter.
8587
#[derive(Clone, Debug, HashStable)]
8688
pub struct Param<'tcx> {
87-
/// The pattern that appears in the parameter list.
88-
pub pat: Pat<'tcx>,
89+
/// The pattern that appears in the parameter list, or None for implicit parameters.
90+
pub pat: Option<Pat<'tcx>>,
8991
/// The possibly inferred type.
9092
pub ty: Ty<'tcx>,
9193
/// Span of the explicitly provided type, or None if inferred for closures.
9294
pub ty_span: Option<Span>,
9395
/// Whether this param is `self`, and how it is bound.
9496
pub self_kind: Option<hir::ImplicitSelfKind>,
9597
/// HirId for lints.
96-
pub hir_id: hir::HirId,
98+
pub hir_id: Option<hir::HirId>,
9799
}
98100

99101
#[derive(Copy, Clone, Debug, HashStable)]

compiler/rustc_mir_build/src/build/mod.rs

Lines changed: 35 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ use rustc_apfloat::Float;
66
use rustc_data_structures::fx::FxHashMap;
77
use rustc_errors::ErrorGuaranteed;
88
use rustc_hir as hir;
9+
use rustc_hir::def::DefKind;
910
use rustc_hir::def_id::{DefId, LocalDefId};
10-
use rustc_hir::{GeneratorKind, ImplicitSelfKind, Node};
11+
use rustc_hir::{GeneratorKind, Node};
1112
use rustc_index::vec::{Idx, IndexVec};
1213
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
1314
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
1415
use rustc_middle::middle::region;
1516
use rustc_middle::mir::interpret::ConstValue;
1617
use rustc_middle::mir::interpret::Scalar;
1718
use rustc_middle::mir::*;
18-
use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, PatKind, Thir};
19+
use rustc_middle::thir::{
20+
self, BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir,
21+
};
1922
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults};
2023
use rustc_span::symbol::sym;
2124
use rustc_span::Span;
@@ -96,26 +99,6 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
9699
///////////////////////////////////////////////////////////////////////////
97100
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
98101

99-
fn liberated_closure_env_ty(
100-
tcx: TyCtxt<'_>,
101-
closure_expr_id: hir::HirId,
102-
body_id: hir::BodyId,
103-
) -> Ty<'_> {
104-
let closure_ty = tcx.typeck_body(body_id).node_type(closure_expr_id);
105-
106-
let ty::Closure(closure_def_id, closure_substs) = *closure_ty.kind() else {
107-
bug!("closure expr does not have closure type: {:?}", closure_ty);
108-
};
109-
110-
let bound_vars =
111-
tcx.mk_bound_variable_kinds(std::iter::once(ty::BoundVariableKind::Region(ty::BrEnv)));
112-
let br =
113-
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind: ty::BrEnv };
114-
let env_region = ty::ReLateBound(ty::INNERMOST, br);
115-
let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
116-
tcx.erase_late_bound_regions(ty::Binder::bind_with_vars(closure_env_ty, bound_vars))
117-
}
118-
119102
#[derive(Debug, PartialEq, Eq)]
120103
enum BlockFrame {
121104
/// Evaluation is currently within a statement.
@@ -436,13 +419,6 @@ macro_rules! unpack {
436419
///////////////////////////////////////////////////////////////////////////
437420
/// the main entry point for building MIR for a function
438421
439-
struct ArgInfo<'thir, 'tcx>(
440-
Ty<'tcx>,
441-
Option<Span>,
442-
Option<&'thir Param<'tcx>>,
443-
Option<ImplicitSelfKind>,
444-
);
445-
446422
fn construct_fn<'tcx>(
447423
tcx: TyCtxt<'tcx>,
448424
fn_def: ty::WithOptConstParam<LocalDefId>,
@@ -473,50 +449,28 @@ fn construct_fn<'tcx>(
473449
hir::Unsafety::Unsafe => Safety::FnUnsafe,
474450
};
475451

476-
let body = tcx.hir().body(body_id);
477-
let ty = tcx.type_of(fn_def.did);
478452
let mut abi = fn_sig.abi;
479-
let implicit_argument = match ty.kind() {
480-
ty::Closure(..) => {
481-
// HACK(eddyb) Avoid having RustCall on closures,
482-
// as it adds unnecessary (and wrong) auto-tupling.
483-
abi = Abi::Rust;
484-
vec![ArgInfo(liberated_closure_env_ty(tcx, fn_id, body_id), None, None, None)]
485-
}
486-
ty::Generator(..) => {
487-
let gen_ty = typeck_results.node_type(fn_id);
488-
489-
// The resume argument may be missing, in that case we need to provide it here.
490-
// It will always be `()` in this case.
491-
if body.params.is_empty() {
492-
vec![ArgInfo(gen_ty, None, None, None), ArgInfo(tcx.mk_unit(), None, None, None)]
493-
} else {
494-
vec![ArgInfo(gen_ty, None, None, None)]
495-
}
496-
}
497-
_ => vec![],
498-
};
499-
500-
let explicit_arguments =
501-
thir.params.iter().map(|arg| ArgInfo(arg.ty, arg.ty_span, Some(&arg), arg.self_kind));
453+
if let DefKind::Closure = tcx.def_kind(fn_def.did) {
454+
// HACK(eddyb) Avoid having RustCall on closures,
455+
// as it adds unnecessary (and wrong) auto-tupling.
456+
abi = Abi::Rust;
457+
}
502458

503-
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
459+
let arguments = &thir.params;
504460

505461
let (yield_ty, return_ty) = if generator_kind.is_some() {
506-
let gen_ty = typeck_results.node_type(fn_id);
462+
let gen_ty = arguments[thir::UPVAR_ENV_PARAM].ty;
507463
let gen_sig = match gen_ty.kind() {
508464
ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(),
509465
_ => {
510-
span_bug!(span, "generator w/o generator type: {:?}", ty)
466+
span_bug!(span, "generator w/o generator type: {:?}", gen_ty)
511467
}
512468
};
513469
(Some(gen_sig.yield_ty), gen_sig.return_ty)
514470
} else {
515471
(None, fn_sig.output())
516472
};
517473

518-
let arguments: Vec<_> = arguments.collect();
519-
520474
let mut body = tcx.infer_ctxt().enter(|infcx| {
521475
let mut builder = Builder::new(
522476
thir,
@@ -532,9 +486,9 @@ fn construct_fn<'tcx>(
532486
);
533487

534488
let call_site_scope =
535-
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
489+
region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::CallSite };
536490
let arg_scope =
537-
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Arguments };
491+
region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::Arguments };
538492
let source_info = builder.source_info(span);
539493
let call_site_s = (call_site_scope, source_info);
540494
unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
@@ -550,7 +504,7 @@ fn construct_fn<'tcx>(
550504
builder.args_and_body(
551505
START_BLOCK,
552506
fn_def.did,
553-
&arguments,
507+
arguments,
554508
arg_scope,
555509
&thir[expr],
556510
)
@@ -809,18 +763,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
809763
&mut self,
810764
mut block: BasicBlock,
811765
fn_def_id: LocalDefId,
812-
arguments: &[ArgInfo<'_, 'tcx>],
766+
arguments: &IndexVec<ParamId, Param<'tcx>>,
813767
argument_scope: region::Scope,
814768
expr: &Expr<'tcx>,
815769
) -> BlockAnd<()> {
816770
// Allocate locals for the function arguments
817-
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
771+
for param in arguments.iter() {
818772
let source_info =
819-
SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span));
820-
let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
773+
SourceInfo::outermost(param.pat.as_ref().map_or(self.fn_span, |pat| pat.span));
774+
let arg_local =
775+
self.local_decls.push(LocalDecl::with_source_info(param.ty, source_info));
821776

822777
// If this is a simple binding pattern, give debuginfo a nice name.
823-
if let Some(arg) = arg_opt && let Some(name) = arg.pat.simple_ident() {
778+
if let Some(ref pat) = param.pat && let Some(name) = pat.simple_ident() {
824779
self.var_debug_info.push(VarDebugInfo {
825780
name,
826781
source_info,
@@ -893,27 +848,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
893848

894849
let mut scope = None;
895850
// Bind the argument patterns
896-
for (index, arg_info) in arguments.iter().enumerate() {
851+
for (index, param) in arguments.iter().enumerate() {
897852
// Function arguments always get the first Local indices after the return place
898853
let local = Local::new(index + 1);
899854
let place = Place::from(local);
900-
let &ArgInfo(_, opt_ty_info, arg_opt, ref self_binding) = arg_info;
901855

902856
// Make sure we drop (parts of) the argument even when not matched on.
903857
self.schedule_drop(
904-
arg_opt.as_ref().map_or(expr.span, |arg| arg.pat.span),
858+
param.pat.as_ref().map_or(expr.span, |pat| pat.span),
905859
argument_scope,
906860
local,
907861
DropKind::Value,
908862
);
909863

910-
let Some(arg) = arg_opt else {
864+
let Some(ref pat) = param.pat else {
911865
continue;
912866
};
913867
let original_source_scope = self.source_scope;
914-
let span = arg.pat.span;
915-
self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
916-
match *arg.pat.kind {
868+
let span = pat.span;
869+
if let Some(arg_hir_id) = param.hir_id {
870+
self.set_correct_source_scope_for_arg(arg_hir_id, original_source_scope, span);
871+
}
872+
match *pat.kind {
917873
// Don't introduce extra copies for simple bindings
918874
PatKind::Binding {
919875
mutability,
@@ -924,16 +880,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
924880
} => {
925881
self.local_decls[local].mutability = mutability;
926882
self.local_decls[local].source_info.scope = self.source_scope;
927-
self.local_decls[local].local_info = if let Some(kind) = self_binding {
883+
self.local_decls[local].local_info = if let Some(kind) = param.self_kind {
928884
Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(
929-
BindingForm::ImplicitSelf(*kind),
885+
BindingForm::ImplicitSelf(kind),
930886
))))
931887
} else {
932888
let binding_mode = ty::BindingMode::BindByValue(mutability);
933889
Some(Box::new(LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
934890
VarBindingForm {
935891
binding_mode,
936-
opt_ty_info,
892+
opt_ty_info: param.ty_span,
937893
opt_match_place: Some((Some(place), span)),
938894
pat_span: span,
939895
},
@@ -945,12 +901,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
945901
scope = self.declare_bindings(
946902
scope,
947903
expr.span,
948-
&arg.pat,
904+
&pat,
949905
matches::ArmHasGuard(false),
950906
Some((Some(&place), span)),
951907
);
952908
let place_builder = PlaceBuilder::from(local);
953-
unpack!(block = self.place_into_pattern(block, &arg.pat, place_builder, false));
909+
unpack!(block = self.place_into_pattern(block, &pat, place_builder, false));
954910
}
955911
}
956912
self.source_scope = original_source_scope;

compiler/rustc_mir_build/src/thir/cx/mod.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::thir::util::UserAnnotatedTyHelpers;
88
use rustc_data_structures::steal::Steal;
99
use rustc_errors::ErrorGuaranteed;
1010
use rustc_hir as hir;
11+
use rustc_hir::def::DefKind;
1112
use rustc_hir::def_id::{DefId, LocalDefId};
1213
use rustc_hir::lang_items::LangItem;
1314
use rustc_hir::HirId;
@@ -31,8 +32,21 @@ pub(crate) fn thir_body<'tcx>(
3132

3233
let owner_id = hir.local_def_id_to_hir_id(owner_def.did);
3334
if let Some(ref fn_decl) = hir.fn_decl_by_hir_id(owner_id) {
35+
let closure_env_param = cx.closure_env_param(owner_def.did, owner_id);
3436
let explicit_params = cx.explicit_params(owner_id, fn_decl, body);
35-
cx.thir.params = explicit_params.collect();
37+
cx.thir.params = closure_env_param.into_iter().chain(explicit_params).collect();
38+
39+
// The resume argument may be missing, in that case we need to provide it here.
40+
// It will always be `()` in this case.
41+
if tcx.def_kind(owner_def.did) == DefKind::Generator && body.params.is_empty() {
42+
cx.thir.params.push(Param {
43+
ty: tcx.mk_unit(),
44+
pat: None,
45+
ty_span: None,
46+
self_kind: None,
47+
hir_id: None,
48+
});
49+
}
3650
}
3751

3852
Ok((tcx.alloc_steal_thir(cx.thir), expr))
@@ -94,6 +108,48 @@ impl<'tcx> Cx<'tcx> {
94108
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
95109
}
96110

111+
fn closure_env_param(&self, owner_def: LocalDefId, owner_id: HirId) -> Option<Param<'tcx>> {
112+
match self.tcx.def_kind(owner_def) {
113+
DefKind::Closure => {
114+
let closure_ty = self.typeck_results.node_type(owner_id);
115+
116+
let ty::Closure(closure_def_id, closure_substs) = *closure_ty.kind() else {
117+
bug!("closure expr does not have closure type: {:?}", closure_ty);
118+
};
119+
120+
let bound_vars = self.tcx.mk_bound_variable_kinds(std::iter::once(
121+
ty::BoundVariableKind::Region(ty::BrEnv),
122+
));
123+
let br = ty::BoundRegion {
124+
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
125+
kind: ty::BrEnv,
126+
};
127+
let env_region = ty::ReLateBound(ty::INNERMOST, br);
128+
let closure_env_ty =
129+
self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap();
130+
let liberated_closure_env_ty = self.tcx.erase_late_bound_regions(
131+
ty::Binder::bind_with_vars(closure_env_ty, bound_vars),
132+
);
133+
let env_param = Param {
134+
ty: liberated_closure_env_ty,
135+
pat: None,
136+
ty_span: None,
137+
self_kind: None,
138+
hir_id: None,
139+
};
140+
141+
Some(env_param)
142+
}
143+
DefKind::Generator => {
144+
let gen_ty = self.typeck_results.node_type(owner_id);
145+
let gen_param =
146+
Param { ty: gen_ty, pat: None, ty_span: None, self_kind: None, hir_id: None };
147+
Some(gen_param)
148+
}
149+
_ => None,
150+
}
151+
}
152+
97153
fn explicit_params<'a>(
98154
&'a mut self,
99155
owner_id: HirId,
@@ -128,7 +184,7 @@ impl<'tcx> Cx<'tcx> {
128184
};
129185

130186
let pat = self.pattern_from_hir(param.pat);
131-
Param { pat, ty, ty_span, self_kind, hir_id: param.hir_id }
187+
Param { pat: Some(pat), ty, ty_span, self_kind, hir_id: Some(param.hir_id) }
132188
})
133189
}
134190
}

0 commit comments

Comments
 (0)