2019-02-08 06:28:15 +09:00
|
|
|
use crate::build;
|
2019-05-30 13:21:17 -07:00
|
|
|
use crate::build::scope::DropKind;
|
2020-07-21 09:09:27 +00:00
|
|
|
use crate::thir::cx::Cx;
|
|
|
|
use crate::thir::{BindingMode, LintLevel, PatKind};
|
2020-01-11 13:15:20 +01:00
|
|
|
use rustc_attr::{self as attr, UnwindAttr};
|
2020-04-12 04:24:25 +03:00
|
|
|
use rustc_errors::ErrorReported;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir as hir;
|
2020-04-09 09:43:00 +01:00
|
|
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
2020-08-18 11:47:27 +01:00
|
|
|
use rustc_hir::lang_items::LangItem;
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::{GeneratorKind, HirIdMap, Node};
|
2019-12-24 17:38:22 -05:00
|
|
|
use rustc_index::vec::{Idx, IndexVec};
|
2020-01-06 23:21:41 +01:00
|
|
|
use rustc_infer::infer::TyCtxtInferExt;
|
2020-11-26 00:07:41 -05:00
|
|
|
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
|
2020-03-31 21:38:14 +02:00
|
|
|
use rustc_middle::middle::region;
|
|
|
|
use rustc_middle::mir::*;
|
|
|
|
use rustc_middle::ty::subst::Subst;
|
|
|
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
2020-01-01 19:30:57 +01:00
|
|
|
use rustc_span::symbol::kw;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::Span;
|
2019-12-24 17:38:22 -05:00
|
|
|
use rustc_target::spec::abi::Abi;
|
2017-12-08 21:18:21 +02:00
|
|
|
use rustc_target::spec::PanicStrategy;
|
2015-10-05 12:31:48 -04:00
|
|
|
|
2018-09-11 21:35:08 -04:00
|
|
|
use super::lints;
|
|
|
|
|
2020-07-21 22:54:18 +02:00
|
|
|
crate fn mir_built<'tcx>(
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
def: ty::WithOptConstParam<LocalDefId>,
|
2020-11-14 01:29:30 +01:00
|
|
|
) -> &'tcx rustc_data_structures::steal::Steal<Body<'tcx>> {
|
2020-07-17 19:12:30 +02:00
|
|
|
if let Some(def) = def.try_upgrade(tcx) {
|
2020-07-16 19:36:18 +02:00
|
|
|
return tcx.mir_built(def);
|
2020-07-06 23:49:53 +02:00
|
|
|
}
|
|
|
|
|
2020-10-01 18:47:36 -07:00
|
|
|
let mut body = mir_build(tcx, def);
|
|
|
|
if def.const_param_did.is_some() {
|
|
|
|
assert!(matches!(body.source.instance, ty::InstanceDef::Item(_)));
|
|
|
|
body.source = MirSource::from_instance(ty::InstanceDef::Item(def.to_global()));
|
|
|
|
}
|
|
|
|
|
|
|
|
tcx.alloc_steal_mir(body)
|
2020-01-05 15:46:44 +00:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Construct the MIR for a given `DefId`.
|
2020-07-15 10:50:54 +02:00
|
|
|
fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
|
2020-08-12 12:22:56 +02:00
|
|
|
let id = tcx.hir().local_def_id_to_hir_id(def.did);
|
2016-06-07 17:28:36 +03:00
|
|
|
|
2017-05-02 14:56:26 -04:00
|
|
|
// Figure out what primary body this item has.
|
2020-08-12 17:02:14 -04:00
|
|
|
let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) {
|
2019-11-30 15:08:22 +01:00
|
|
|
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) => {
|
2020-08-12 17:02:14 -04:00
|
|
|
(*body_id, decl.output.span(), None)
|
2019-11-30 15:08:22 +01:00
|
|
|
}
|
|
|
|
Node::Item(hir::Item {
|
2019-12-24 17:38:22 -05:00
|
|
|
kind: hir::ItemKind::Fn(hir::FnSig { decl, .. }, _, body_id),
|
2020-08-12 17:02:14 -04:00
|
|
|
span,
|
2019-12-24 17:38:22 -05:00
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::ImplItem(hir::ImplItem {
|
2020-03-05 09:57:34 -06:00
|
|
|
kind: hir::ImplItemKind::Fn(hir::FnSig { decl, .. }, body_id),
|
2020-08-12 17:02:14 -04:00
|
|
|
span,
|
2019-12-24 17:38:22 -05:00
|
|
|
..
|
|
|
|
})
|
|
|
|
| Node::TraitItem(hir::TraitItem {
|
2020-03-19 11:40:38 +00:00
|
|
|
kind: hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
|
2020-08-12 17:02:14 -04:00
|
|
|
span,
|
2019-12-24 17:38:22 -05:00
|
|
|
..
|
2020-08-12 17:02:14 -04:00
|
|
|
}) => {
|
|
|
|
// Use the `Span` of the `Item/ImplItem/TraitItem` as the body span,
|
|
|
|
// since the def span of a function does not include the body
|
|
|
|
(*body_id, decl.output.span(), Some(*span))
|
|
|
|
}
|
2020-04-16 17:38:52 -07:00
|
|
|
Node::Item(hir::Item {
|
|
|
|
kind: hir::ItemKind::Static(ty, _, body_id) | hir::ItemKind::Const(ty, body_id),
|
|
|
|
..
|
|
|
|
})
|
2019-09-26 16:38:13 +01:00
|
|
|
| Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(ty, body_id), .. })
|
2019-12-24 17:38:22 -05:00
|
|
|
| Node::TraitItem(hir::TraitItem {
|
|
|
|
kind: hir::TraitItemKind::Const(ty, Some(body_id)),
|
|
|
|
..
|
2020-08-12 17:02:14 -04:00
|
|
|
}) => (*body_id, ty.span, None),
|
2021-02-05 06:35:32 -05:00
|
|
|
Node::AnonConst(hir::AnonConst { body, hir_id, .. }) => {
|
|
|
|
(*body, tcx.hir().span(*hir_id), None)
|
|
|
|
}
|
2018-09-15 15:45:12 +01:00
|
|
|
|
2020-07-06 23:49:53 +02:00
|
|
|
_ => span_bug!(tcx.hir().span(id), "can't build MIR for {:?}", def.did),
|
2017-05-02 14:56:26 -04:00
|
|
|
};
|
|
|
|
|
2020-08-12 17:02:14 -04:00
|
|
|
// If we don't have a specialized span for the body, just use the
|
|
|
|
// normal def span.
|
|
|
|
let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id));
|
|
|
|
|
2017-06-09 10:55:16 +03:00
|
|
|
tcx.infer_ctxt().enter(|infcx| {
|
2020-07-06 23:49:53 +02:00
|
|
|
let cx = Cx::new(&infcx, def, id);
|
2020-07-17 08:47:04 +00:00
|
|
|
let body = if let Some(ErrorReported) = cx.typeck_results().tainted_by_errors {
|
2017-05-02 14:56:26 -04:00
|
|
|
build::construct_error(cx, body_id)
|
2018-12-07 18:25:55 +01:00
|
|
|
} else if cx.body_owner_kind.is_fn_or_closure() {
|
2017-05-02 14:56:26 -04:00
|
|
|
// fetch the fully liberated fn signature (that is, all bound
|
|
|
|
// types/lifetimes replaced)
|
2020-07-17 08:47:04 +00:00
|
|
|
let fn_sig = cx.typeck_results().liberated_fn_sigs()[id];
|
2019-06-27 11:28:14 +02:00
|
|
|
let fn_def_id = tcx.hir().local_def_id(id);
|
2017-05-02 14:56:26 -04:00
|
|
|
|
2020-01-25 02:31:32 +01:00
|
|
|
let safety = match fn_sig.unsafety {
|
|
|
|
hir::Unsafety::Normal => Safety::Safe,
|
|
|
|
hir::Unsafety::Unsafe => Safety::FnUnsafe,
|
|
|
|
};
|
|
|
|
|
|
|
|
let body = tcx.hir().body(body_id);
|
2018-11-03 00:22:12 +01:00
|
|
|
let ty = tcx.type_of(fn_def_id);
|
2017-05-02 14:56:26 -04:00
|
|
|
let mut abi = fn_sig.abi;
|
2020-08-03 00:49:11 +02:00
|
|
|
let implicit_argument = match ty.kind() {
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Closure(..) => {
|
2016-12-26 14:34:03 +01:00
|
|
|
// HACK(eddyb) Avoid having RustCall on closures,
|
|
|
|
// as it adds unnecessary (and wrong) auto-tupling.
|
|
|
|
abi = Abi::Rust;
|
2020-01-25 20:03:10 +01:00
|
|
|
vec![ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)]
|
2016-12-26 14:34:03 +01:00
|
|
|
}
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Generator(..) => {
|
2020-07-17 08:47:04 +00:00
|
|
|
let gen_ty = tcx.typeck_body(body_id).node_type(id);
|
2017-05-02 14:56:26 -04:00
|
|
|
|
2020-01-25 02:31:32 +01:00
|
|
|
// The resume argument may be missing, in that case we need to provide it here.
|
2020-02-06 12:27:35 +01:00
|
|
|
// It will always be `()` in this case.
|
2020-01-25 02:31:32 +01:00
|
|
|
if body.params.is_empty() {
|
|
|
|
vec![
|
|
|
|
ArgInfo(gen_ty, None, None, None),
|
2020-02-06 12:27:35 +01:00
|
|
|
ArgInfo(tcx.mk_unit(), None, None, None),
|
2020-01-25 02:31:32 +01:00
|
|
|
]
|
|
|
|
} else {
|
|
|
|
vec![ArgInfo(gen_ty, None, None, None)]
|
|
|
|
}
|
2016-12-26 14:34:03 +01:00
|
|
|
}
|
2020-01-25 20:03:10 +01:00
|
|
|
_ => vec![],
|
2017-09-19 16:20:02 +03:00
|
|
|
};
|
2018-11-30 18:17:50 +01:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let explicit_arguments = body.params.iter().enumerate().map(|(index, arg)| {
|
|
|
|
let owner_id = tcx.hir().body_owner(body_id);
|
|
|
|
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).map(|ty| ty.span);
|
|
|
|
self_arg = if index == 0 && fn_decl.implicit_self.has_implicit_self() {
|
|
|
|
match fn_decl.implicit_self {
|
|
|
|
hir::ImplicitSelfKind::Imm => Some(ImplicitSelfKind::Imm),
|
|
|
|
hir::ImplicitSelfKind::Mut => Some(ImplicitSelfKind::Mut),
|
|
|
|
hir::ImplicitSelfKind::ImmRef => Some(ImplicitSelfKind::ImmRef),
|
|
|
|
hir::ImplicitSelfKind::MutRef => Some(ImplicitSelfKind::MutRef),
|
|
|
|
_ => None,
|
2018-06-07 17:05:58 +02:00
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
opt_ty_info = None;
|
|
|
|
self_arg = None;
|
|
|
|
}
|
2019-05-29 19:28:51 +03:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
// 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() {
|
2020-08-18 11:47:27 +01:00
|
|
|
let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(arg.span));
|
2019-12-24 17:38:22 -05:00
|
|
|
|
2020-03-19 11:40:38 +00:00
|
|
|
tcx.type_of(va_list_did).subst(tcx, &[tcx.lifetimes.re_erased.into()])
|
2019-12-24 17:38:22 -05:00
|
|
|
} else {
|
|
|
|
fn_sig.inputs()[index]
|
|
|
|
};
|
2019-08-10 14:38:17 +03:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
ArgInfo(ty, opt_ty_info, Some(&arg), self_arg)
|
|
|
|
});
|
2017-05-02 14:56:26 -04:00
|
|
|
|
|
|
|
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
|
2017-07-05 14:57:26 -07:00
|
|
|
|
2019-06-18 14:34:51 -07:00
|
|
|
let (yield_ty, return_ty) = if body.generator_kind.is_some() {
|
2020-07-17 08:47:04 +00:00
|
|
|
let gen_ty = tcx.typeck_body(body_id).node_type(id);
|
2020-08-03 00:49:11 +02:00
|
|
|
let gen_sig = match gen_ty.kind() {
|
2020-03-13 03:23:38 +02:00
|
|
|
ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(),
|
2019-12-24 17:38:22 -05:00
|
|
|
_ => span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty),
|
2017-11-18 11:16:25 -05:00
|
|
|
};
|
2017-07-11 12:57:05 -07:00
|
|
|
(Some(gen_sig.yield_ty), gen_sig.return_ty)
|
2016-12-26 14:34:03 +01:00
|
|
|
} else {
|
2017-07-11 12:57:05 -07:00
|
|
|
(None, fn_sig.output())
|
2016-12-26 14:34:03 +01:00
|
|
|
};
|
2017-07-05 14:57:26 -07:00
|
|
|
|
2018-05-16 18:58:54 +03:00
|
|
|
let mut mir = build::construct_fn(
|
|
|
|
cx,
|
|
|
|
id,
|
|
|
|
arguments,
|
|
|
|
safety,
|
|
|
|
abi,
|
|
|
|
return_ty,
|
|
|
|
return_ty_span,
|
|
|
|
body,
|
2021-02-05 06:35:32 -05:00
|
|
|
span_with_body,
|
2018-05-16 18:58:54 +03:00
|
|
|
);
|
2021-01-17 13:27:05 +01:00
|
|
|
if yield_ty.is_some() {
|
|
|
|
mir.generator.as_mut().unwrap().yield_ty = yield_ty;
|
|
|
|
}
|
2018-05-16 18:58:54 +03:00
|
|
|
mir
|
2017-05-02 14:56:26 -04:00
|
|
|
} else {
|
2019-03-30 13:00:41 +00:00
|
|
|
// Get the revealed type of this const. This is *not* the adjusted
|
|
|
|
// type of its body, which may be a subtype of this type. For
|
|
|
|
// example:
|
|
|
|
//
|
|
|
|
// fn foo(_: &()) {}
|
|
|
|
// static X: fn(&'static ()) = foo;
|
|
|
|
//
|
|
|
|
// The adjusted type of the body of X is `for<'a> fn(&'a ())` which
|
|
|
|
// is not the same as the type of X. We need the type of the return
|
|
|
|
// place to be the type of the constant because NLL typeck will
|
|
|
|
// equate them.
|
|
|
|
|
2020-07-17 08:47:04 +00:00
|
|
|
let return_ty = cx.typeck_results().node_type(id);
|
2019-03-30 13:00:41 +00:00
|
|
|
|
|
|
|
build::construct_const(cx, body_id, return_ty, return_ty_span)
|
2017-05-02 14:56:26 -04:00
|
|
|
};
|
|
|
|
|
2020-10-04 15:22:23 -07:00
|
|
|
lints::check(tcx, &body);
|
2020-04-09 19:24:09 -07:00
|
|
|
|
2020-03-19 11:40:38 +00:00
|
|
|
// The borrow checker will replace all the regions here with its own
|
|
|
|
// inference variables. There's no point having non-erased regions here.
|
|
|
|
// The exception is `body.user_type_annotations`, which is used unmodified
|
|
|
|
// by borrow checking.
|
|
|
|
debug_assert!(
|
|
|
|
!(body.local_decls.has_free_regions()
|
|
|
|
|| body.basic_blocks().has_free_regions()
|
|
|
|
|| body.var_debug_info.has_free_regions()
|
2021-01-17 13:27:05 +01:00
|
|
|
|| body.yield_ty().has_free_regions()),
|
2020-03-19 11:40:38 +00:00
|
|
|
"Unexpected free regions in MIR: {:?}",
|
|
|
|
body,
|
|
|
|
);
|
|
|
|
|
2019-11-12 23:41:43 -05:00
|
|
|
body
|
2017-05-02 14:56:26 -04:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
|
|
|
|
|
2019-06-21 18:51:27 +02:00
|
|
|
fn liberated_closure_env_ty(
|
|
|
|
tcx: TyCtxt<'_>,
|
2019-06-12 00:11:55 +03:00
|
|
|
closure_expr_id: hir::HirId,
|
|
|
|
body_id: hir::BodyId,
|
2019-06-21 18:51:27 +02:00
|
|
|
) -> Ty<'_> {
|
2020-07-17 08:47:04 +00:00
|
|
|
let closure_ty = tcx.typeck_body(body_id).node_type(closure_expr_id);
|
2017-05-02 14:56:26 -04:00
|
|
|
|
2020-08-03 00:49:11 +02:00
|
|
|
let (closure_def_id, closure_substs) = match *closure_ty.kind() {
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Closure(closure_def_id, closure_substs) => (closure_def_id, closure_substs),
|
2019-12-24 17:38:22 -05:00
|
|
|
_ => bug!("closure expr does not have closure type: {:?}", closure_ty),
|
2017-11-08 09:45:48 -05:00
|
|
|
};
|
|
|
|
|
2017-11-21 11:18:40 -05:00
|
|
|
let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap();
|
2020-10-24 02:21:18 +02:00
|
|
|
tcx.erase_late_bound_regions(closure_env_ty)
|
2017-05-02 14:56:26 -04:00
|
|
|
}
|
2016-06-07 17:28:36 +03:00
|
|
|
|
2018-09-22 00:51:48 +02:00
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
2020-01-05 15:46:44 +00:00
|
|
|
enum BlockFrame {
|
2018-09-22 00:51:48 +02:00
|
|
|
/// Evaluation is currently within a statement.
|
|
|
|
///
|
|
|
|
/// Examples include:
|
2019-02-28 22:43:53 +00:00
|
|
|
/// 1. `EXPR;`
|
|
|
|
/// 2. `let _ = EXPR;`
|
|
|
|
/// 3. `let x = EXPR;`
|
2018-09-22 00:51:48 +02:00
|
|
|
Statement {
|
|
|
|
/// If true, then statement discards result from evaluating
|
|
|
|
/// the expression (such as examples 1 and 2 above).
|
2019-12-24 17:38:22 -05:00
|
|
|
ignores_expr_result: bool,
|
2018-09-22 00:51:48 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/// Evaluation is currently within the tail expression of a block.
|
|
|
|
///
|
|
|
|
/// Example: `{ STMT_1; STMT_2; EXPR }`
|
|
|
|
TailExpr {
|
|
|
|
/// If true, then the surrounding context of the block ignores
|
|
|
|
/// the result of evaluating the block's tail expression.
|
|
|
|
///
|
|
|
|
/// Example: `let _ = { STMT_1; EXPR };`
|
2019-12-24 17:38:22 -05:00
|
|
|
tail_result_is_ignored: bool,
|
2020-04-16 12:43:40 -07:00
|
|
|
|
|
|
|
/// `Span` of the tail expression.
|
|
|
|
span: Span,
|
2018-09-22 00:51:48 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
/// Generic mark meaning that the block occurred as a subexpression
|
|
|
|
/// where the result might be used.
|
|
|
|
///
|
|
|
|
/// Examples: `foo(EXPR)`, `match EXPR { ... }`
|
|
|
|
SubExpr,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BlockFrame {
|
|
|
|
fn is_tail_expr(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
BlockFrame::TailExpr { .. } => true,
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
BlockFrame::Statement { .. } | BlockFrame::SubExpr => false,
|
2018-09-22 00:51:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fn is_statement(&self) -> bool {
|
|
|
|
match *self {
|
|
|
|
BlockFrame::Statement { .. } => true,
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
BlockFrame::TailExpr { .. } | BlockFrame::SubExpr => false,
|
2018-09-22 00:51:48 +02:00
|
|
|
}
|
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2018-09-22 00:51:48 +02:00
|
|
|
|
2018-11-08 14:31:12 +01:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct BlockContext(Vec<BlockFrame>);
|
|
|
|
|
2019-06-14 19:39:39 +03:00
|
|
|
struct Builder<'a, 'tcx> {
|
2019-06-01 13:38:36 +02:00
|
|
|
hir: Cx<'a, 'tcx>,
|
2015-10-05 12:31:48 -04:00
|
|
|
cfg: CFG<'tcx>,
|
2016-03-09 11:04:26 -05:00
|
|
|
|
2020-10-04 11:01:38 -07:00
|
|
|
def_id: DefId,
|
2016-03-22 20:41:07 -04:00
|
|
|
fn_span: Span,
|
2016-09-25 01:38:27 +02:00
|
|
|
arg_count: usize,
|
2019-11-25 12:58:40 +00:00
|
|
|
generator_kind: Option<GeneratorKind>,
|
2016-03-22 20:41:07 -04:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// The current set of scopes, updated as we traverse;
|
|
|
|
/// see the `scope` module for more details.
|
2019-06-15 17:37:19 +01:00
|
|
|
scopes: scope::Scopes<'tcx>,
|
2016-03-09 11:04:26 -05:00
|
|
|
|
2020-07-21 09:09:27 +00:00
|
|
|
/// The block-context: each time we build the code within an thir::Block,
|
2018-09-22 00:51:48 +02:00
|
|
|
/// we push a frame here tracking whether we are building a statement or
|
|
|
|
/// if we are pushing the tail expression of the block. This is used to
|
|
|
|
/// embed information in generated temps about whether they were created
|
|
|
|
/// for a block tail expression or not.
|
|
|
|
///
|
|
|
|
/// It would be great if we could fold this into `self.scopes`
|
2019-02-08 14:53:55 +01:00
|
|
|
/// somehow, but right now I think that is very tightly tied to
|
2018-09-22 00:51:48 +02:00
|
|
|
/// the code generation in ways that we cannot (or should not)
|
|
|
|
/// start just throwing new entries onto that vector in order to
|
|
|
|
/// distinguish the context of EXPR1 from the context of EXPR2 in
|
2019-02-08 14:53:55 +01:00
|
|
|
/// `{ STMTS; EXPR1 } + EXPR2`.
|
2018-11-08 14:31:12 +01:00
|
|
|
block_context: BlockContext,
|
2018-09-22 00:51:48 +02:00
|
|
|
|
2017-09-19 16:20:02 +03:00
|
|
|
/// The current unsafe block in scope, even if it is hidden by
|
2019-02-08 14:53:55 +01:00
|
|
|
/// a `PushUnsafeBlock`.
|
2017-09-19 16:20:02 +03:00
|
|
|
unpushed_unsafe: Safety,
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// The number of `push_unsafe_block` levels in scope.
|
2017-09-19 16:20:02 +03:00
|
|
|
push_unsafe_count: usize,
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// The vector of all scopes that we have created thus far;
|
|
|
|
/// we track this for debuginfo later.
|
2020-02-08 21:31:09 +02:00
|
|
|
source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
|
2018-05-28 14:16:09 +03:00
|
|
|
source_scope: SourceScope,
|
2016-03-09 11:04:26 -05:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// The guard-context: each time we build the guard expression for
|
2018-02-26 15:45:13 +01:00
|
|
|
/// a match arm, we push onto this stack, and then pop when we
|
|
|
|
/// finish building it.
|
|
|
|
guard_context: Vec<GuardFrame>,
|
|
|
|
|
2019-03-10 13:22:00 +01:00
|
|
|
/// Maps `HirId`s of variable bindings to the `Local`s created for them.
|
2018-02-26 15:45:13 +01:00
|
|
|
/// (A match binding can have two locals; the 2nd is for the arm's guard.)
|
2019-03-07 12:18:59 +01:00
|
|
|
var_indices: HirIdMap<LocalsForNode>,
|
2016-09-25 01:38:27 +02:00
|
|
|
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
2018-11-16 22:56:18 +01:00
|
|
|
canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
|
2018-05-16 15:40:32 +03:00
|
|
|
upvar_mutbls: Vec<Mutability>,
|
2017-12-01 14:31:47 +02:00
|
|
|
unit_temp: Option<Place<'tcx>>,
|
2016-03-23 20:46:38 -04:00
|
|
|
|
2018-05-16 18:58:54 +03:00
|
|
|
var_debug_info: Vec<VarDebugInfo<'tcx>>,
|
2015-08-18 17:59:21 -04:00
|
|
|
}
|
|
|
|
|
2019-06-01 13:38:36 +02:00
|
|
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
2019-03-07 12:18:59 +01:00
|
|
|
fn is_bound_var_in_guard(&self, id: hir::HirId) -> bool {
|
2018-02-26 15:45:13 +01:00
|
|
|
self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id))
|
|
|
|
}
|
|
|
|
|
2019-03-07 12:18:59 +01:00
|
|
|
fn var_local_id(&self, id: hir::HirId, for_guard: ForGuard) -> Local {
|
2018-02-26 15:45:13 +01:00
|
|
|
self.var_indices[&id].local_id(for_guard)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-08 14:31:12 +01:00
|
|
|
impl BlockContext {
|
2019-12-24 17:38:22 -05:00
|
|
|
fn new() -> Self {
|
|
|
|
BlockContext(vec![])
|
|
|
|
}
|
|
|
|
fn push(&mut self, bf: BlockFrame) {
|
|
|
|
self.0.push(bf);
|
|
|
|
}
|
|
|
|
fn pop(&mut self) -> Option<BlockFrame> {
|
|
|
|
self.0.pop()
|
|
|
|
}
|
2018-11-08 14:31:12 +01:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Traverses the frames on the `BlockContext`, searching for either
|
2018-11-08 14:31:12 +01:00
|
|
|
/// the first block-tail expression frame with no intervening
|
|
|
|
/// statement frame.
|
|
|
|
///
|
|
|
|
/// Notably, this skips over `SubExpr` frames; this method is
|
|
|
|
/// meant to be used in the context of understanding the
|
|
|
|
/// relationship of a temp (created within some complicated
|
|
|
|
/// expression) with its containing expression, and whether the
|
|
|
|
/// value of that *containing expression* (not the temp!) is
|
|
|
|
/// ignored.
|
|
|
|
fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
|
|
|
|
for bf in self.0.iter().rev() {
|
|
|
|
match bf {
|
|
|
|
BlockFrame::SubExpr => continue,
|
|
|
|
BlockFrame::Statement { .. } => break,
|
2020-04-16 12:43:40 -07:00
|
|
|
&BlockFrame::TailExpr { tail_result_is_ignored, span } => {
|
|
|
|
return Some(BlockTailInfo { tail_result_is_ignored, span });
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2018-11-08 14:31:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-20 15:03:11 +01:00
|
|
|
None
|
2018-11-08 14:31:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Looks at the topmost frame on the BlockContext and reports
|
|
|
|
/// whether its one that would discard a block tail result.
|
|
|
|
///
|
|
|
|
/// Unlike `currently_within_ignored_tail_expression`, this does
|
|
|
|
/// *not* skip over `SubExpr` frames: here, we want to know
|
|
|
|
/// whether the block result itself is discarded.
|
|
|
|
fn currently_ignores_tail_results(&self) -> bool {
|
|
|
|
match self.0.last() {
|
|
|
|
// no context: conservatively assume result is read
|
|
|
|
None => false,
|
|
|
|
|
|
|
|
// sub-expression: block result feeds into some computation
|
|
|
|
Some(BlockFrame::SubExpr) => false,
|
|
|
|
|
|
|
|
// otherwise: use accumulated is_ignored state.
|
2020-04-16 17:38:52 -07:00
|
|
|
Some(
|
2020-04-16 12:43:40 -07:00
|
|
|
BlockFrame::TailExpr { tail_result_is_ignored: ignored, .. }
|
2020-04-16 17:38:52 -07:00
|
|
|
| BlockFrame::Statement { ignores_expr_result: ignored },
|
|
|
|
) => *ignored,
|
2018-11-08 14:31:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-26 15:45:13 +01:00
|
|
|
#[derive(Debug)]
|
|
|
|
enum LocalsForNode {
|
2019-03-10 13:22:00 +01:00
|
|
|
/// In the usual case, a `HirId` for an identifier maps to at most
|
2019-02-08 14:53:55 +01:00
|
|
|
/// one `Local` declaration.
|
2018-02-26 15:45:13 +01:00
|
|
|
One(Local),
|
2018-07-26 13:14:12 +02:00
|
|
|
|
|
|
|
/// The exceptional case is identifiers in a match arm's pattern
|
|
|
|
/// that are referenced in a guard of that match arm. For these,
|
2019-02-02 16:38:12 +00:00
|
|
|
/// we have `2` Locals.
|
2018-07-26 13:14:12 +02:00
|
|
|
///
|
|
|
|
/// * `for_arm_body` is the Local used in the arm body (which is
|
|
|
|
/// just like the `One` case above),
|
|
|
|
///
|
|
|
|
/// * `ref_for_guard` is the Local used in the arm's guard (which
|
|
|
|
/// is a reference to a temp that is an alias of
|
|
|
|
/// `for_arm_body`).
|
2019-02-02 16:38:12 +00:00
|
|
|
ForGuard { ref_for_guard: Local, for_arm_body: Local },
|
2018-02-26 15:45:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct GuardFrameLocal {
|
2019-03-07 12:18:59 +01:00
|
|
|
id: hir::HirId,
|
2018-02-26 15:45:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GuardFrameLocal {
|
2019-03-07 12:18:59 +01:00
|
|
|
fn new(id: hir::HirId, _binding_mode: BindingMode) -> Self {
|
2020-03-06 19:28:44 +01:00
|
|
|
GuardFrameLocal { id }
|
2018-02-26 15:45:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct GuardFrame {
|
|
|
|
/// These are the id's of names that are bound by patterns of the
|
|
|
|
/// arm of *this* guard.
|
|
|
|
///
|
|
|
|
/// (Frames higher up the stack will have the id's bound in arms
|
|
|
|
/// further out, such as in a case like:
|
|
|
|
///
|
|
|
|
/// match E1 {
|
|
|
|
/// P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1,
|
|
|
|
/// }
|
|
|
|
///
|
2019-02-08 14:53:55 +01:00
|
|
|
/// here, when building for FIXME.
|
2018-02-26 15:45:13 +01:00
|
|
|
locals: Vec<GuardFrameLocal>,
|
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// `ForGuard` indicates whether we are talking about:
|
2019-02-02 16:38:12 +00:00
|
|
|
/// 1. The variable for use outside of guard expressions, or
|
|
|
|
/// 2. The temp that holds reference to (1.), which is actually what the
|
|
|
|
/// guard expressions see.
|
2018-02-26 15:45:13 +01:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
enum ForGuard {
|
2018-05-11 23:32:13 +02:00
|
|
|
RefWithinGuard,
|
2018-02-26 15:45:13 +01:00
|
|
|
OutsideGuard,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LocalsForNode {
|
|
|
|
fn local_id(&self, for_guard: ForGuard) -> Local {
|
|
|
|
match (self, for_guard) {
|
2019-12-24 17:38:22 -05:00
|
|
|
(&LocalsForNode::One(local_id), ForGuard::OutsideGuard)
|
|
|
|
| (
|
|
|
|
&LocalsForNode::ForGuard { ref_for_guard: local_id, .. },
|
|
|
|
ForGuard::RefWithinGuard,
|
|
|
|
)
|
|
|
|
| (&LocalsForNode::ForGuard { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) => {
|
|
|
|
local_id
|
|
|
|
}
|
2018-02-26 15:45:13 +01:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
(&LocalsForNode::One(_), ForGuard::RefWithinGuard) => {
|
|
|
|
bug!("anything with one local should never be within a guard.")
|
|
|
|
}
|
2018-02-26 15:45:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-05 12:31:48 -04:00
|
|
|
struct CFG<'tcx> {
|
2016-06-07 17:28:36 +03:00
|
|
|
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
2015-08-18 17:59:21 -04:00
|
|
|
}
|
|
|
|
|
2019-09-26 05:38:33 +00:00
|
|
|
rustc_index::newtype_index! {
|
2020-01-05 15:46:44 +00:00
|
|
|
struct ScopeId { .. }
|
2018-07-25 13:41:32 +03:00
|
|
|
}
|
2016-05-31 20:27:36 +03:00
|
|
|
|
2015-08-18 17:59:21 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2016-02-03 13:25:07 +01:00
|
|
|
/// The `BlockAnd` "monad" packages up the new basic block along with a
|
|
|
|
/// produced value (sometimes just unit, of course). The `unpack!`
|
|
|
|
/// macro (and methods below) makes working with `BlockAnd` much more
|
|
|
|
/// convenient.
|
2015-08-18 17:59:21 -04:00
|
|
|
|
2018-03-30 23:06:05 -07:00
|
|
|
#[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
|
2017-05-01 11:58:05 -04:00
|
|
|
struct BlockAnd<T>(BasicBlock, T);
|
2015-08-18 17:59:21 -04:00
|
|
|
|
2015-11-19 16:37:34 +01:00
|
|
|
trait BlockAndExtension {
|
|
|
|
fn and<T>(self, v: T) -> BlockAnd<T>;
|
|
|
|
fn unit(self) -> BlockAnd<()>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BlockAndExtension for BasicBlock {
|
2015-08-18 17:59:21 -04:00
|
|
|
fn and<T>(self, v: T) -> BlockAnd<T> {
|
|
|
|
BlockAnd(self, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn unit(self) -> BlockAnd<()> {
|
|
|
|
BlockAnd(self, ())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Update a block pointer and return the value.
|
|
|
|
/// Use it like `let x = unpack!(block = self.foo(block, foo))`.
|
|
|
|
macro_rules! unpack {
|
2019-12-24 17:38:22 -05:00
|
|
|
($x:ident = $c:expr) => {{
|
|
|
|
let BlockAnd(b, v) = $c;
|
|
|
|
$x = b;
|
|
|
|
v
|
|
|
|
}};
|
|
|
|
|
|
|
|
($c:expr) => {{
|
|
|
|
let BlockAnd(b, ()) = $c;
|
|
|
|
b
|
|
|
|
}};
|
2015-08-18 17:59:21 -04:00
|
|
|
}
|
|
|
|
|
2020-04-09 09:43:00 +01:00
|
|
|
fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: LocalDefId, _abi: Abi) -> bool {
|
2019-10-12 20:48:19 +02:00
|
|
|
// Validate `#[unwind]` syntax regardless of platform-specific panic strategy.
|
2020-04-09 09:43:00 +01:00
|
|
|
let attrs = &tcx.get_attrs(fn_def_id.to_def_id());
|
2020-07-30 11:27:50 +10:00
|
|
|
let unwind_attr = attr::find_unwind_attr(&tcx.sess, attrs);
|
2019-02-27 09:36:49 +03:00
|
|
|
|
2019-10-12 20:48:19 +02:00
|
|
|
// We never unwind, so it's not relevant to stop an unwind.
|
2019-12-24 17:38:22 -05:00
|
|
|
if tcx.sess.panic_strategy() != PanicStrategy::Unwind {
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-19 01:59:29 +01:00
|
|
|
|
|
|
|
// This is a special case: some functions have a C abi but are meant to
|
|
|
|
// unwind anyway. Don't stop them.
|
2019-02-27 09:36:49 +03:00
|
|
|
match unwind_attr {
|
2019-10-12 20:48:19 +02:00
|
|
|
None => false, // FIXME(#58794); should be `!(abi == Abi::Rust || abi == Abi::RustCall)`
|
2018-02-20 13:49:54 -05:00
|
|
|
Some(UnwindAttr::Allowed) => false,
|
|
|
|
Some(UnwindAttr::Aborts) => true,
|
|
|
|
}
|
2017-12-19 01:59:29 +01:00
|
|
|
}
|
|
|
|
|
2015-08-18 17:59:21 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////
|
2016-02-03 13:25:07 +01:00
|
|
|
/// the main entry point for building MIR for a function
|
2015-08-18 17:59:21 -04:00
|
|
|
|
2019-11-30 15:08:22 +01:00
|
|
|
struct ArgInfo<'tcx>(
|
|
|
|
Ty<'tcx>,
|
|
|
|
Option<Span>,
|
|
|
|
Option<&'tcx hir::Param<'tcx>>,
|
|
|
|
Option<ImplicitSelfKind>,
|
|
|
|
);
|
2018-06-07 16:32:07 +02:00
|
|
|
|
2019-06-01 13:38:36 +02:00
|
|
|
fn construct_fn<'a, 'tcx, A>(
|
|
|
|
hir: Cx<'a, 'tcx>,
|
|
|
|
fn_id: hir::HirId,
|
|
|
|
arguments: A,
|
|
|
|
safety: Safety,
|
|
|
|
abi: Abi,
|
|
|
|
return_ty: Ty<'tcx>,
|
|
|
|
return_ty_span: Span,
|
2019-11-29 11:09:23 +01:00
|
|
|
body: &'tcx hir::Body<'tcx>,
|
2021-02-05 06:35:32 -05:00
|
|
|
span_with_body: Span,
|
2019-06-01 13:38:36 +02:00
|
|
|
) -> Body<'tcx>
|
|
|
|
where
|
2019-12-24 17:38:22 -05:00
|
|
|
A: Iterator<Item = ArgInfo<'tcx>>,
|
2016-04-15 17:11:24 +03:00
|
|
|
{
|
2016-09-25 01:38:27 +02:00
|
|
|
let arguments: Vec<_> = arguments.collect();
|
|
|
|
|
2016-03-23 12:26:37 -04:00
|
|
|
let tcx = hir.tcx();
|
2018-12-22 15:06:14 -08:00
|
|
|
let tcx_hir = tcx.hir();
|
2019-06-14 18:58:55 +02:00
|
|
|
let span = tcx_hir.span(fn_id);
|
2018-07-15 15:00:58 +01:00
|
|
|
|
2019-06-27 11:28:14 +02:00
|
|
|
let fn_def_id = tcx_hir.local_def_id(fn_id);
|
2018-07-15 15:00:58 +01:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let mut builder = Builder::new(
|
|
|
|
hir,
|
2020-10-04 11:01:38 -07:00
|
|
|
fn_def_id.to_def_id(),
|
2020-08-12 17:02:14 -04:00
|
|
|
span_with_body,
|
2017-07-11 12:57:05 -07:00
|
|
|
arguments.len(),
|
2017-09-19 16:20:02 +03:00
|
|
|
safety,
|
2018-07-15 15:00:58 +01:00
|
|
|
return_ty,
|
2018-09-15 15:45:12 +01:00
|
|
|
return_ty_span,
|
2019-12-24 17:38:22 -05:00
|
|
|
body.generator_kind,
|
|
|
|
);
|
2016-03-18 08:52:13 -04:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let call_site_scope =
|
|
|
|
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite };
|
|
|
|
let arg_scope =
|
|
|
|
region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::Arguments };
|
2017-05-26 18:21:03 +02:00
|
|
|
let source_info = builder.source_info(span);
|
2017-09-13 22:33:07 +03:00
|
|
|
let call_site_s = (call_site_scope, source_info);
|
2019-11-16 13:23:31 +00:00
|
|
|
unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
|
|
|
|
let arg_scope_s = (arg_scope, source_info);
|
|
|
|
// Attribute epilogue to function's closing brace
|
|
|
|
let fn_end = span_with_body.shrink_to_hi();
|
2021-01-21 22:35:05 -05:00
|
|
|
let return_block =
|
|
|
|
unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
|
2019-11-16 13:23:31 +00:00
|
|
|
Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| {
|
|
|
|
builder.args_and_body(
|
|
|
|
START_BLOCK,
|
|
|
|
fn_def_id.to_def_id(),
|
|
|
|
&arguments,
|
|
|
|
arg_scope,
|
|
|
|
&body.value,
|
|
|
|
)
|
|
|
|
}))
|
2021-01-21 22:35:05 -05:00
|
|
|
}));
|
2019-11-16 13:23:31 +00:00
|
|
|
let source_info = builder.source_info(fn_end);
|
|
|
|
builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
|
|
|
|
let should_abort = should_abort_on_panic(tcx, fn_def_id, abi);
|
|
|
|
builder.build_drop_trees(should_abort);
|
|
|
|
return_block.unit()
|
|
|
|
}));
|
2016-04-15 17:11:24 +03:00
|
|
|
|
2020-03-21 14:44:17 +01:00
|
|
|
let spread_arg = if abi == Abi::RustCall {
|
2016-11-10 16:49:53 +02:00
|
|
|
// RustCall pseudo-ABI untuples the last argument.
|
2020-03-21 14:44:17 +01:00
|
|
|
Some(Local::new(arguments.len()))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2020-04-09 09:43:00 +01:00
|
|
|
debug!("fn_id {:?} has attrs {:?}", fn_def_id, tcx.get_attrs(fn_def_id.to_def_id()));
|
2016-03-22 16:05:28 -04:00
|
|
|
|
2018-05-16 18:58:54 +03:00
|
|
|
let mut body = builder.finish();
|
2019-06-03 18:26:48 -04:00
|
|
|
body.spread_arg = spread_arg;
|
|
|
|
body
|
2015-08-18 17:59:21 -04:00
|
|
|
}
|
|
|
|
|
2019-06-01 13:38:36 +02:00
|
|
|
fn construct_const<'a, 'tcx>(
|
|
|
|
hir: Cx<'a, 'tcx>,
|
2018-09-15 15:45:12 +01:00
|
|
|
body_id: hir::BodyId,
|
2019-03-30 13:00:41 +00:00
|
|
|
const_ty: Ty<'tcx>,
|
|
|
|
const_ty_span: Span,
|
2019-05-17 23:55:04 +02:00
|
|
|
) -> Body<'tcx> {
|
2016-05-02 23:11:19 +03:00
|
|
|
let tcx = hir.tcx();
|
2018-12-04 13:45:36 +01:00
|
|
|
let owner_id = tcx.hir().body_owner(body_id);
|
2020-10-04 11:01:38 -07:00
|
|
|
let def_id = tcx.hir().local_def_id(owner_id);
|
2019-06-14 18:58:55 +02:00
|
|
|
let span = tcx.hir().span(owner_id);
|
2021-02-05 06:35:32 -05:00
|
|
|
let mut builder =
|
|
|
|
Builder::new(hir, def_id.to_def_id(), span, 0, Safety::Safe, const_ty, const_ty_span, None);
|
2016-05-02 23:11:19 +03:00
|
|
|
|
|
|
|
let mut block = START_BLOCK;
|
2019-03-30 13:00:41 +00:00
|
|
|
let ast_expr = &tcx.hir().body(body_id).value;
|
2021-02-24 21:29:09 +01:00
|
|
|
let expr = builder.hir.mirror_expr(ast_expr);
|
|
|
|
unpack!(block = builder.expr_into_dest(Place::return_place(), block, &expr));
|
2016-05-02 23:11:19 +03:00
|
|
|
|
2017-05-07 17:30:55 +03:00
|
|
|
let source_info = builder.source_info(span);
|
|
|
|
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
2016-05-02 23:11:19 +03:00
|
|
|
|
2019-11-16 13:23:31 +00:00
|
|
|
builder.build_drop_trees(false);
|
2016-05-02 23:11:19 +03:00
|
|
|
|
2018-05-16 18:58:54 +03:00
|
|
|
builder.finish()
|
2016-05-02 23:11:19 +03:00
|
|
|
}
|
|
|
|
|
2019-12-26 17:51:39 +00:00
|
|
|
/// Construct MIR for a item that has had errors in type checking.
|
|
|
|
///
|
|
|
|
/// This is required because we may still want to run MIR passes on an item
|
|
|
|
/// with type errors, but normal MIR construction can't handle that in general.
|
2019-12-24 17:38:22 -05:00
|
|
|
fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> {
|
2019-12-26 17:51:39 +00:00
|
|
|
let tcx = hir.tcx();
|
|
|
|
let owner_id = tcx.hir().body_owner(body_id);
|
2020-10-04 11:01:38 -07:00
|
|
|
let def_id = tcx.hir().local_def_id(owner_id);
|
2019-12-26 17:51:39 +00:00
|
|
|
let span = tcx.hir().span(owner_id);
|
2020-05-05 23:02:09 -05:00
|
|
|
let ty = tcx.ty_error();
|
2021-01-17 13:27:05 +01:00
|
|
|
let generator_kind = tcx.hir().body(body_id).generator_kind;
|
2019-12-26 17:51:39 +00:00
|
|
|
let num_params = match hir.body_owner_kind {
|
|
|
|
hir::BodyOwnerKind::Fn => tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len(),
|
|
|
|
hir::BodyOwnerKind::Closure => {
|
2021-01-17 13:27:05 +01:00
|
|
|
if generator_kind.is_some() {
|
2019-12-26 17:51:39 +00:00
|
|
|
// Generators have an implicit `self` parameter *and* a possibly
|
|
|
|
// implicit resume parameter.
|
|
|
|
2
|
|
|
|
} else {
|
|
|
|
// The implicit self parameter adds another local in MIR.
|
|
|
|
1 + tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
hir::BodyOwnerKind::Const => 0,
|
|
|
|
hir::BodyOwnerKind::Static(_) => 0,
|
|
|
|
};
|
2021-01-17 13:27:05 +01:00
|
|
|
let mut builder = Builder::new(
|
|
|
|
hir,
|
|
|
|
def_id.to_def_id(),
|
|
|
|
span,
|
|
|
|
num_params,
|
|
|
|
Safety::Safe,
|
|
|
|
ty,
|
|
|
|
span,
|
|
|
|
generator_kind,
|
|
|
|
);
|
2017-02-15 15:00:20 +02:00
|
|
|
let source_info = builder.source_info(span);
|
2019-12-26 17:51:39 +00:00
|
|
|
// Some MIR passes will expect the number of parameters to match the
|
|
|
|
// function declaration.
|
|
|
|
for _ in 0..num_params {
|
2020-05-06 10:17:38 +10:00
|
|
|
builder.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
2019-12-26 17:51:39 +00:00
|
|
|
}
|
2017-02-15 15:00:20 +02:00
|
|
|
builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
|
2019-12-26 17:51:39 +00:00
|
|
|
let mut body = builder.finish();
|
2021-01-17 13:27:05 +01:00
|
|
|
body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty));
|
2019-12-26 17:51:39 +00:00
|
|
|
body
|
2017-02-15 15:00:20 +02:00
|
|
|
}
|
|
|
|
|
2019-06-01 13:38:36 +02:00
|
|
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
2019-12-24 17:38:22 -05:00
|
|
|
fn new(
|
|
|
|
hir: Cx<'a, 'tcx>,
|
2020-10-04 11:01:38 -07:00
|
|
|
def_id: DefId,
|
2019-12-24 17:38:22 -05:00
|
|
|
span: Span,
|
|
|
|
arg_count: usize,
|
|
|
|
safety: Safety,
|
|
|
|
return_ty: Ty<'tcx>,
|
|
|
|
return_span: Span,
|
|
|
|
generator_kind: Option<GeneratorKind>,
|
|
|
|
) -> Builder<'a, 'tcx> {
|
2017-09-13 22:33:07 +03:00
|
|
|
let lint_level = LintLevel::Explicit(hir.root_lint_level);
|
2016-04-15 17:11:24 +03:00
|
|
|
let mut builder = Builder {
|
2017-08-06 22:54:09 -07:00
|
|
|
hir,
|
2020-10-04 11:01:38 -07:00
|
|
|
def_id,
|
2016-06-07 17:28:36 +03:00
|
|
|
cfg: CFG { basic_blocks: IndexVec::new() },
|
2016-04-15 17:11:24 +03:00
|
|
|
fn_span: span,
|
2017-08-06 22:54:09 -07:00
|
|
|
arg_count,
|
2019-11-25 12:58:40 +00:00
|
|
|
generator_kind,
|
2019-11-16 13:23:31 +00:00
|
|
|
scopes: scope::Scopes::new(),
|
2018-11-08 14:31:12 +01:00
|
|
|
block_context: BlockContext::new(),
|
2018-05-28 14:16:09 +03:00
|
|
|
source_scopes: IndexVec::new(),
|
|
|
|
source_scope: OUTERMOST_SOURCE_SCOPE,
|
2018-02-26 15:45:13 +01:00
|
|
|
guard_context: vec![],
|
2017-09-19 16:20:02 +03:00
|
|
|
push_unsafe_count: 0,
|
|
|
|
unpushed_unsafe: safety,
|
2020-05-06 10:17:38 +10:00
|
|
|
local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
|
2018-11-16 22:56:18 +01:00
|
|
|
canonical_user_type_annotations: IndexVec::new(),
|
2018-05-16 18:58:54 +03:00
|
|
|
upvar_mutbls: vec![],
|
2018-07-21 22:15:11 +03:00
|
|
|
var_indices: Default::default(),
|
2016-04-15 17:11:24 +03:00
|
|
|
unit_temp: None,
|
2018-05-16 18:58:54 +03:00
|
|
|
var_debug_info: vec![],
|
2016-04-15 17:11:24 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
|
2017-09-13 22:33:07 +03:00
|
|
|
assert_eq!(
|
2018-05-28 14:16:09 +03:00
|
|
|
builder.new_source_scope(span, lint_level, Some(safety)),
|
2019-12-24 17:38:22 -05:00
|
|
|
OUTERMOST_SOURCE_SCOPE
|
|
|
|
);
|
2018-05-28 14:16:09 +03:00
|
|
|
builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None;
|
2016-04-15 17:11:24 +03:00
|
|
|
|
|
|
|
builder
|
|
|
|
}
|
|
|
|
|
2018-05-16 18:58:54 +03:00
|
|
|
fn finish(self) -> Body<'tcx> {
|
2016-04-15 17:11:24 +03:00
|
|
|
for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
|
2019-10-04 00:55:28 -04:00
|
|
|
if block.terminator.is_none() {
|
2016-04-15 17:11:24 +03:00
|
|
|
span_bug!(self.fn_span, "no terminator on block {:?}", index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 23:55:04 +02:00
|
|
|
Body::new(
|
2020-10-04 11:01:38 -07:00
|
|
|
MirSource::item(self.def_id),
|
2018-11-24 14:38:31 +01:00
|
|
|
self.cfg.basic_blocks,
|
|
|
|
self.source_scopes,
|
|
|
|
self.local_decls,
|
2018-11-16 22:56:18 +01:00
|
|
|
self.canonical_user_type_annotations,
|
2018-11-24 14:38:31 +01:00
|
|
|
self.arg_count,
|
2018-05-16 18:58:54 +03:00
|
|
|
self.var_debug_info,
|
2018-11-24 14:38:31 +01:00
|
|
|
self.fn_span,
|
2019-12-24 17:38:22 -05:00
|
|
|
self.generator_kind,
|
2016-11-03 14:22:57 +11:00
|
|
|
)
|
2016-04-15 17:11:24 +03:00
|
|
|
}
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
fn args_and_body(
|
|
|
|
&mut self,
|
|
|
|
mut block: BasicBlock,
|
|
|
|
fn_def_id: DefId,
|
|
|
|
arguments: &[ArgInfo<'tcx>],
|
|
|
|
argument_scope: region::Scope,
|
2019-11-30 15:08:22 +01:00
|
|
|
ast_body: &'tcx hir::Expr<'tcx>,
|
2019-12-24 17:38:22 -05:00
|
|
|
) -> BlockAnd<()> {
|
2016-09-25 01:38:27 +02:00
|
|
|
// Allocate locals for the function arguments
|
2019-07-26 19:52:37 -03:00
|
|
|
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {
|
2020-05-06 10:30:11 +10:00
|
|
|
let source_info =
|
|
|
|
SourceInfo::outermost(arg_opt.map_or(self.fn_span, |arg| arg.pat.span));
|
2020-05-06 10:17:38 +10:00
|
|
|
let arg_local = self.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
2018-05-16 18:58:54 +03:00
|
|
|
|
|
|
|
// If this is a simple binding pattern, give debuginfo a nice name.
|
|
|
|
if let Some(arg) = arg_opt {
|
|
|
|
if let Some(ident) = arg.pat.simple_ident() {
|
|
|
|
self.var_debug_info.push(VarDebugInfo {
|
|
|
|
name: ident.name,
|
|
|
|
source_info,
|
2020-05-30 15:02:32 -04:00
|
|
|
value: VarDebugInfoContents::Place(arg_local.into()),
|
2018-05-16 18:58:54 +03:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-11 14:07:08 -04:00
|
|
|
let tcx = self.hir.tcx();
|
2018-05-16 18:58:54 +03:00
|
|
|
let tcx_hir = tcx.hir();
|
2020-07-17 08:47:04 +00:00
|
|
|
let hir_typeck_results = self.hir.typeck_results();
|
2018-05-16 18:58:54 +03:00
|
|
|
|
|
|
|
// In analyze_closure() in upvar.rs we gathered a list of upvars used by a
|
2020-07-17 08:47:04 +00:00
|
|
|
// indexed closure and we stored in a map called closure_captures in TypeckResults
|
2018-05-16 18:58:54 +03:00
|
|
|
// with the closure's DefId. Here, we run through that vec of UpvarIds for
|
|
|
|
// the given closure and use the necessary information to create upvar
|
|
|
|
// debuginfo and to fill `self.upvar_mutbls`.
|
2020-11-26 00:07:41 -05:00
|
|
|
if hir_typeck_results.closure_min_captures.get(&fn_def_id).is_some() {
|
2018-05-16 18:58:54 +03:00
|
|
|
let closure_env_arg = Local::new(1);
|
|
|
|
let mut closure_env_projs = vec![];
|
|
|
|
let mut closure_ty = self.local_decls[closure_env_arg].ty;
|
2020-08-03 00:49:11 +02:00
|
|
|
if let ty::Ref(_, ty, _) = closure_ty.kind() {
|
2018-05-16 18:58:54 +03:00
|
|
|
closure_env_projs.push(ProjectionElem::Deref);
|
|
|
|
closure_ty = ty;
|
|
|
|
}
|
2020-08-03 00:49:11 +02:00
|
|
|
let upvar_substs = match closure_ty.kind() {
|
2020-03-13 03:23:38 +02:00
|
|
|
ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs),
|
|
|
|
ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs),
|
2019-12-24 17:38:22 -05:00
|
|
|
_ => span_bug!(self.fn_span, "upvars with non-closure env ty {:?}", closure_ty),
|
2018-05-16 18:58:54 +03:00
|
|
|
};
|
2020-11-26 00:07:41 -05:00
|
|
|
let capture_tys = upvar_substs.upvar_tys();
|
2021-01-09 12:00:45 -05:00
|
|
|
let captures_with_tys =
|
|
|
|
hir_typeck_results.closure_min_captures_flattened(fn_def_id).zip(capture_tys);
|
2020-11-26 00:07:41 -05:00
|
|
|
|
|
|
|
self.upvar_mutbls = captures_with_tys
|
2019-12-24 17:38:22 -05:00
|
|
|
.enumerate()
|
2020-11-26 00:07:41 -05:00
|
|
|
.map(|(i, (captured_place, ty))| {
|
|
|
|
let capture = captured_place.info.capture_kind;
|
|
|
|
let var_id = match captured_place.place.base {
|
|
|
|
HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
|
2021-01-09 12:00:45 -05:00
|
|
|
_ => bug!("Expected an upvar"),
|
2020-11-26 00:07:41 -05:00
|
|
|
};
|
2019-12-24 17:38:22 -05:00
|
|
|
|
2020-12-02 03:03:56 -05:00
|
|
|
let mutability = captured_place.mutability;
|
2020-11-26 00:07:41 -05:00
|
|
|
|
|
|
|
// FIXME(project-rfc-2229#8): Store more precise information
|
2020-12-29 20:28:08 -05:00
|
|
|
let mut name = kw::Empty;
|
2019-12-24 17:38:22 -05:00
|
|
|
if let Some(Node::Binding(pat)) = tcx_hir.find(var_id) {
|
|
|
|
if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
|
|
|
|
name = ident.name;
|
2018-05-16 18:58:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let mut projs = closure_env_projs.clone();
|
|
|
|
projs.push(ProjectionElem::Field(Field::new(i), ty));
|
|
|
|
match capture {
|
2020-08-25 23:58:58 -04:00
|
|
|
ty::UpvarCapture::ByValue(_) => {}
|
2019-12-24 17:38:22 -05:00
|
|
|
ty::UpvarCapture::ByRef(..) => {
|
|
|
|
projs.push(ProjectionElem::Deref);
|
|
|
|
}
|
|
|
|
};
|
2018-05-16 18:58:54 +03:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
self.var_debug_info.push(VarDebugInfo {
|
|
|
|
name,
|
2020-05-06 10:30:11 +10:00
|
|
|
source_info: SourceInfo::outermost(tcx_hir.span(var_id)),
|
2020-05-30 15:02:32 -04:00
|
|
|
value: VarDebugInfoContents::Place(Place {
|
2020-02-25 18:10:34 +01:00
|
|
|
local: closure_env_arg,
|
2019-12-24 17:38:22 -05:00
|
|
|
projection: tcx.intern_place_elems(&projs),
|
2020-05-30 15:02:32 -04:00
|
|
|
}),
|
2019-12-24 17:38:22 -05:00
|
|
|
});
|
2018-05-16 18:58:54 +03:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
mutability
|
|
|
|
})
|
|
|
|
.collect();
|
2016-09-25 01:38:27 +02:00
|
|
|
}
|
|
|
|
|
2016-05-31 20:27:36 +03:00
|
|
|
let mut scope = None;
|
2016-09-25 01:38:27 +02:00
|
|
|
// Bind the argument patterns
|
2018-06-07 17:05:58 +02:00
|
|
|
for (index, arg_info) in arguments.iter().enumerate() {
|
2017-12-01 14:39:51 +02:00
|
|
|
// Function arguments always get the first Local indices after the return place
|
Avoid unnecessary copies of arguments that are simple bindings
Initially MIR differentiated between arguments and locals, which
introduced a need to add extra copies assigning the argument to a
local, even for simple bindings. This differentiation no longer exists,
but we're still creating those copies, bloating the MIR and LLVM IR we
emit.
Additionally, the current approach means that we create debug info for
both the incoming argument (marking it as an argument), and then
immediately shadow it a local that goes by the same name. This can be
confusing when using e.g. "info args" in gdb, or when e.g. a debugger
with a GUI displays the function arguments separately from the local
variables, especially when the binding is mutable, because the argument
doesn't change, while the local variable does.
2017-10-11 20:49:36 +02:00
|
|
|
let local = Local::new(index + 1);
|
2019-06-24 17:46:09 +02:00
|
|
|
let place = Place::from(local);
|
2019-09-29 15:08:57 +01:00
|
|
|
let &ArgInfo(_, opt_ty_info, arg_opt, ref self_binding) = arg_info;
|
2016-09-25 01:38:27 +02:00
|
|
|
|
2018-11-18 14:49:24 +00:00
|
|
|
// Make sure we drop (parts of) the argument even when not matched on.
|
|
|
|
self.schedule_drop(
|
2019-07-26 19:52:37 -03:00
|
|
|
arg_opt.as_ref().map_or(ast_body.span, |arg| arg.pat.span),
|
2019-12-24 17:38:22 -05:00
|
|
|
argument_scope,
|
|
|
|
local,
|
|
|
|
DropKind::Value,
|
2018-11-18 14:49:24 +00:00
|
|
|
);
|
|
|
|
|
2019-07-26 19:52:37 -03:00
|
|
|
if let Some(arg) = arg_opt {
|
|
|
|
let pattern = self.hir.pattern_from_hir(&arg.pat);
|
|
|
|
let original_source_scope = self.source_scope;
|
2018-06-27 22:06:54 +01:00
|
|
|
let span = pattern.span;
|
2019-07-26 19:52:37 -03:00
|
|
|
self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span);
|
Avoid unnecessary copies of arguments that are simple bindings
Initially MIR differentiated between arguments and locals, which
introduced a need to add extra copies assigning the argument to a
local, even for simple bindings. This differentiation no longer exists,
but we're still creating those copies, bloating the MIR and LLVM IR we
emit.
Additionally, the current approach means that we create debug info for
both the incoming argument (marking it as an argument), and then
immediately shadow it a local that goes by the same name. This can be
confusing when using e.g. "info args" in gdb, or when e.g. a debugger
with a GUI displays the function arguments separately from the local
variables, especially when the binding is mutable, because the argument
doesn't change, while the local variable does.
2017-10-11 20:49:36 +02:00
|
|
|
match *pattern.kind {
|
|
|
|
// Don't introduce extra copies for simple bindings
|
2019-09-26 18:42:24 +01:00
|
|
|
PatKind::Binding {
|
2019-06-02 19:03:17 +01:00
|
|
|
mutability,
|
|
|
|
var,
|
|
|
|
mode: BindingMode::ByValue,
|
|
|
|
subpattern: None,
|
|
|
|
..
|
|
|
|
} => {
|
Avoid unnecessary copies of arguments that are simple bindings
Initially MIR differentiated between arguments and locals, which
introduced a need to add extra copies assigning the argument to a
local, even for simple bindings. This differentiation no longer exists,
but we're still creating those copies, bloating the MIR and LLVM IR we
emit.
Additionally, the current approach means that we create debug info for
both the incoming argument (marking it as an argument), and then
immediately shadow it a local that goes by the same name. This can be
confusing when using e.g. "info args" in gdb, or when e.g. a debugger
with a GUI displays the function arguments separately from the local
variables, especially when the binding is mutable, because the argument
doesn't change, while the local variable does.
2017-10-11 20:49:36 +02:00
|
|
|
self.local_decls[local].mutability = mutability;
|
2019-07-26 19:52:37 -03:00
|
|
|
self.local_decls[local].source_info.scope = self.source_scope;
|
2019-12-24 17:38:22 -05:00
|
|
|
self.local_decls[local].local_info = if let Some(kind) = self_binding {
|
2020-05-05 23:02:09 -05:00
|
|
|
Some(box LocalInfo::User(ClearCrossCrate::Set(
|
|
|
|
BindingForm::ImplicitSelf(*kind),
|
|
|
|
)))
|
2019-12-24 17:38:22 -05:00
|
|
|
} else {
|
2020-02-25 18:10:34 +01:00
|
|
|
let binding_mode = ty::BindingMode::BindByValue(mutability);
|
2020-05-06 12:29:00 +10:00
|
|
|
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
|
2019-12-24 17:38:22 -05:00
|
|
|
VarBindingForm {
|
|
|
|
binding_mode,
|
|
|
|
opt_ty_info,
|
2020-01-22 16:30:15 +01:00
|
|
|
opt_match_place: Some((Some(place), span)),
|
2019-12-24 17:38:22 -05:00
|
|
|
pat_span: span,
|
|
|
|
},
|
2020-05-06 12:29:00 +10:00
|
|
|
))))
|
2019-12-24 17:38:22 -05:00
|
|
|
};
|
2018-02-26 15:45:13 +01:00
|
|
|
self.var_indices.insert(var, LocalsForNode::One(local));
|
Avoid unnecessary copies of arguments that are simple bindings
Initially MIR differentiated between arguments and locals, which
introduced a need to add extra copies assigning the argument to a
local, even for simple bindings. This differentiation no longer exists,
but we're still creating those copies, bloating the MIR and LLVM IR we
emit.
Additionally, the current approach means that we create debug info for
both the incoming argument (marking it as an argument), and then
immediately shadow it a local that goes by the same name. This can be
confusing when using e.g. "info args" in gdb, or when e.g. a debugger
with a GUI displays the function arguments separately from the local
variables, especially when the binding is mutable, because the argument
doesn't change, while the local variable does.
2017-10-11 20:49:36 +02:00
|
|
|
}
|
|
|
|
_ => {
|
2019-04-02 22:29:28 +01:00
|
|
|
scope = self.declare_bindings(
|
|
|
|
scope,
|
|
|
|
ast_body.span,
|
|
|
|
&pattern,
|
|
|
|
matches::ArmHasGuard(false),
|
|
|
|
Some((Some(&place), span)),
|
|
|
|
);
|
2020-01-11 20:30:42 +00:00
|
|
|
unpack!(block = self.place_into_pattern(block, pattern, place, false));
|
Avoid unnecessary copies of arguments that are simple bindings
Initially MIR differentiated between arguments and locals, which
introduced a need to add extra copies assigning the argument to a
local, even for simple bindings. This differentiation no longer exists,
but we're still creating those copies, bloating the MIR and LLVM IR we
emit.
Additionally, the current approach means that we create debug info for
both the incoming argument (marking it as an argument), and then
immediately shadow it a local that goes by the same name. This can be
confusing when using e.g. "info args" in gdb, or when e.g. a debugger
with a GUI displays the function arguments separately from the local
variables, especially when the binding is mutable, because the argument
doesn't change, while the local variable does.
2017-10-11 20:49:36 +02:00
|
|
|
}
|
|
|
|
}
|
2019-07-26 19:52:37 -03:00
|
|
|
self.source_scope = original_source_scope;
|
2016-04-15 17:11:24 +03:00
|
|
|
}
|
2016-09-25 01:38:27 +02:00
|
|
|
}
|
2016-03-23 12:26:37 -04:00
|
|
|
|
2018-05-28 14:16:09 +03:00
|
|
|
// Enter the argument pattern bindings source scope, if it exists.
|
|
|
|
if let Some(source_scope) = scope {
|
|
|
|
self.source_scope = source_scope;
|
2016-05-31 20:27:36 +03:00
|
|
|
}
|
|
|
|
|
2021-02-24 21:29:09 +01:00
|
|
|
let body = self.hir.mirror_expr(ast_body);
|
|
|
|
self.expr_into_dest(Place::return_place(), block, &body)
|
2015-08-18 17:59:21 -04:00
|
|
|
}
|
2016-01-16 00:36:32 +02:00
|
|
|
|
2019-07-26 19:52:37 -03:00
|
|
|
fn set_correct_source_scope_for_arg(
|
|
|
|
&mut self,
|
|
|
|
arg_hir_id: hir::HirId,
|
|
|
|
original_source_scope: SourceScope,
|
2019-12-24 17:38:22 -05:00
|
|
|
pattern_span: Span,
|
2019-07-26 19:52:37 -03:00
|
|
|
) {
|
|
|
|
let tcx = self.hir.tcx();
|
2019-12-24 17:38:22 -05:00
|
|
|
let current_root = tcx.maybe_lint_level_root_bounded(arg_hir_id, self.hir.root_lint_level);
|
2019-07-26 19:52:37 -03:00
|
|
|
let parent_root = tcx.maybe_lint_level_root_bounded(
|
2019-11-26 22:17:35 +02:00
|
|
|
self.source_scopes[original_source_scope]
|
|
|
|
.local_data
|
2019-11-26 19:55:03 +02:00
|
|
|
.as_ref()
|
|
|
|
.assert_crate_local()
|
|
|
|
.lint_root,
|
2019-07-26 19:52:37 -03:00
|
|
|
self.hir.root_lint_level,
|
|
|
|
);
|
|
|
|
if current_root != parent_root {
|
2019-12-24 17:38:22 -05:00
|
|
|
self.source_scope =
|
|
|
|
self.new_source_scope(pattern_span, LintLevel::Explicit(current_root), None);
|
2019-07-26 19:52:37 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-01 14:31:47 +02:00
|
|
|
fn get_unit_temp(&mut self) -> Place<'tcx> {
|
2016-01-16 00:36:32 +02:00
|
|
|
match self.unit_temp {
|
2020-01-22 16:30:15 +01:00
|
|
|
Some(tmp) => tmp,
|
2016-01-16 00:36:32 +02:00
|
|
|
None => {
|
|
|
|
let ty = self.hir.unit_ty();
|
2017-04-11 23:52:51 +03:00
|
|
|
let fn_span = self.fn_span;
|
|
|
|
let tmp = self.temp(ty, fn_span);
|
2020-01-22 16:30:15 +01:00
|
|
|
self.unit_temp = Some(tmp);
|
2016-01-16 00:36:32 +02:00
|
|
|
tmp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-08-18 17:59:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Builder methods are broken up into modules, depending on what kind
|
2018-05-08 16:10:16 +03:00
|
|
|
// of thing is being lowered. Note that they use the `unpack` macro
|
2015-08-18 17:59:21 -04:00
|
|
|
// above extensively.
|
|
|
|
|
|
|
|
mod block;
|
|
|
|
mod cfg;
|
|
|
|
mod expr;
|
|
|
|
mod matches;
|
|
|
|
mod misc;
|
|
|
|
mod scope;
|