From 1525dc2146e3b85123f57e59adcee1908e57013f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 26 Nov 2018 21:40:05 +0200 Subject: [PATCH] rustc: dissuade compiler developers from misusing upvar debuginfo. --- src/librustc/mir/mod.rs | 18 +++++++++++------- src/librustc_codegen_ssa/mir/mod.rs | 11 ++++++----- src/librustc_mir/build/mod.rs | 18 +++++++++--------- src/librustc_mir/transform/inline.rs | 6 +++--- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 7c432c9c7eb2..bf2a1eaafd66 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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, + // 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, /// 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 @@ pub fn new( local_decls: LocalDecls<'tcx>, user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, arg_count: usize, - upvar_decls: Vec, + __upvar_debuginfo_codegen_only_do_not_use: Vec, span: Span, control_flow_destroyed: Vec<(Span, String)>, ) -> Self { @@ -197,7 +201,7 @@ pub fn new( 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 @@ pub enum Safety { 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 @@ pub fn new_return_place(return_ty: Ty<'_>, span: Span) -> LocalDecl<'_> { /// 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 @@ pub enum ClosureOutlivesSubject<'tcx> { MirPhase, Mutability, SourceInfo, - UpvarDecl, + UpvarDebuginfo, FakeReadCause, RetagKind, SourceScope, @@ -3173,7 +3177,7 @@ impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> { local_decls, user_type_annotations, arg_count, - upvar_decls, + __upvar_debuginfo_codegen_only_do_not_use, spread_arg, control_flow_destroyed, span, diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index c9a6ff1a0c04..621c4e5d4488 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -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) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index cd2fa10927f6..79e1d5daae19 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -375,7 +375,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { var_indices: HirIdMap, local_decls: IndexVec>, canonical_user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, - upvar_decls: Vec, + __upvar_debuginfo_codegen_only_do_not_use: Vec, upvar_mutbls: Vec, unit_temp: Option>, @@ -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 @@ fn new(hir: Cx<'a, 'gcx, 'tcx>, safety: Safety, return_ty: Ty<'tcx>, return_span: Span, - upvar_decls: Vec, + __upvar_debuginfo_codegen_only_do_not_use: Vec, upvar_mutbls: Vec) -> Builder<'a, 'gcx, 'tcx> { let lint_level = LintLevel::Explicit(hir.root_lint_level); @@ -801,7 +801,7 @@ fn new(hir: Cx<'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 @@ fn finish(self, 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(), ) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 027ae70b06a1..e96a40ad2f03 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -222,10 +222,10 @@ fn should_inline(&self, 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; }