Compute explicit MIR params on THIR.
This commit is contained in:
parent
f76594a0bc
commit
445841cda3
5 changed files with 86 additions and 55 deletions
|
@ -78,6 +78,22 @@ thir_with_elements! {
|
||||||
blocks: BlockId => Block => "b{}",
|
blocks: BlockId => Block => "b{}",
|
||||||
exprs: ExprId => Expr<'tcx> => "e{}",
|
exprs: ExprId => Expr<'tcx> => "e{}",
|
||||||
stmts: StmtId => Stmt<'tcx> => "s{}",
|
stmts: StmtId => Stmt<'tcx> => "s{}",
|
||||||
|
params: ParamId => Param<'tcx> => "p{}",
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Description of a type-checked function parameter.
|
||||||
|
#[derive(Clone, Debug, HashStable)]
|
||||||
|
pub struct Param<'tcx> {
|
||||||
|
/// The pattern that appears in the parameter list.
|
||||||
|
pub pat: Box<Pat<'tcx>>,
|
||||||
|
/// The possibly inferred type.
|
||||||
|
pub ty: Ty<'tcx>,
|
||||||
|
/// Span of the explicitly provided type, or None if inferred for closures.
|
||||||
|
pub ty_span: Option<Span>,
|
||||||
|
/// Whether this param is `self`, and how it is bound.
|
||||||
|
pub self_kind: Option<hir::ImplicitSelfKind>,
|
||||||
|
/// HirId for lints.
|
||||||
|
pub hir_id: hir::HirId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, HashStable)]
|
#[derive(Copy, Clone, Debug, HashStable)]
|
||||||
|
@ -548,6 +564,15 @@ impl<'tcx> Pat<'tcx> {
|
||||||
pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
|
pub fn wildcard_from_ty(ty: Ty<'tcx>) -> Self {
|
||||||
Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
|
Pat { ty, span: DUMMY_SP, kind: PatKind::Wild }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn simple_ident(&self) -> Option<Symbol> {
|
||||||
|
match self.kind {
|
||||||
|
PatKind::Binding { name, mode: BindingMode::ByValue, subpattern: None, .. } => {
|
||||||
|
Some(name)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, HashStable)]
|
#[derive(Clone, Debug, HashStable)]
|
||||||
|
|
|
@ -568,7 +568,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
let place_builder = unpack!(block = self.as_place_builder(block, initializer));
|
let place_builder = unpack!(block = self.as_place_builder(block, initializer));
|
||||||
self.place_into_pattern(block, irrefutable_pat, place_builder, true)
|
self.place_into_pattern(block, &irrefutable_pat, place_builder, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant;
|
pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant;
|
||||||
use crate::build::expr::as_place::PlaceBuilder;
|
use crate::build::expr::as_place::PlaceBuilder;
|
||||||
use crate::build::scope::DropKind;
|
use crate::build::scope::DropKind;
|
||||||
use crate::thir::pattern::pat_from_hir;
|
|
||||||
use rustc_apfloat::ieee::{Double, Single};
|
use rustc_apfloat::ieee::{Double, Single};
|
||||||
use rustc_apfloat::Float;
|
use rustc_apfloat::Float;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -9,7 +8,6 @@ use rustc_data_structures::sorted_map::SortedIndexMultiMap;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_hir::lang_items::LangItem;
|
|
||||||
use rustc_hir::{GeneratorKind, ImplicitSelfKind, Node};
|
use rustc_hir::{GeneratorKind, ImplicitSelfKind, Node};
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||||
|
@ -18,8 +16,7 @@ use rustc_middle::middle::region;
|
||||||
use rustc_middle::mir::interpret::ConstValue;
|
use rustc_middle::mir::interpret::ConstValue;
|
||||||
use rustc_middle::mir::interpret::Scalar;
|
use rustc_middle::mir::interpret::Scalar;
|
||||||
use rustc_middle::mir::*;
|
use rustc_middle::mir::*;
|
||||||
use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir};
|
use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, Param, PatKind, Thir};
|
||||||
use rustc_middle::ty::subst::Subst;
|
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -449,10 +446,10 @@ macro_rules! unpack {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
/// the main entry point for building MIR for a function
|
/// the main entry point for building MIR for a function
|
||||||
|
|
||||||
struct ArgInfo<'tcx>(
|
struct ArgInfo<'thir, 'tcx>(
|
||||||
Ty<'tcx>,
|
Ty<'tcx>,
|
||||||
Option<Span>,
|
Option<Span>,
|
||||||
Option<&'tcx hir::Param<'tcx>>,
|
Option<&'thir Param<'tcx>>,
|
||||||
Option<ImplicitSelfKind>,
|
Option<ImplicitSelfKind>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -510,38 +507,8 @@ fn construct_fn<'tcx>(
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
};
|
};
|
||||||
|
|
||||||
let explicit_arguments = body.params.iter().enumerate().map(|(index, arg)| {
|
let explicit_arguments =
|
||||||
let owner_id = tcx.hir().body_owner(body_id);
|
thir.params.iter().map(|arg| ArgInfo(arg.ty, arg.ty_span, Some(&arg), arg.self_kind));
|
||||||
let opt_ty_info;
|
|
||||||
let self_arg;
|
|
||||||
if let Some(ref fn_decl) = tcx.hir().fn_decl_by_hir_id(owner_id) {
|
|
||||||
opt_ty_info = fn_decl
|
|
||||||
.inputs
|
|
||||||
.get(index)
|
|
||||||
// Make sure that inferred closure args have no type span
|
|
||||||
.and_then(|ty| if arg.pat.span != ty.span { Some(ty.span) } else { None });
|
|
||||||
self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
|
|
||||||
Some(fn_decl.implicit_self)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
opt_ty_info = None;
|
|
||||||
self_arg = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
|
|
||||||
// (as it's created inside the body itself, not passed in from outside).
|
|
||||||
let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() {
|
|
||||||
let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(arg.span));
|
|
||||||
|
|
||||||
tcx.bound_type_of(va_list_did).subst(tcx, &[tcx.lifetimes.re_erased.into()])
|
|
||||||
} else {
|
|
||||||
fn_sig.inputs()[index]
|
|
||||||
};
|
|
||||||
|
|
||||||
ArgInfo(ty, opt_ty_info, Some(&arg), self_arg)
|
|
||||||
});
|
|
||||||
|
|
||||||
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
|
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
|
||||||
|
|
||||||
|
@ -852,7 +819,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
fn_def_id: LocalDefId,
|
fn_def_id: LocalDefId,
|
||||||
arguments: &[ArgInfo<'tcx>],
|
arguments: &[ArgInfo<'_, 'tcx>],
|
||||||
argument_scope: region::Scope,
|
argument_scope: region::Scope,
|
||||||
expr: &Expr<'tcx>,
|
expr: &Expr<'tcx>,
|
||||||
) -> BlockAnd<()> {
|
) -> BlockAnd<()> {
|
||||||
|
@ -863,9 +830,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
||||||
|
|
||||||
// If this is a simple binding pattern, give debuginfo a nice name.
|
// If this is a simple binding pattern, give debuginfo a nice name.
|
||||||
if let Some(arg) = arg_opt && let Some(ident) = arg.pat.simple_ident() {
|
if let Some(arg) = arg_opt && let Some(name) = arg.pat.simple_ident() {
|
||||||
self.var_debug_info.push(VarDebugInfo {
|
self.var_debug_info.push(VarDebugInfo {
|
||||||
name: ident.name,
|
name,
|
||||||
source_info,
|
source_info,
|
||||||
value: VarDebugInfoContents::Place(arg_local.into()),
|
value: VarDebugInfoContents::Place(arg_local.into()),
|
||||||
});
|
});
|
||||||
|
@ -955,15 +922,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let Some(arg) = arg_opt else {
|
let Some(arg) = arg_opt else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let pat = match tcx.hir().get(arg.pat.hir_id) {
|
|
||||||
Node::Pat(pat) => pat,
|
|
||||||
node => bug!("pattern became {:?}", node),
|
|
||||||
};
|
|
||||||
let pattern = pat_from_hir(tcx, self.param_env, self.typeck_results, pat);
|
|
||||||
let original_source_scope = self.source_scope;
|
let original_source_scope = self.source_scope;
|
||||||
let span = pattern.span;
|
let span = arg.pat.span;
|
||||||
self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
|
self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
|
||||||
match pattern.kind {
|
match arg.pat.kind {
|
||||||
// Don't introduce extra copies for simple bindings
|
// Don't introduce extra copies for simple bindings
|
||||||
PatKind::Binding {
|
PatKind::Binding {
|
||||||
mutability,
|
mutability,
|
||||||
|
@ -995,15 +957,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
scope = self.declare_bindings(
|
scope = self.declare_bindings(
|
||||||
scope,
|
scope,
|
||||||
expr.span,
|
expr.span,
|
||||||
&pattern,
|
&arg.pat,
|
||||||
matches::ArmHasGuard(false),
|
matches::ArmHasGuard(false),
|
||||||
Some((Some(&place), span)),
|
Some((Some(&place), span)),
|
||||||
);
|
);
|
||||||
let place_builder = PlaceBuilder::from(local);
|
let place_builder = PlaceBuilder::from(local);
|
||||||
unpack!(
|
unpack!(block = self.place_into_pattern(block, &arg.pat, place_builder, false));
|
||||||
block =
|
|
||||||
self.place_into_pattern(block, pattern.as_ref(), place_builder, false)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.source_scope = original_source_scope;
|
self.source_scope = original_source_scope;
|
||||||
|
|
|
@ -9,11 +9,12 @@ use rustc_data_structures::steal::Steal;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
use rustc_hir::Node;
|
use rustc_hir::Node;
|
||||||
use rustc_middle::middle::region;
|
use rustc_middle::middle::region;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
|
use rustc_middle::ty::{self, RvalueScopes, Subst, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
|
||||||
pub(crate) fn thir_body<'tcx>(
|
pub(crate) fn thir_body<'tcx>(
|
||||||
|
@ -27,6 +28,13 @@ pub(crate) fn thir_body<'tcx>(
|
||||||
return Err(reported);
|
return Err(reported);
|
||||||
}
|
}
|
||||||
let expr = cx.mirror_expr(&body.value);
|
let expr = cx.mirror_expr(&body.value);
|
||||||
|
|
||||||
|
let owner_id = hir.local_def_id_to_hir_id(owner_def.did);
|
||||||
|
if let Some(ref fn_decl) = hir.fn_decl_by_hir_id(owner_id) {
|
||||||
|
let explicit_params = cx.explicit_params(owner_id, fn_decl, body);
|
||||||
|
cx.thir.params = explicit_params.collect();
|
||||||
|
}
|
||||||
|
|
||||||
Ok((tcx.alloc_steal_thir(cx.thir), expr))
|
Ok((tcx.alloc_steal_thir(cx.thir), expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +93,44 @@ impl<'tcx> Cx<'tcx> {
|
||||||
};
|
};
|
||||||
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
|
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn explicit_params<'a>(
|
||||||
|
&'a mut self,
|
||||||
|
owner_id: HirId,
|
||||||
|
fn_decl: &'tcx hir::FnDecl<'tcx>,
|
||||||
|
body: &'tcx hir::Body<'tcx>,
|
||||||
|
) -> impl Iterator<Item = Param<'tcx>> + 'a {
|
||||||
|
let fn_sig = self.typeck_results.liberated_fn_sigs()[owner_id];
|
||||||
|
|
||||||
|
body.params.iter().enumerate().map(move |(index, param)| {
|
||||||
|
let ty_span = fn_decl
|
||||||
|
.inputs
|
||||||
|
.get(index)
|
||||||
|
// Make sure that inferred closure args have no type span
|
||||||
|
.and_then(|ty| if param.pat.span != ty.span { Some(ty.span) } else { None });
|
||||||
|
|
||||||
|
let self_kind = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
|
||||||
|
Some(fn_decl.implicit_self)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
|
||||||
|
// (as it's created inside the body itself, not passed in from outside).
|
||||||
|
let ty = if fn_decl.c_variadic && index == fn_decl.inputs.len() {
|
||||||
|
let va_list_did = self.tcx.require_lang_item(LangItem::VaList, Some(param.span));
|
||||||
|
|
||||||
|
self.tcx
|
||||||
|
.bound_type_of(va_list_did)
|
||||||
|
.subst(self.tcx, &[self.tcx.lifetimes.re_erased.into()])
|
||||||
|
} else {
|
||||||
|
fn_sig.inputs()[index]
|
||||||
|
};
|
||||||
|
|
||||||
|
let pat = self.pattern_from_hir(param.pat);
|
||||||
|
Param { pat, ty, ty_span, self_kind, hir_id: param.hir_id }
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> {
|
impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> {
|
||||||
|
|
|
@ -54,5 +54,6 @@ Thir {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
stmts: [],
|
stmts: [],
|
||||||
|
params: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue