rustc: dissuade compiler developers from misusing upvar debuginfo.
This commit is contained in:
parent
e6ec968485
commit
1525dc2146
4 changed files with 29 additions and 24 deletions
|
|
@ -146,7 +146,11 @@ pub struct Mir<'tcx> {
|
|||
|
||||
/// Names and capture modes of all the closure upvars, assuming
|
||||
/// the first argument is either the closure or a reference to it.
|
||||
pub upvar_decls: Vec<UpvarDecl>,
|
||||
// NOTE(eddyb) This is *strictly* a temporary hack for codegen
|
||||
// debuginfo generation, and will be removed at some point.
|
||||
// Do **NOT** use it for anything else, upvar information should not be
|
||||
// in the MIR, please rely on local crate HIR or other side-channels.
|
||||
pub __upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
|
||||
|
||||
/// Mark this MIR of a const context other than const functions as having converted a `&&` or
|
||||
/// `||` expression into `&` or `|` respectively. This is problematic because if we ever stop
|
||||
|
|
@ -173,7 +177,7 @@ impl<'tcx> Mir<'tcx> {
|
|||
local_decls: LocalDecls<'tcx>,
|
||||
user_type_annotations: CanonicalUserTypeAnnotations<'tcx>,
|
||||
arg_count: usize,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
__upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
|
||||
span: Span,
|
||||
control_flow_destroyed: Vec<(Span, String)>,
|
||||
) -> Self {
|
||||
|
|
@ -197,7 +201,7 @@ impl<'tcx> Mir<'tcx> {
|
|||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
__upvar_debuginfo_codegen_only_do_not_use,
|
||||
spread_arg: None,
|
||||
span,
|
||||
cache: cache::Cache::new(),
|
||||
|
|
@ -431,7 +435,7 @@ impl_stable_hash_for!(struct Mir<'tcx> {
|
|||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
__upvar_debuginfo_codegen_only_do_not_use,
|
||||
spread_arg,
|
||||
control_flow_destroyed,
|
||||
span,
|
||||
|
|
@ -983,7 +987,7 @@ impl<'tcx> LocalDecl<'tcx> {
|
|||
|
||||
/// A closure capture, with its name and mode.
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub struct UpvarDecl {
|
||||
pub struct UpvarDebuginfo {
|
||||
pub debug_name: Name,
|
||||
|
||||
/// If true, the capture is behind a reference.
|
||||
|
|
@ -3151,7 +3155,7 @@ CloneTypeFoldableAndLiftImpls! {
|
|||
MirPhase,
|
||||
Mutability,
|
||||
SourceInfo,
|
||||
UpvarDecl,
|
||||
UpvarDebuginfo,
|
||||
FakeReadCause,
|
||||
RetagKind,
|
||||
SourceScope,
|
||||
|
|
@ -3173,7 +3177,7 @@ BraceStructTypeFoldableImpl! {
|
|||
local_decls,
|
||||
user_type_annotations,
|
||||
arg_count,
|
||||
upvar_decls,
|
||||
__upvar_debuginfo_codegen_only_do_not_use,
|
||||
spread_arg,
|
||||
control_flow_destroyed,
|
||||
span,
|
||||
|
|
|
|||
|
|
@ -598,9 +598,10 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
tmp
|
||||
}
|
||||
};
|
||||
let upvar_debuginfo = &mir.__upvar_debuginfo_codegen_only_do_not_use;
|
||||
arg_scope.map(|scope| {
|
||||
// Is this a regular argument?
|
||||
if arg_index > 0 || mir.upvar_decls.is_empty() {
|
||||
if arg_index > 0 || upvar_debuginfo.is_empty() {
|
||||
// The Rust ABI passes indirect variables using a pointer and a manual copy, so we
|
||||
// need to insert a deref here, but the C ABI uses a pointer and a copy using the
|
||||
// byval attribute, for which LLVM always does the deref itself,
|
||||
|
|
@ -638,16 +639,16 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
let (def_id, upvar_substs) = match closure_layout.ty.sty {
|
||||
ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)),
|
||||
ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)),
|
||||
_ => bug!("upvar_decls with non-closure arg0 type `{}`", closure_layout.ty)
|
||||
_ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty)
|
||||
};
|
||||
let upvar_tys = upvar_substs.upvar_tys(def_id, tcx);
|
||||
|
||||
let extra_locals = {
|
||||
let upvars = mir.upvar_decls
|
||||
let upvars = upvar_debuginfo
|
||||
.iter()
|
||||
.zip(upvar_tys)
|
||||
.enumerate()
|
||||
.map(|(i, (decl, ty))| (i, decl.debug_name, decl.by_ref, ty));
|
||||
.map(|(i, (upvar, ty))| (i, upvar.debug_name, upvar.by_ref, ty));
|
||||
|
||||
let generator_fields = mir.generator_layout.as_ref().map(|generator_layout| {
|
||||
let (def_id, gen_substs) = match closure_layout.ty.sty {
|
||||
|
|
@ -656,7 +657,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
};
|
||||
let state_tys = gen_substs.state_tys(def_id, tcx);
|
||||
|
||||
let upvar_count = mir.upvar_decls.len();
|
||||
let upvar_count = upvar_debuginfo.len();
|
||||
generator_layout.fields
|
||||
.iter()
|
||||
.zip(state_tys)
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
|||
var_indices: HirIdMap<LocalsForNode>,
|
||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||
canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
__upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
|
||||
upvar_mutbls: Vec<Mutability>,
|
||||
unit_temp: Option<Place<'tcx>>,
|
||||
|
||||
|
|
@ -631,7 +631,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
// closure and we stored in a map called upvar_list in TypeckTables indexed
|
||||
// with the closure's DefId. Here, we run through that vec of UpvarIds for
|
||||
// the given closure and use the necessary information to create UpvarDecl.
|
||||
let upvar_decls: Vec<_> = hir_tables
|
||||
let upvar_debuginfo: Vec<_> = hir_tables
|
||||
.upvar_list
|
||||
.get(&fn_def_id)
|
||||
.into_iter()
|
||||
|
|
@ -644,14 +644,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
ty::UpvarCapture::ByValue => false,
|
||||
ty::UpvarCapture::ByRef(..) => true,
|
||||
};
|
||||
let mut decl = UpvarDecl {
|
||||
let mut debuginfo = UpvarDebuginfo {
|
||||
debug_name: keywords::Invalid.name(),
|
||||
by_ref,
|
||||
};
|
||||
let mut mutability = Mutability::Not;
|
||||
if let Some(Node::Binding(pat)) = tcx_hir.find(var_node_id) {
|
||||
if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
|
||||
decl.debug_name = ident.name;
|
||||
debuginfo.debug_name = ident.name;
|
||||
if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) {
|
||||
if bm == ty::BindByValue(hir::MutMutable) {
|
||||
mutability = Mutability::Mut;
|
||||
|
|
@ -664,7 +664,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
upvar_mutbls.push(mutability);
|
||||
decl
|
||||
debuginfo
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
@ -674,7 +674,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
|||
safety,
|
||||
return_ty,
|
||||
return_ty_span,
|
||||
upvar_decls,
|
||||
upvar_debuginfo,
|
||||
upvar_mutbls);
|
||||
|
||||
let call_site_scope = region::Scope {
|
||||
|
|
@ -778,7 +778,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
safety: Safety,
|
||||
return_ty: Ty<'tcx>,
|
||||
return_span: Span,
|
||||
upvar_decls: Vec<UpvarDecl>,
|
||||
__upvar_debuginfo_codegen_only_do_not_use: Vec<UpvarDebuginfo>,
|
||||
upvar_mutbls: Vec<Mutability>)
|
||||
-> Builder<'a, 'gcx, 'tcx> {
|
||||
let lint_level = LintLevel::Explicit(hir.root_lint_level);
|
||||
|
|
@ -801,7 +801,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
1,
|
||||
),
|
||||
canonical_user_type_annotations: IndexVec::new(),
|
||||
upvar_decls,
|
||||
__upvar_debuginfo_codegen_only_do_not_use,
|
||||
upvar_mutbls,
|
||||
var_indices: Default::default(),
|
||||
unit_temp: None,
|
||||
|
|
@ -837,7 +837,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
self.local_decls,
|
||||
self.canonical_user_type_annotations,
|
||||
self.arg_count,
|
||||
self.upvar_decls,
|
||||
self.__upvar_debuginfo_codegen_only_do_not_use,
|
||||
self.fn_span,
|
||||
self.hir.control_flow_destroyed(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -222,10 +222,10 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
|
|||
debug!("should_inline({:?})", callsite);
|
||||
let tcx = self.tcx;
|
||||
|
||||
// Don't inline closures that have captures
|
||||
// Don't inline closures that have capture debuginfo
|
||||
// FIXME: Handle closures better
|
||||
if callee_mir.upvar_decls.len() > 0 {
|
||||
debug!(" upvar decls present - not inlining");
|
||||
if callee_mir.__upvar_debuginfo_codegen_only_do_not_use.len() > 0 {
|
||||
debug!(" upvar debuginfo present - not inlining");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue