rust/compiler/rustc_mir_build/src/build/mod.rs

1007 lines
36 KiB
Rust
Raw Normal View History

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};
use rustc_attr::{self as attr, UnwindAttr};
use rustc_errors::ErrorReported;
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::lang_items::LangItem;
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;
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;
use rustc_span::Span;
2019-12-24 17:38:22 -05:00
use rustc_target::spec::abi::Abi;
use rustc_target::spec::PanicStrategy;
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) {
return tcx.mir_built(def);
2020-07-06 23:49:53 +02: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)
}
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<'_> {
let id = tcx.hir().local_def_id_to_hir_id(def.did);
// Figure out what primary body this item has.
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
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, _, _), .. }) => {
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
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),
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
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),
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
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)),
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
2020-08-12 17:02:14 -04:00
span,
2019-12-24 17:38:22 -05:00
..
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
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))
}
Node::Item(hir::Item {
kind: hir::ItemKind::Static(ty, _, body_id) | hir::ItemKind::Const(ty, body_id),
..
})
| 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)),
..
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
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)
}
2020-07-06 23:49:53 +02:00
_ => span_bug!(tcx.hir().span(id), "can't build MIR for {:?}", def.did),
};
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
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));
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 {
build::construct_error(cx, body_id)
} else if cx.body_owner_kind.is_fn_or_closure() {
// 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];
let fn_def_id = tcx.hir().local_def_id(id);
let safety = match fn_sig.unsafety {
hir::Unsafety::Normal => Safety::Safe,
hir::Unsafety::Unsafe => Safety::FnUnsafe,
};
let body = tcx.hir().body(body_id);
let ty = tcx.type_of(fn_def_id);
let mut abi = fn_sig.abi;
2020-08-03 00:49:11 +02:00
let implicit_argument = match ty.kind() {
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;
vec![ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)]
2016-12-26 14:34:03 +01:00
}
ty::Generator(..) => {
2020-07-17 08:47:04 +00:00
let gen_ty = tcx.typeck_body(body_id).node_type(id);
// 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.
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),
]
} else {
vec![ArgInfo(gen_ty, None, None, None)]
}
2016-12-26 14:34:03 +01:00
}
_ => vec![],
};
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,
}
2019-12-24 17:38:22 -05:00
} else {
None
};
} else {
opt_ty_info = None;
self_arg = None;
}
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() {
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-12-24 17:38:22 -05:00
ArgInfo(ty, opt_ty_info, Some(&arg), self_arg)
});
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
2017-07-05 14:57:26 -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() {
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-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
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,
);
2021-01-17 13:27:05 +01:00
if yield_ty.is_some() {
mir.generator.as_mut().unwrap().yield_ty = yield_ty;
}
mir
} else {
// 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);
build::construct_const(cx, body_id, return_ty, return_ty_span)
};
lints::check(tcx, &body);
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,
);
body
})
}
///////////////////////////////////////////////////////////////////////////
// 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<'_>,
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);
2020-08-03 00:49:11 +02:00
let (closure_def_id, closure_substs) = match *closure_ty.kind() {
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),
};
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)
}
#[derive(Debug, PartialEq, Eq)]
enum BlockFrame {
/// Evaluation is currently within a statement.
///
/// Examples include:
/// 1. `EXPR;`
/// 2. `let _ = EXPR;`
/// 3. `let x = EXPR;`
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,
},
/// 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,
/// `Span` of the tail expression.
span: Span,
},
/// 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,
}
}
fn is_statement(&self) -> bool {
match *self {
BlockFrame::Statement { .. } => true,
2019-12-24 17:38:22 -05:00
BlockFrame::TailExpr { .. } | BlockFrame::SubExpr => false,
}
}
2019-12-24 17:38:22 -05:00
}
#[derive(Debug)]
struct BlockContext(Vec<BlockFrame>);
struct Builder<'a, 'tcx> {
hir: Cx<'a, 'tcx>,
cfg: CFG<'tcx>,
2016-03-09 11:04:26 -05:00
def_id: DefId,
fn_span: Span,
arg_count: usize,
2019-11-25 12:58:40 +00:00
generator_kind: Option<GeneratorKind>,
2019-02-08 14:53:55 +01:00
/// The current set of scopes, updated as we traverse;
/// see the `scope` module for more details.
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,
/// 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
/// 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`.
block_context: BlockContext,
/// The current unsafe block in scope, even if it is hidden by
2019-02-08 14:53:55 +01:00
/// a `PushUnsafeBlock`.
unpushed_unsafe: Safety,
2019-02-08 14:53:55 +01:00
/// The number of `push_unsafe_block` levels in scope.
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.
source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
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
/// a match arm, we push onto this stack, and then pop when we
/// finish building it.
guard_context: Vec<GuardFrame>,
/// Maps `HirId`s of variable bindings to the `Local`s created for them.
/// (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>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
upvar_mutbls: Vec<Mutability>,
2017-12-01 14:31:47 +02:00
unit_temp: Option<Place<'tcx>>,
var_debug_info: Vec<VarDebugInfo<'tcx>>,
2015-08-18 17:59:21 -04: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 {
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 {
self.var_indices[&id].local_id(for_guard)
}
}
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()
}
2019-02-08 14:53:55 +01:00
/// Traverses the frames on the `BlockContext`, searching for either
/// 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,
&BlockFrame::TailExpr { tail_result_is_ignored, span } => {
return Some(BlockTailInfo { tail_result_is_ignored, span });
2019-12-24 17:38:22 -05:00
}
}
}
None
}
/// 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.
Some(
BlockFrame::TailExpr { tail_result_is_ignored: ignored, .. }
| BlockFrame::Statement { ignores_expr_result: ignored },
) => *ignored,
}
}
}
#[derive(Debug)]
enum LocalsForNode {
/// In the usual case, a `HirId` for an identifier maps to at most
2019-02-08 14:53:55 +01:00
/// one `Local` declaration.
One(Local),
/// The exceptional case is identifiers in a match arm's pattern
/// that are referenced in a guard of that match arm. For these,
/// we have `2` Locals.
///
/// * `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`).
ForGuard { ref_for_guard: Local, for_arm_body: Local },
}
#[derive(Debug)]
struct GuardFrameLocal {
2019-03-07 12:18:59 +01:00
id: hir::HirId,
}
impl GuardFrameLocal {
2019-03-07 12:18:59 +01:00
fn new(id: hir::HirId, _binding_mode: BindingMode) -> Self {
GuardFrameLocal { id }
}
}
#[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.
locals: Vec<GuardFrameLocal>,
}
2019-02-08 14:53:55 +01:00
/// `ForGuard` indicates whether we are talking about:
/// 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.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum ForGuard {
RefWithinGuard,
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
}
2019-12-24 17:38:22 -05:00
(&LocalsForNode::One(_), ForGuard::RefWithinGuard) => {
bug!("anything with one local should never be within a guard.")
}
}
}
}
struct CFG<'tcx> {
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
2015-08-18 17:59:21 -04:00
}
rustc_index::newtype_index! {
struct ScopeId { .. }
}
2015-08-18 17:59:21 -04: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
#[must_use = "if you don't use one of these results, you're leaving a dangling edge"]
struct BlockAnd<T>(BasicBlock, T);
2015-08-18 17:59:21 -04: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
}
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.
let attrs = &tcx.get_attrs(fn_def_id.to_def_id());
let unwind_attr = attr::find_unwind_attr(&tcx.sess, attrs);
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;
}
// This is a special case: some functions have a C abi but are meant to
// unwind anyway. Don't stop them.
match unwind_attr {
2019-10-12 20:48:19 +02:00
None => false, // FIXME(#58794); should be `!(abi == Abi::Rust || abi == Abi::RustCall)`
Some(UnwindAttr::Allowed) => false,
Some(UnwindAttr::Aborts) => true,
}
}
2015-08-18 17:59:21 -04: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>,
);
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,
) -> Body<'tcx>
where
2019-12-24 17:38:22 -05:00
A: Iterator<Item = ArgInfo<'tcx>>,
{
let arguments: Vec<_> = arguments.collect();
let tcx = hir.tcx();
let tcx_hir = tcx.hir();
let span = tcx_hir.span(fn_id);
let fn_def_id = tcx_hir.local_def_id(fn_id);
2019-12-24 17:38:22 -05:00
let mut builder = Builder::new(
hir,
fn_def_id.to_def_id(),
Use smaller def span for functions Currently, the def span of a funtion encompasses the entire function signature and body. However, this is usually unnecessarily verbose - when we are pointing at an entire function in a diagnostic, we almost always want to point at the signature. The actual contents of the body tends to be irrelevant to the diagnostic we are emitting, and just takes up additional screen space. This commit changes the `def_span` of all function items (freestanding functions, `impl`-block methods, and `trait`-block methods) to be the span of the signature. For example, the function ```rust pub fn foo<T>(val: T) -> T { val } ``` now has a `def_span` corresponding to `pub fn foo<T>(val: T) -> T` (everything before the opening curly brace). Trait methods without a body have a `def_span` which includes the trailing semicolon. For example: ```rust trait Foo { fn bar(); }``` the function definition `Foo::bar` has a `def_span` of `fn bar();` This makes our diagnostic output much shorter, and emphasizes information that is relevant to whatever diagnostic we are reporting. We continue to use the full span (including the body) in a few of places: * MIR building uses the full span when building source scopes. * 'Outlives suggestions' use the full span to sort the diagnostics being emitted. * The `#[rustc_on_unimplemented(enclosing_scope="in this scope")]` attribute points the entire scope body. * The 'unconditional recursion' lint uses the full span to show additional context for the recursive call. All of these cases work only with local items, so we don't need to add anything extra to crate metadata.
2020-08-12 17:02:14 -04:00
span_with_body,
2017-07-11 12:57:05 -07:00
arguments.len(),
safety,
return_ty,
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 };
let source_info = builder.source_info(span);
2017-09-13 22:33:07 +03:00
let call_site_s = (call_site_scope, source_info);
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();
let return_block =
unpack!(builder.in_breakable_scope(None, Place::return_place(), fn_end, |builder| {
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,
)
}))
}));
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()
}));
let spread_arg = if abi == Abi::RustCall {
// RustCall pseudo-ABI untuples the last argument.
Some(Local::new(arguments.len()))
} else {
None
};
debug!("fn_id {:?} has attrs {:?}", fn_def_id, tcx.get_attrs(fn_def_id.to_def_id()));
let mut body = builder.finish();
body.spread_arg = spread_arg;
body
2015-08-18 17:59:21 -04:00
}
fn construct_const<'a, 'tcx>(
hir: Cx<'a, 'tcx>,
body_id: hir::BodyId,
const_ty: Ty<'tcx>,
const_ty_span: Span,
) -> Body<'tcx> {
let tcx = hir.tcx();
let owner_id = tcx.hir().body_owner(body_id);
let def_id = tcx.hir().local_def_id(owner_id);
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);
let mut block = START_BLOCK;
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));
let source_info = builder.source_info(span);
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
builder.build_drop_trees(false);
builder.finish()
}
/// 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> {
let tcx = hir.tcx();
let owner_id = tcx.hir().body_owner(body_id);
let def_id = tcx.hir().local_def_id(owner_id);
let span = tcx.hir().span(owner_id);
let ty = tcx.ty_error();
2021-01-17 13:27:05 +01:00
let generator_kind = tcx.hir().body(body_id).generator_kind;
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() {
// 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,
);
let source_info = builder.source_info(span);
// Some MIR passes will expect the number of parameters to match the
// function declaration.
for _ in 0..num_params {
builder.local_decls.push(LocalDecl::with_source_info(ty, source_info));
}
builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
let mut body = builder.finish();
2021-01-17 13:27:05 +01:00
body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty));
body
}
impl<'a, 'tcx> Builder<'a, 'tcx> {
2019-12-24 17:38:22 -05:00
fn new(
hir: Cx<'a, 'tcx>,
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);
let mut builder = Builder {
hir,
def_id,
cfg: CFG { basic_blocks: IndexVec::new() },
fn_span: span,
arg_count,
2019-11-25 12:58:40 +00:00
generator_kind,
scopes: scope::Scopes::new(),
block_context: BlockContext::new(),
source_scopes: IndexVec::new(),
source_scope: OUTERMOST_SOURCE_SCOPE,
guard_context: vec![],
push_unsafe_count: 0,
unpushed_unsafe: safety,
local_decls: IndexVec::from_elem_n(LocalDecl::new(return_ty, return_span), 1),
canonical_user_type_annotations: IndexVec::new(),
upvar_mutbls: vec![],
var_indices: Default::default(),
unit_temp: None,
var_debug_info: vec![],
};
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
2017-09-13 22:33:07 +03:00
assert_eq!(
builder.new_source_scope(span, lint_level, Some(safety)),
2019-12-24 17:38:22 -05:00
OUTERMOST_SOURCE_SCOPE
);
builder.source_scopes[OUTERMOST_SOURCE_SCOPE].parent_scope = None;
builder
}
fn finish(self) -> Body<'tcx> {
for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
if block.terminator.is_none() {
span_bug!(self.fn_span, "no terminator on block {:?}", index);
}
}
Body::new(
MirSource::item(self.def_id),
2018-11-24 14:38:31 +01:00
self.cfg.basic_blocks,
self.source_scopes,
self.local_decls,
self.canonical_user_type_annotations,
2018-11-24 14:38:31 +01:00
self.arg_count,
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,
)
}
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<()> {
// 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));
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 let Some(arg) = arg_opt {
if let Some(ident) = arg.pat.simple_ident() {
self.var_debug_info.push(VarDebugInfo {
name: ident.name,
source_info,
value: VarDebugInfoContents::Place(arg_local.into()),
});
}
}
}
let tcx = self.hir.tcx();
let tcx_hir = tcx.hir();
2020-07-17 08:47:04 +00:00
let hir_typeck_results = self.hir.typeck_results();
// 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
// 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`.
if hir_typeck_results.closure_min_captures.get(&fn_def_id).is_some() {
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() {
closure_env_projs.push(ProjectionElem::Deref);
closure_ty = ty;
}
2020-08-03 00:49:11 +02:00
let upvar_substs = match closure_ty.kind() {
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),
};
let capture_tys = upvar_substs.upvar_tys();
let captures_with_tys =
hir_typeck_results.closure_min_captures_flattened(fn_def_id).zip(capture_tys);
self.upvar_mutbls = captures_with_tys
2019-12-24 17:38:22 -05:00
.enumerate()
.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,
_ => bug!("Expected an upvar"),
};
2019-12-24 17:38:22 -05:00
let mutability = captured_place.mutability;
// FIXME(project-rfc-2229#8): Store more precise information
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;
}
}
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 {
ty::UpvarCapture::ByValue(_) => {}
2019-12-24 17:38:22 -05:00
ty::UpvarCapture::ByRef(..) => {
projs.push(ProjectionElem::Deref);
}
};
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)),
value: VarDebugInfoContents::Place(Place {
local: closure_env_arg,
2019-12-24 17:38:22 -05:00
projection: tcx.intern_place_elems(&projs),
}),
2019-12-24 17:38:22 -05:00
});
2019-12-24 17:38:22 -05:00
mutability
})
.collect();
}
let mut scope = None;
// Bind the argument patterns
for (index, arg_info) in arguments.iter().enumerate() {
// Function arguments always get the first Local indices after the return place
let local = Local::new(index + 1);
let place = Place::from(local);
let &ArgInfo(_, opt_ty_info, arg_opt, ref self_binding) = arg_info;
// 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,
);
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;
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);
match *pattern.kind {
// Don't introduce extra copies for simple bindings
PatKind::Binding {
mutability,
var,
mode: BindingMode::ByValue,
subpattern: None,
..
} => {
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 {
Some(box LocalInfo::User(ClearCrossCrate::Set(
BindingForm::ImplicitSelf(*kind),
)))
2019-12-24 17:38:22 -05:00
} else {
let binding_mode = ty::BindingMode::BindByValue(mutability);
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
2019-12-24 17:38:22 -05:00
VarBindingForm {
binding_mode,
opt_ty_info,
opt_match_place: Some((Some(place), span)),
2019-12-24 17:38:22 -05:00
pat_span: span,
},
))))
2019-12-24 17:38:22 -05:00
};
self.var_indices.insert(var, LocalsForNode::One(local));
}
_ => {
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));
}
}
2019-07-26 19:52:37 -03:00
self.source_scope = original_source_scope;
}
}
// Enter the argument pattern bindings source scope, if it exists.
if let Some(source_scope) = scope {
self.source_scope = source_scope;
}
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
}
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(
self.source_scopes[original_source_scope]
.local_data
.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> {
match self.unit_temp {
Some(tmp) => tmp,
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);
self.unit_temp = Some(tmp);
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;