Skip to content
Permalink
Browse files

rustc: dissuade compiler developers from misusing upvar debuginfo.

  • Loading branch information...
eddyb committed Nov 26, 2018
1 parent e6ec968 commit 1525dc2146e3b85123f57e59adcee1908e57013f
@@ -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;
}

0 comments on commit 1525dc2

Please sign in to comment.
You can’t perform that action at this time.