Skip to content

Commit d35dbbd

Browse files
committed
Store the body type in THIR.
1 parent 70fd012 commit d35dbbd

File tree

4 files changed

+57
-37
lines changed

4 files changed

+57
-37
lines changed

compiler/rustc_middle/src/thir.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::AllocId;
2020
use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Field, Mutability, UnOp};
2121
use rustc_middle::ty::adjustment::PointerCast;
2222
use rustc_middle::ty::subst::SubstsRef;
23-
use rustc_middle::ty::{self, AdtDef, Ty, UpvarSubsts};
23+
use rustc_middle::ty::{self, AdtDef, FnSig, Ty, UpvarSubsts};
2424
use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
2525
use rustc_span::def_id::LocalDefId;
2626
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -33,7 +33,12 @@ pub mod print;
3333
pub mod visit;
3434

3535
macro_rules! thir_with_elements {
36-
($($name:ident: $id:ty => $value:ty => $format:literal,)*) => {
36+
(
37+
$($field_name:ident: $field_ty:ty,)*
38+
39+
@elements:
40+
$($name:ident: $id:ty => $value:ty => $format:literal,)*
41+
) => {
3742
$(
3843
newtype_index! {
3944
#[derive(HashStable)]
@@ -47,14 +52,20 @@ macro_rules! thir_with_elements {
4752
/// This can be indexed directly by any THIR index (e.g. [`ExprId`]).
4853
#[derive(Debug, HashStable, Clone)]
4954
pub struct Thir<'tcx> {
55+
$(
56+
pub $field_name: $field_ty,
57+
)*
5058
$(
5159
pub $name: IndexVec<$id, $value>,
5260
)*
5361
}
5462

5563
impl<'tcx> Thir<'tcx> {
56-
pub fn new() -> Thir<'tcx> {
64+
pub fn new($($field_name: $field_ty,)*) -> Thir<'tcx> {
5765
Thir {
66+
$(
67+
$field_name,
68+
)*
5869
$(
5970
$name: IndexVec::new(),
6071
)*
@@ -76,13 +87,22 @@ macro_rules! thir_with_elements {
7687
pub const UPVAR_ENV_PARAM: ParamId = ParamId::from_u32(0);
7788

7889
thir_with_elements! {
90+
body_type: BodyTy<'tcx>,
91+
92+
@elements:
7993
arms: ArmId => Arm<'tcx> => "a{}",
8094
blocks: BlockId => Block => "b{}",
8195
exprs: ExprId => Expr<'tcx> => "e{}",
8296
stmts: StmtId => Stmt<'tcx> => "s{}",
8397
params: ParamId => Param<'tcx> => "p{}",
8498
}
8599

100+
#[derive(Debug, HashStable, Clone)]
101+
pub enum BodyTy<'tcx> {
102+
Const(Ty<'tcx>),
103+
Fn(FnSig<'tcx>),
104+
}
105+
86106
/// Description of a type-checked function parameter.
87107
#[derive(Clone, Debug, HashStable)]
88108
pub struct Param<'tcx> {

compiler/rustc_mir_build/src/build/mod.rs

+8-32
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ pub(crate) fn mir_built(
4747

4848
/// Construct the MIR for a given `DefId`.
4949
fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
50-
let body_owner_kind = tcx.hir().body_owner_kind(def.did);
51-
5250
// Ensure unsafeck and abstract const building is ran before we steal the THIR.
5351
// We can't use `ensure()` for `thir_abstract_const` as it doesn't compute the query
5452
// if inputs are green. This can cause ICEs when calling `thir_abstract_const` after
@@ -65,16 +63,15 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
6563
}
6664

6765
let body = match tcx.thir_body(def) {
68-
Err(error_reported) => construct_error(tcx, def.did, body_owner_kind, error_reported),
66+
Err(error_reported) => construct_error(tcx, def.did, error_reported),
6967
Ok((thir, expr)) => {
7068
// We ran all queries that depended on THIR at the beginning
7169
// of `mir_build`, so now we can steal it
7270
let thir = thir.steal();
7371

74-
if body_owner_kind.is_fn_or_closure() {
75-
construct_fn(tcx, def, &thir, expr)
76-
} else {
77-
construct_const(tcx, def, &thir, expr)
72+
match thir.body_type {
73+
thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig),
74+
thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty),
7875
}
7976
}
8077
};
@@ -434,6 +431,7 @@ fn construct_fn<'tcx>(
434431
fn_def: ty::WithOptConstParam<LocalDefId>,
435432
thir: &Thir<'tcx>,
436433
expr: ExprId,
434+
fn_sig: ty::FnSig<'tcx>,
437435
) -> Body<'tcx> {
438436
let span = tcx.def_span(fn_def.did);
439437
let fn_id = tcx.hir().local_def_id_to_hir_id(fn_def.did);
@@ -453,11 +451,6 @@ fn construct_fn<'tcx>(
453451
.output
454452
.span();
455453

456-
// fetch the fully liberated fn signature (that is, all bound
457-
// types/lifetimes replaced)
458-
let typeck_results = tcx.typeck_opt_const_arg(fn_def);
459-
let fn_sig = typeck_results.liberated_fn_sigs()[fn_id];
460-
461454
let safety = match fn_sig.unsafety {
462455
hir::Unsafety::Normal => Safety::Safe,
463456
hir::Unsafety::Unsafe => Safety::FnUnsafe,
@@ -563,6 +556,7 @@ fn construct_const<'a, 'tcx>(
563556
def: ty::WithOptConstParam<LocalDefId>,
564557
thir: &'a Thir<'tcx>,
565558
expr: ExprId,
559+
const_ty: Ty<'tcx>,
566560
) -> Body<'tcx> {
567561
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
568562

@@ -586,20 +580,6 @@ fn construct_const<'a, 'tcx>(
586580
_ => span_bug!(tcx.def_span(def.did), "can't build MIR for {:?}", def.did),
587581
};
588582

589-
// Get the revealed type of this const. This is *not* the adjusted
590-
// type of its body, which may be a subtype of this type. For
591-
// example:
592-
//
593-
// fn foo(_: &()) {}
594-
// static X: fn(&'static ()) = foo;
595-
//
596-
// The adjusted type of the body of X is `for<'a> fn(&'a ())` which
597-
// is not the same as the type of X. We need the type of the return
598-
// place to be the type of the constant because NLL typeck will
599-
// equate them.
600-
let typeck_results = tcx.typeck_opt_const_arg(def);
601-
let const_ty = typeck_results.node_type(hir_id);
602-
603583
let infcx = tcx.infer_ctxt().build();
604584
let mut builder = Builder::new(
605585
thir,
@@ -629,15 +609,11 @@ fn construct_const<'a, 'tcx>(
629609
///
630610
/// This is required because we may still want to run MIR passes on an item
631611
/// with type errors, but normal MIR construction can't handle that in general.
632-
fn construct_error(
633-
tcx: TyCtxt<'_>,
634-
def: LocalDefId,
635-
body_owner_kind: hir::BodyOwnerKind,
636-
err: ErrorGuaranteed,
637-
) -> Body<'_> {
612+
fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Body<'_> {
638613
let span = tcx.def_span(def);
639614
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
640615
let generator_kind = tcx.generator_kind(def);
616+
let body_owner_kind = tcx.hir().body_owner_kind(def);
641617

642618
let ty = tcx.ty_error(err);
643619
let num_params = match body_owner_kind {

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

+23-2
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,38 @@ impl<'tcx> Cx<'tcx> {
9999
let typeck_results = tcx.typeck_opt_const_arg(def);
100100
let did = def.did;
101101
let hir = tcx.hir();
102+
let hir_id = hir.local_def_id_to_hir_id(did);
103+
104+
let body_type = if hir.body_owner_kind(did).is_fn_or_closure() {
105+
// fetch the fully liberated fn signature (that is, all bound
106+
// types/lifetimes replaced)
107+
BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
108+
} else {
109+
// Get the revealed type of this const. This is *not* the adjusted
110+
// type of its body, which may be a subtype of this type. For
111+
// example:
112+
//
113+
// fn foo(_: &()) {}
114+
// static X: fn(&'static ()) = foo;
115+
//
116+
// The adjusted type of the body of X is `for<'a> fn(&'a ())` which
117+
// is not the same as the type of X. We need the type of the return
118+
// place to be the type of the constant because NLL typeck will
119+
// equate them.
120+
BodyTy::Const(typeck_results.node_type(hir_id))
121+
};
122+
102123
Cx {
103124
tcx,
104-
thir: Thir::new(),
125+
thir: Thir::new(body_type),
105126
param_env: tcx.param_env(def.did),
106127
region_scope_tree: tcx.region_scope_tree(def.did),
107128
typeck_results,
108129
rvalue_scopes: &typeck_results.rvalue_scopes,
109130
body_owner: did.to_def_id(),
110131
adjustment_span: None,
111132
apply_adjustments: hir
112-
.attrs(hir.local_def_id_to_hir_id(did))
133+
.attrs(hir_id)
113134
.iter()
114135
.all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
115136
}

tests/ui/thir-print/thir-flat.stdout

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
DefId(0:3 ~ thir_flat[45a6]::main):
22
Thir {
3+
body_type: Fn(
4+
([]; c_variadic: false)->(),
5+
),
36
arms: [],
47
blocks: [
58
Block {

0 commit comments

Comments
 (0)