diff --git a/Cargo.lock b/Cargo.lock index 2275e96da2fd7..b3427cd98ff6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3818,6 +3818,7 @@ version = "0.0.0" dependencies = [ "rustc_ast", "rustc_ast_pretty", + "rustc_data_structures", "rustc_hir", "rustc_span", "rustc_target", diff --git a/compiler/rustc_ast/src/ptr.rs b/compiler/rustc_ast/src/ptr.rs index 89a0857992e49..3738c96380d5a 100644 --- a/compiler/rustc_ast/src/ptr.rs +++ b/compiler/rustc_ast/src/ptr.rs @@ -21,23 +21,36 @@ //! implementation changes (using a special thread-local heap, for example). //! Moreover, a switch to, e.g., `P<'a, T>` would be easy and mostly automated. +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; + use std::fmt::{self, Debug, Display}; use std::iter::FromIterator; +use std::mem::ManuallyDrop; use std::ops::{Deref, DerefMut}; use std::{slice, vec}; -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; - -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; /// An owned smart pointer. pub struct P { - ptr: Box, + ptr: ManuallyDrop>, } /// Construct a `P` from a `T` value. #[allow(non_snake_case)] pub fn P(value: T) -> P { - P { ptr: Box::new(value) } + P::from_box(Box::new(value)) +} + +impl P { + const fn from_box(ptr: Box) -> P { + P { ptr: ManuallyDrop::new(ptr) } + } + + fn into_box(self) -> Box { + let mut this = ManuallyDrop::new(self); + unsafe { ManuallyDrop::take(&mut this.ptr) } + } } impl P { @@ -47,32 +60,38 @@ impl P { where F: FnOnce(T) -> U, { - f(*self.ptr) + f(*self.into_box()) } /// Equivalent to `and_then(|x| x)`. pub fn into_inner(self) -> T { - *self.ptr + *self.into_box() } /// Produce a new `P` from `self` without reallocating. - pub fn map(mut self, f: F) -> P + pub fn map(self, f: F) -> P where F: FnOnce(T) -> T, { - let x = f(*self.ptr); - *self.ptr = x; - - self + let mut ptr = self.into_box(); + *ptr = f(*ptr); + P::from_box(ptr) } /// Optionally produce a new `P` from `self` without reallocating. - pub fn filter_map(mut self, f: F) -> Option> + pub fn filter_map(self, f: F) -> Option> where F: FnOnce(T) -> Option, { - *self.ptr = f(*self.ptr)?; - Some(self) + let mut ptr = self.into_box(); + *ptr = f(*ptr)?; + Some(P::from_box(ptr)) + } +} + +impl Drop for P { + fn drop(&mut self) { + ensure_sufficient_stack(|| unsafe { ManuallyDrop::drop(&mut self.ptr) }); } } @@ -98,7 +117,7 @@ impl Clone for P { impl Debug for P { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - Debug::fmt(&self.ptr, f) + Debug::fmt(&*self.ptr, f) } } @@ -110,7 +129,7 @@ impl Display for P { impl fmt::Pointer for P { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Pointer::fmt(&self.ptr, f) + fmt::Pointer::fmt(&*self.ptr, f) } } @@ -128,17 +147,17 @@ impl> Encodable for P { impl P<[T]> { pub const fn new() -> P<[T]> { - P { ptr: Box::default() } + P::from_box(Box::default()) } #[inline(never)] pub fn from_vec(v: Vec) -> P<[T]> { - P { ptr: v.into_boxed_slice() } + P::from_box(v.into_boxed_slice()) } #[inline(never)] pub fn into_vec(self) -> Vec { - self.ptr.into_vec() + self.into_box().into_vec() } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index e08ba73e0ae31..9506201fd2f49 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -16,6 +16,7 @@ use crate::ast::*; use crate::token; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::Span; @@ -411,7 +412,7 @@ pub fn walk_pat_field<'a, V: Visitor<'a>>(visitor: &mut V, fp: &'a PatField) { } pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { - match typ.kind { + ensure_sufficient_stack(|| match typ.kind { TyKind::Slice(ref ty) | TyKind::Paren(ref ty) => visitor.visit_ty(ty), TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty), TyKind::Rptr(ref opt_lifetime, ref mutable_type) => { @@ -445,7 +446,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err => {} TyKind::MacCall(ref mac) => visitor.visit_mac_call(mac), TyKind::Never | TyKind::CVarArgs => {} - } + }) } pub fn walk_path<'a, V: Visitor<'a>>(visitor: &mut V, path: &'a Path) { @@ -721,7 +722,7 @@ pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) { } pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { - match statement.kind { + ensure_sufficient_stack(|| match statement.kind { StmtKind::Local(ref local) => visitor.visit_local(local), StmtKind::Item(ref item) => visitor.visit_item(item), StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr), @@ -733,7 +734,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { visitor.visit_attribute(attr); } } - } + }) } pub fn walk_mac<'a, V: Visitor<'a>>(visitor: &mut V, mac: &'a MacCall) { @@ -773,7 +774,7 @@ pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineA pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { walk_list!(visitor, visit_attribute, expression.attrs.iter()); - match expression.kind { + ensure_sufficient_stack(|| match expression.kind { ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression), ExprKind::Array(ref subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); @@ -902,7 +903,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Try(ref subexpression) => visitor.visit_expr(subexpression), ExprKind::TryBlock(ref body) => visitor.visit_block(body), ExprKind::Lit(_) | ExprKind::Err => {} - } + }); visitor.visit_expr_post(expression) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 97ed9c708b458..11911b2bd8d5a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -48,6 +48,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_hir as hir; @@ -1166,13 +1167,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_, 'hir>) -> hir::Ty<'hir> { - let kind = match t.kind { - TyKind::Infer => hir::TyKind::Infer, - TyKind::Err => hir::TyKind::Err, - TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), - TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), - TyKind::Rptr(ref region, ref mt) => { - let region = region.unwrap_or_else(|| { + ensure_sufficient_stack(|| { + let kind = match t.kind { + TyKind::Infer => hir::TyKind::Infer, + TyKind::Err => hir::TyKind::Err, + TyKind::Slice(ref ty) => hir::TyKind::Slice(self.lower_ty(ty, itctx)), + TyKind::Ptr(ref mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), + TyKind::Rptr(ref region, ref mt) => { + let region = region.unwrap_or_else(|| { let Some(LifetimeRes::ElidedAnchor { start, end }) = self.resolver.get_lifetime_res(t.id) else { panic!() }; @@ -1183,56 +1185,53 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { id: start, } }); - let lifetime = self.lower_lifetime(®ion); - hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) - } - TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| { - hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy { - generic_params: this.lower_generic_params( - &f.generic_params, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - ), - unsafety: this.lower_unsafety(f.unsafety), - abi: this.lower_extern(f.ext), - decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), - param_names: this.lower_fn_params_to_names(&f.decl), - })) - }), - TyKind::Never => hir::TyKind::Never, - TyKind::Tup(ref tys) => { - hir::TyKind::Tup(self.arena.alloc_from_iter( + let lifetime = self.lower_lifetime(®ion); + hir::TyKind::Rptr(lifetime, self.lower_mt(mt, itctx)) + } + TyKind::BareFn(ref f) => self.with_lifetime_binder(t.id, |this| { + hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy { + generic_params: this.lower_generic_params( + &f.generic_params, + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + ), + unsafety: this.lower_unsafety(f.unsafety), + abi: this.lower_extern(f.ext), + decl: this.lower_fn_decl(&f.decl, None, FnDeclKind::Pointer, None), + param_names: this.lower_fn_params_to_names(&f.decl), + })) + }), + TyKind::Never => hir::TyKind::Never, + TyKind::Tup(ref tys) => hir::TyKind::Tup(self.arena.alloc_from_iter( tys.iter().map(|ty| self.lower_ty_direct(ty, itctx.reborrow())), - )) - } - TyKind::Paren(ref ty) => { - return self.lower_ty_direct(ty, itctx); - } - TyKind::Path(ref qself, ref path) => { - return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx); - } - TyKind::ImplicitSelf => { - let res = self.expect_full_res(t.id); - let res = self.lower_res(res); - hir::TyKind::Path(hir::QPath::Resolved( - None, - self.arena.alloc(hir::Path { - res, - segments: arena_vec![self; hir::PathSegment::from_ident( - Ident::with_dummy_span(kw::SelfUpper) - )], - span: self.lower_span(t.span), - }), - )) - } - TyKind::Array(ref ty, ref length) => { - hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) - } - TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), - TyKind::TraitObject(ref bounds, kind) => { - let mut lifetime_bound = None; - let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { - let bounds = - this.arena.alloc_from_iter(bounds.iter().filter_map( + )), + TyKind::Paren(ref ty) => { + return self.lower_ty_direct(ty, itctx); + } + TyKind::Path(ref qself, ref path) => { + return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx); + } + TyKind::ImplicitSelf => { + let res = self.expect_full_res(t.id); + let res = self.lower_res(res); + hir::TyKind::Path(hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + res, + segments: arena_vec![self; hir::PathSegment::from_ident( + Ident::with_dummy_span(kw::SelfUpper) + )], + span: self.lower_span(t.span), + }), + )) + } + TyKind::Array(ref ty, ref length) => { + hir::TyKind::Array(self.lower_ty(ty, itctx), self.lower_array_length(length)) + } + TyKind::Typeof(ref expr) => hir::TyKind::Typeof(self.lower_anon_const(expr)), + TyKind::TraitObject(ref bounds, kind) => { + let mut lifetime_bound = None; + let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { + let bounds = this.arena.alloc_from_iter(bounds.iter().filter_map( |bound| match *bound { GenericBound::Trait( ref ty, @@ -1252,48 +1251,51 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } }, )); - let lifetime_bound = - lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); - (bounds, lifetime_bound) - }); - hir::TyKind::TraitObject(bounds, lifetime_bound, kind) - } - TyKind::ImplTrait(def_node_id, ref bounds) => { - let span = t.span; - match itctx { - ImplTraitContext::ReturnPositionOpaqueTy { origin } => self - .lower_opaque_impl_trait(span, origin, def_node_id, |this| { - this.lower_param_bounds(bounds, itctx) - }), - ImplTraitContext::TypeAliasesOpaqueTy => { - let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; - self.lower_opaque_impl_trait( - span, - hir::OpaqueTyOrigin::TyAlias, - def_node_id, - |this| this.lower_param_bounds(bounds, nested_itctx), - ) - } - ImplTraitContext::Universal(in_band_ty_params, parent_def_id) => { - // Add a definition for the in-band `Param`. - let def_id = self.resolver.local_def_id(def_node_id); + let lifetime_bound = + lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); + (bounds, lifetime_bound) + }); + hir::TyKind::TraitObject(bounds, lifetime_bound, kind) + } + TyKind::ImplTrait(def_node_id, ref bounds) => { + let span = t.span; + match itctx { + ImplTraitContext::ReturnPositionOpaqueTy { origin } => self + .lower_opaque_impl_trait(span, origin, def_node_id, |this| { + this.lower_param_bounds(bounds, itctx) + }), + ImplTraitContext::TypeAliasesOpaqueTy => { + let nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy; + self.lower_opaque_impl_trait( + span, + hir::OpaqueTyOrigin::TyAlias, + def_node_id, + |this| this.lower_param_bounds(bounds, nested_itctx), + ) + } + ImplTraitContext::Universal(in_band_ty_params, parent_def_id) => { + // Add a definition for the in-band `Param`. + let def_id = self.resolver.local_def_id(def_node_id); - let hir_bounds = self.lower_param_bounds( - bounds, - ImplTraitContext::Universal(in_band_ty_params, parent_def_id), - ); - // Set the name to `impl Bound1 + Bound2`. - let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); - in_band_ty_params.push(hir::GenericParam { - hir_id: self.lower_node_id(def_node_id), - name: ParamName::Plain(self.lower_ident(ident)), - pure_wrt_drop: false, - bounds: hir_bounds, - span: self.lower_span(span), - kind: hir::GenericParamKind::Type { default: None, synthetic: true }, - }); + let hir_bounds = self.lower_param_bounds( + bounds, + ImplTraitContext::Universal(in_band_ty_params, parent_def_id), + ); + // Set the name to `impl Bound1 + Bound2`. + let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); + in_band_ty_params.push(hir::GenericParam { + hir_id: self.lower_node_id(def_node_id), + name: ParamName::Plain(self.lower_ident(ident)), + pure_wrt_drop: false, + bounds: hir_bounds, + span: self.lower_span(span), + kind: hir::GenericParamKind::Type { + default: None, + synthetic: true, + }, + }); - hir::TyKind::Path(hir::QPath::Resolved( + hir::TyKind::Path(hir::QPath::Resolved( None, self.arena.alloc(hir::Path { span: self.lower_span(span), @@ -1301,31 +1303,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { segments: arena_vec![self; hir::PathSegment::from_ident(self.lower_ident(ident))], }), )) - } - ImplTraitContext::Disallowed(position) => { - let mut err = struct_span_err!( - self.sess, - t.span, - E0562, - "`impl Trait` only allowed in function and inherent method return types, not in {}", - position - ); - err.emit(); - hir::TyKind::Err + } + ImplTraitContext::Disallowed(position) => { + let mut err = struct_span_err!( + self.sess, + t.span, + E0562, + "`impl Trait` only allowed in function and inherent method return types, not in {}", + position + ); + err.emit(); + hir::TyKind::Err + } } } - } - TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), - TyKind::CVarArgs => { - self.sess.delay_span_bug( - t.span, - "`TyKind::CVarArgs` should have been handled elsewhere", - ); - hir::TyKind::Err - } - }; + TyKind::MacCall(_) => panic!("`TyKind::MacCall` should have been expanded by now"), + TyKind::CVarArgs => { + self.sess.delay_span_bug( + t.span, + "`TyKind::CVarArgs` should have been handled elsewhere", + ); + hir::TyKind::Err + } + }; - hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } + hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } + }) } #[tracing::instrument(level = "debug", skip(self, lower_bounds))] diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 058a0f975a7b3..a363f7fdc3a97 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -13,6 +13,7 @@ use rustc_ast::walk_list; use rustc_ast::*; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{error_code, pluralize, struct_span_err, Applicability}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ @@ -215,7 +216,7 @@ impl<'a> AstValidator<'a> { // Mirrors `visit::walk_ty`, but tracks relevant state. fn walk_ty(&mut self, t: &'a Ty) { - match t.kind { + ensure_sufficient_stack(|| match t.kind { TyKind::ImplTrait(..) => { self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)) } @@ -254,7 +255,7 @@ impl<'a> AstValidator<'a> { } } _ => visit::walk_ty(self, t), - } + }) } fn visit_struct_field_def(&mut self, field: &'a FieldDef) { diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 99e30531c226f..dc7c5dcbc7e67 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -19,6 +19,7 @@ use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_data_structures::stack::ensure_recursive_stack; use rustc_errors::{FatalError, Handler, Level}; use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_middle::bug; @@ -757,6 +758,13 @@ pub(crate) unsafe fn codegen( create_msvc_imps(cgcx, llcx, llmod); } + let stack_size = crate::debuginfo::LLMOD_DEPTHS + .lock() + .unwrap() + .get(&(llmod as *const _ as usize)) + .unwrap_or(&0) + * 256; + // A codegen-specific pass manager is used to generate object // files for an LLVM module. // @@ -769,6 +777,7 @@ pub(crate) unsafe fn codegen( tm: &'ll llvm::TargetMachine, llmod: &'ll llvm::Module, no_builtins: bool, + stack_size: usize, f: F, ) -> R where @@ -777,7 +786,7 @@ pub(crate) unsafe fn codegen( let cpm = llvm::LLVMCreatePassManager(); llvm::LLVMAddAnalysisPasses(tm, cpm); llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); - f(cpm) + ensure_recursive_stack(stack_size, || f(cpm)) } // Two things to note: @@ -881,7 +890,7 @@ pub(crate) unsafe fn codegen( } else { llmod }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, config.no_builtins, stack_size, |cpm| { write_output_file( diag_handler, tm, @@ -916,7 +925,7 @@ pub(crate) unsafe fn codegen( (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()), }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { + with_codegen(tm, llmod, config.no_builtins, stack_size, |cpm| { write_output_file( diag_handler, tm, diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 76caa3ceaafae..ef002e857aa40 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -1,5 +1,5 @@ use super::metadata::file_metadata; -use super::utils::DIB; +use super::utils::{self, DIB}; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; use rustc_codegen_ssa::traits::*; @@ -97,15 +97,19 @@ fn make_mir_scope<'ll, 'tcx>( let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); cx.dbg_scope_fn(callee, callee_fn_abi, None) } - None => unsafe { - llvm::LLVMRustDIBuilderCreateLexicalBlock( - DIB(cx), - parent_scope.dbg_scope.unwrap(), - file_metadata, - loc.line, - loc.col, - ) - }, + None => { + let dbg_scope = unsafe { + llvm::LLVMRustDIBuilderCreateLexicalBlock( + DIB(cx), + parent_scope.dbg_scope.unwrap(), + file_metadata, + loc.line, + loc.col, + ) + }; + utils::debug_context(cx).add_di_node(dbg_scope); + dbg_scope + } }; let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index f2cf3b1ef5c1e..50be7bb103084 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -24,6 +24,7 @@ use cstr::cstr; use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo; use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind; use rustc_codegen_ssa::traits::*; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -135,10 +136,10 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>( let upper_bound = len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong; - let subrange = - unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) }; + let subrange = unsafe { llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound) }; + debug_context(cx).add_di_node(subrange); - let subscripts = create_DIArray(DIB(cx), &[subrange]); + let subscripts = create_DIArray(cx, &[Some(subrange)]); let di_node = unsafe { llvm::LLVMRustDIBuilderCreateArrayType( DIB(cx), @@ -148,6 +149,7 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>( subscripts, ) }; + debug_context(cx).add_di_node(di_node); DINodeCreationResult::new(di_node, false) } @@ -203,6 +205,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( ptr_type_debuginfo_name.len(), ) }; + debug_context(cx).add_di_node(di_node); DINodeCreationResult { di_node, already_stored_in_typemap: false } } @@ -254,6 +257,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>( 0, ) }; + debug_context(cx).add_di_node(data_ptr_type_di_node); smallvec![ build_field_di_node( @@ -331,9 +335,10 @@ fn build_subroutine_type_di_node<'ll, 'tcx>( let fn_di_node = unsafe { llvm::LLVMRustDIBuilderCreateSubroutineType( DIB(cx), - create_DIArray(DIB(cx), &signature_di_nodes[..]), + create_DIArray(cx, &signature_di_nodes[..]), ) }; + debug_context(cx).add_nested_di_node(fn_di_node, &[3]); // This is actually a function pointer, so wrap it in pointer DI. let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false); @@ -348,6 +353,7 @@ fn build_subroutine_type_di_node<'ll, 'tcx>( name.len(), ) }; + debug_context(cx).add_di_node(di_node); DINodeCreationResult::new(di_node, false) } @@ -435,67 +441,69 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D debug!("type_di_node: {:?}", t); - let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() { - ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { - build_basic_type_di_node(cx, t) - } - ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t), - ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t), - ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id), - ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id), - ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id), - ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => { - build_pointer_or_reference_di_node(cx, t, pointee_type, unique_type_id) - } - // Box may have a non-ZST allocator A. In that case, we - // cannot treat Box as just an owned alias of `*mut T`. - ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { - build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id) - } - ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id), - ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id), - ty::Generator(..) => enums::build_generator_di_node(cx, unique_type_id), - ty::Adt(def, ..) => match def.adt_kind() { - AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id), - AdtKind::Union => build_union_type_di_node(cx, unique_type_id), - AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id), - }, - ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), - // Type parameters from polymorphized functions. - ty::Param(_) => build_param_type_di_node(cx, t), - _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), - }; - - { - if already_stored_in_typemap { - // Make sure that we really do have a `TypeMap` entry for the unique type ID. - let di_node_for_uid = - match debug_context(cx).type_map.di_node_for_unique_id(unique_type_id) { - Some(di_node) => di_node, - None => { - bug!( - "expected type debuginfo node for unique \ + ensure_sufficient_stack(|| { + let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() { + ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { + build_basic_type_di_node(cx, t) + } + ty::Tuple(elements) if elements.is_empty() => build_basic_type_di_node(cx, t), + ty::Array(..) => build_fixed_size_array_di_node(cx, unique_type_id, t), + ty::Slice(_) | ty::Str => build_slice_type_di_node(cx, t, unique_type_id), + ty::Dynamic(..) => build_dyn_type_di_node(cx, t, unique_type_id), + ty::Foreign(..) => build_foreign_type_di_node(cx, t, unique_type_id), + ty::RawPtr(ty::TypeAndMut { ty: pointee_type, .. }) | ty::Ref(_, pointee_type, _) => { + build_pointer_or_reference_di_node(cx, t, pointee_type, unique_type_id) + } + // Box may have a non-ZST allocator A. In that case, we + // cannot treat Box as just an owned alias of `*mut T`. + ty::Adt(def, substs) if def.is_box() && cx.layout_of(substs.type_at(1)).is_zst() => { + build_pointer_or_reference_di_node(cx, t, t.boxed_ty(), unique_type_id) + } + ty::FnDef(..) | ty::FnPtr(_) => build_subroutine_type_di_node(cx, unique_type_id), + ty::Closure(..) => build_closure_env_di_node(cx, unique_type_id), + ty::Generator(..) => enums::build_generator_di_node(cx, unique_type_id), + ty::Adt(def, ..) => match def.adt_kind() { + AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id), + AdtKind::Union => build_union_type_di_node(cx, unique_type_id), + AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id), + }, + ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id), + // Type parameters from polymorphized functions. + ty::Param(_) => build_param_type_di_node(cx, t), + _ => bug!("debuginfo: unexpected type in type_di_node(): {:?}", t), + }; + + { + if already_stored_in_typemap { + // Make sure that we really do have a `TypeMap` entry for the unique type ID. + let di_node_for_uid = + match debug_context(cx).type_map.di_node_for_unique_id(unique_type_id) { + Some(di_node) => di_node, + None => { + bug!( + "expected type debuginfo node for unique \ type ID '{:?}' to already be in \ the `debuginfo::TypeMap` but it \ was not.", - unique_type_id, - ); - } - }; + unique_type_id, + ); + } + }; - debug_assert_eq!(di_node_for_uid as *const _, di_node as *const _); - } else { - debug_context(cx).type_map.insert(unique_type_id, di_node); + debug_assert_eq!(di_node_for_uid as *const _, di_node as *const _); + } else { + debug_context(cx).type_map.insert(unique_type_id, di_node); + } } - } - di_node + di_node + }) } // FIXME(mw): Cache this via a regular UniqueTypeId instead of an extra field in the debug context. fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll DIType { *debug_context(cx).recursion_marker_type.get_or_init(move || { - unsafe { + let di_node = unsafe { // The choice of type here is pretty arbitrary - // anything reading the debuginfo for a recursive // type is going to see *something* weird - the only @@ -514,7 +522,9 @@ fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll D cx.tcx.data_layout.pointer_size.bits(), DW_ATE_unsigned, ) - } + }; + debug_context(cx).add_di_node(di_node); + di_node }) } @@ -592,6 +602,7 @@ fn file_metadata_raw<'ll>( hash_value.len(), ) }; + debug_context(cx).add_di_node(file_metadata); v.insert(file_metadata); file_metadata @@ -677,6 +688,7 @@ fn build_basic_type_di_node<'ll, 'tcx>( encoding, ) }; + debug_context(cx).add_di_node(ty_di_node); if !cpp_like_debuginfo { return DINodeCreationResult::new(ty_di_node, false); @@ -700,6 +712,7 @@ fn build_basic_type_di_node<'ll, 'tcx>( None, ) }; + debug_context(cx).add_di_node(typedef_di_node); DINodeCreationResult::new(typedef_di_node, false) } @@ -737,18 +750,17 @@ fn build_param_type_di_node<'ll, 'tcx>( ) -> DINodeCreationResult<'ll> { debug!("build_param_type_di_node: {:?}", t); let name = format!("{:?}", t); - DINodeCreationResult { - di_node: unsafe { - llvm::LLVMRustDIBuilderCreateBasicType( - DIB(cx), - name.as_ptr().cast(), - name.len(), - Size::ZERO.bits(), - DW_ATE_unsigned, - ) - }, - already_stored_in_typemap: false, - } + let di_node = unsafe { + llvm::LLVMRustDIBuilderCreateBasicType( + DIB(cx), + name.as_ptr().cast(), + name.len(), + Size::ZERO.bits(), + DW_ATE_unsigned, + ) + }; + debug_context(cx).add_di_node(di_node); + DINodeCreationResult { di_node, already_stored_in_typemap: false } } pub fn build_compile_unit_di_node<'ll, 'tcx>( @@ -835,6 +847,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( ptr::null(), 0, ); + debug_context.add_di_node(compile_unit_file); let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( debug_context.builder, @@ -854,6 +867,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( 0, tcx.sess.opts.debugging_opts.split_dwarf_inlining, ); + debug_context.add_di_node(unit_metadata); if tcx.sess.opts.debugging_opts.profile { let cu_desc_metadata = @@ -921,7 +935,7 @@ fn build_field_di_node<'ll, 'tcx>( flags: DIFlags, type_di_node: &'ll DIType, ) -> &'ll DIType { - unsafe { + let di_node = unsafe { llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), owner, @@ -935,7 +949,9 @@ fn build_field_di_node<'ll, 'tcx>( flags, type_di_node, ) - } + }; + debug_context(cx).add_di_node(di_node); + di_node } /// Creates the debuginfo node for a Rust struct type. Maybe be a regular struct or a tuple-struct. @@ -1254,7 +1270,7 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_di_node = type_di_node(cx, actual_type); let name = name.as_str(); - Some(unsafe { + let template_param = unsafe { llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), None, @@ -1262,7 +1278,9 @@ fn build_generic_type_param_di_nodes<'ll, 'tcx>( name.len(), actual_type_di_node, ) - }) + }; + debug_context(cx).add_di_node(template_param); + Some(template_param) } else { None } @@ -1323,7 +1341,7 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo let global_align = cx.align_of(variable_type); - unsafe { + let di_node = unsafe { llvm::LLVMRustDIBuilderCreateStaticVariable( DIB(cx), Some(var_scope), @@ -1338,8 +1356,9 @@ pub fn build_global_var_di_node<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, glo global, None, global_align.bytes() as u32, - ); - } + ) + }; + debug_context(cx).add_nested_di_node(di_node, &[0, 1]); } /// Generates LLVM debuginfo for a vtable. @@ -1464,7 +1483,7 @@ pub fn create_vtable_di_node<'ll, 'tcx>( let vtable_type_di_node = build_vtable_type_di_node(cx, ty, poly_trait_ref); let linkage_name = ""; - unsafe { + let di_node = unsafe { llvm::LLVMRustDIBuilderCreateStaticVariable( DIB(cx), NO_SCOPE_METADATA, @@ -1479,8 +1498,9 @@ pub fn create_vtable_di_node<'ll, 'tcx>( vtable, None, 0, - ); - } + ) + }; + debug_context(cx).add_nested_di_node(di_node, &[0, 1]); } /// Creates an "extension" of an existing `DIScope` into another file. @@ -1490,7 +1510,11 @@ pub fn extend_scope_to_file<'ll>( file: &SourceFile, ) -> &'ll DILexicalBlock { let file_metadata = file_metadata(cx, file); - unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) } + let di_node = unsafe { + llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) + }; + debug_context(cx).add_di_node(di_node); + di_node } pub fn tuple_field_name(field_index: usize) -> Cow<'static, str> { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs index d6e2c8ccdf44a..9d803bb148f53 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs @@ -27,7 +27,7 @@ use crate::{ unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA, UNKNOWN_LINE_NUMBER, }, - utils::DIB, + utils::{debug_context, DIB}, }, llvm::{ self, @@ -441,7 +441,7 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( // We use LLVMRustDIBuilderCreateMemberType() member type directly because // the build_field_di_node() function does not support specifying a source location, // which is something that we don't do anywhere else. - unsafe { + let member_type_di_node = unsafe { llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), enum_type_di_node, @@ -458,7 +458,9 @@ fn build_union_fields_for_direct_tag_enum_or_generator<'ll, 'tcx>( DIFlags::FlagZero, variant_member_info.variant_struct_type_di_node, ) - } + }; + debug_context(cx).add_di_node(member_type_di_node); + member_type_di_node })); debug_assert_eq!( diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 73e01d0453b25..7d56a9a0a890c 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -26,7 +26,7 @@ use crate::{ type_map::{self, Stub}, unknown_file_metadata, UNKNOWN_LINE_NUMBER, }, - utils::{create_DIArray, get_namespace_for_item, DIB}, + utils::{create_DIArray, debug_context, get_namespace_for_item, DIB}, }, llvm::{ self, @@ -163,22 +163,24 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( let enumerator_di_nodes: SmallVec> = variants .map(|(discr, variant_name)| { - unsafe { - Some(llvm::LLVMRustDIBuilderCreateEnumerator( + let enumerator_di_node = unsafe { + llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), variant_name.as_ptr().cast(), variant_name.len(), // FIXME: what if enumeration has i128 discriminant? discr.val as i64, is_unsigned, - )) - } + ) + }; + debug_context(cx).add_di_node(enumerator_di_node); + Some(enumerator_di_node) }) .collect(); let (size, align) = cx.size_and_align_of(base_type); - unsafe { + let di_node = unsafe { llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), containing_scope, @@ -188,11 +190,13 @@ fn build_enumeration_type_di_node<'ll, 'tcx>( UNKNOWN_LINE_NUMBER, size.bits(), align.bits() as u32, - create_DIArray(DIB(cx), &enumerator_di_nodes[..]), + create_DIArray(cx, &enumerator_di_nodes[..]), type_di_node(cx, base_type), true, ) - } + }; + debug_context(cx).add_di_node(di_node); + di_node } /// Build the debuginfo node for the struct type describing a single variant of an enum. diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index f1935e0ec31af..bbbd5695268f8 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -11,7 +11,7 @@ use crate::{ unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, UNKNOWN_LINE_NUMBER, }, - utils::{create_DIArray, get_namespace_for_item, DIB}, + utils::{create_DIArray, debug_context, get_namespace_for_item, DIB}, }, llvm::{ self, @@ -243,28 +243,29 @@ fn build_enum_variant_part_di_node<'ll, 'tcx>( let variant_part_unique_type_id = UniqueTypeId::for_enum_variant_part(cx.tcx, enum_type_and_layout.ty); - let stub = StubInfo::new( - cx, - variant_part_unique_type_id, - |cx, variant_part_unique_type_id_str| unsafe { - let variant_part_name = ""; - llvm::LLVMRustDIBuilderCreateVariantPart( - DIB(cx), - enum_type_di_node, - variant_part_name.as_ptr().cast(), - variant_part_name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, - enum_type_and_layout.size.bits(), - enum_type_and_layout.align.abi.bits() as u32, - DIFlags::FlagZero, - tag_member_di_node, - create_DIArray(DIB(cx), &[]), - variant_part_unique_type_id_str.as_ptr().cast(), - variant_part_unique_type_id_str.len(), - ) - }, - ); + let stub = + StubInfo::new(cx, variant_part_unique_type_id, |cx, variant_part_unique_type_id_str| { + let variant_part_di_node = unsafe { + let variant_part_name = ""; + llvm::LLVMRustDIBuilderCreateVariantPart( + DIB(cx), + enum_type_di_node, + variant_part_name.as_ptr().cast(), + variant_part_name.len(), + unknown_file_metadata(cx), + UNKNOWN_LINE_NUMBER, + enum_type_and_layout.size.bits(), + enum_type_and_layout.align.abi.bits() as u32, + DIFlags::FlagZero, + tag_member_di_node, + create_DIArray(cx, &[]), + variant_part_unique_type_id_str.as_ptr().cast(), + variant_part_unique_type_id_str.len(), + ) + }; + debug_context(cx).add_di_node(variant_part_di_node); + variant_part_di_node + }); type_map::build_type_with_children( cx, @@ -330,8 +331,8 @@ fn build_discr_member_di_node<'ll, 'tcx>( let tag_base_type = tag_base_type(cx, enum_or_generator_type_and_layout); let (size, align) = cx.size_and_align_of(tag_base_type); - unsafe { - Some(llvm::LLVMRustDIBuilderCreateMemberType( + let di_node = unsafe { + llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), containing_scope, tag_name.as_ptr().cast(), @@ -343,8 +344,10 @@ fn build_discr_member_di_node<'ll, 'tcx>( enum_or_generator_type_and_layout.fields.offset(tag_field).bits(), DIFlags::FlagArtificial, type_di_node(cx, tag_base_type), - )) - } + ) + }; + debug_context(cx).add_di_node(di_node); + Some(di_node) } } } @@ -402,7 +405,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>( .source_info .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)); - unsafe { + let di_node = unsafe { llvm::LLVMRustDIBuilderCreateVariantMemberType( DIB(cx), variant_part_di_node, @@ -417,7 +420,9 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>( DIFlags::FlagZero, variant_member_info.variant_struct_type_di_node, ) - } + }; + debug_context(cx).add_di_node(di_node); + di_node } /// Information needed for building a `DW_TAG_variant`: diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs index 87fbb737ea8a9..3df11a9dc95c2 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/type_map.rs @@ -175,7 +175,7 @@ pub(super) fn stub<'ll, 'tcx>( containing_scope: Option<&'ll DIScope>, flags: DIFlags, ) -> StubInfo<'ll, 'tcx> { - let empty_array = create_DIArray(DIB(cx), &[]); + let empty_array = create_DIArray(cx, &[]); let unique_type_id_str = unique_type_id.generate_unique_id_string(cx.tcx); let metadata = match kind { @@ -222,6 +222,7 @@ pub(super) fn stub<'ll, 'tcx>( ) }, }; + debug_context(cx).add_di_node(metadata); StubInfo { metadata, unique_type_id } } @@ -251,8 +252,8 @@ pub(super) fn build_type_with_children<'ll, 'tcx>( if !(members.is_empty() && generics.is_empty()) { unsafe { - let members_array = create_DIArray(DIB(cx), &members[..]); - let generics_array = create_DIArray(DIB(cx), &generics[..]); + let members_array = create_DIArray(cx, &members[..]); + let generics_array = create_DIArray(cx, &generics[..]); llvm::LLVMRustDICompositeTypeReplaceArrays( DIB(cx), stub_info.metadata, @@ -260,6 +261,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>( Some(generics_array), ); } + debug_context(cx).add_di_node(stub_info.metadata); } DINodeCreationResult { di_node: stub_info.metadata, already_stored_in_typemap: true } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 4e6d3f88e6719..9e67a38a79d77 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -5,7 +5,7 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use self::metadata::{file_metadata, type_di_node}; use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER}; use self::namespace::mangled_name_of_instance; -use self::utils::{create_DIArray, is_node_local_to_unit, DIB}; +use self::utils::{create_DIArray, debug_context, is_node_local_to_unit, DIB}; use crate::abi::FnAbi; use crate::builder::Builder; @@ -38,7 +38,8 @@ use libc::c_uint; use smallvec::SmallVec; use std::cell::RefCell; use std::iter; -use std::lazy::OnceCell; +use std::lazy::{OnceCell, SyncLazy}; +use std::sync::Mutex; use tracing::debug; mod create_scope_map; @@ -56,6 +57,8 @@ const DW_TAG_auto_variable: c_uint = 0x100; #[allow(non_upper_case_globals)] const DW_TAG_arg_variable: c_uint = 0x101; +pub static LLMOD_DEPTHS: SyncLazy>> = SyncLazy::new(Default::default); + /// A context object for maintaining all state needed by the debuginfo module. pub struct CodegenUnitDebugContext<'ll, 'tcx> { llcontext: &'ll llvm::Context, @@ -66,6 +69,7 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> { type_map: metadata::TypeMap<'ll, 'tcx>, namespace_map: RefCell>, recursion_marker_type: OnceCell<&'ll DIType>, + depth_map: RefCell>, } impl Drop for CodegenUnitDebugContext<'_, '_> { @@ -90,6 +94,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { type_map: Default::default(), namespace_map: RefCell::new(Default::default()), recursion_marker_type: OnceCell::new(), + depth_map: Default::default(), } } @@ -132,6 +137,47 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { ); } } + + pub fn add_di_node(&self, di_node: &'ll llvm::Metadata) { + self.add_nested_di_node(di_node, &[]) + } + + pub fn add_nested_di_node(&self, di_node: &'ll llvm::Metadata, indices: &[usize]) { + let di_node_as_llval = unsafe { llvm::LLVMRustMetadataAsValue(self.llcontext, di_node) }; + let num_operands = unsafe { llvm::LLVMGetMDNodeNumOperands(di_node_as_llval) as usize }; + let mut operands = Vec::with_capacity(num_operands); + unsafe { + llvm::LLVMGetMDNodeOperands(di_node_as_llval, operands.as_mut_ptr()); + operands.set_len(num_operands); + } + for &index in indices { + if let Some(operand) = operands[index] { + let operand = unsafe { + assert!(llvm::LLVMIsAMDNode(operand).is_some()); + llvm::LLVMValueAsMetadata(operand) + }; + self.add_di_node(operand); + } + } + let mut depth_map = self.depth_map.borrow_mut(); + let node_depth = operands + .into_iter() + .flatten() + .filter_map(|operand| unsafe { llvm::LLVMIsAMDNode(operand) }) + .map(|operand| { + let operand = unsafe { llvm::LLVMValueAsMetadata(operand) }; + depth_map[&operand] + 1 + }) + .max() + .unwrap_or(1); + depth_map.insert(di_node, node_depth); + LLMOD_DEPTHS + .lock() + .unwrap() + .entry(self.llmod as *const _ as usize) + .and_modify(|depth| *depth = (*depth).max(node_depth)) + .or_insert(node_depth); + } } /// Creates any deferred debug metadata nodes @@ -326,6 +372,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let fn_signature = get_function_signature(self, fn_abi); llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature) }; + debug_context(self).add_nested_di_node(function_type_metadata, &[3]); let mut name = String::new(); type_names::push_item_name(tcx, def_id, false, &mut name); @@ -373,8 +420,8 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } - unsafe { - return llvm::LLVMRustDIBuilderCreateFunction( + let function_metadata = unsafe { + llvm::LLVMRustDIBuilderCreateFunction( DIB(self), containing_scope, name.as_ptr().cast(), @@ -390,15 +437,17 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { maybe_definition_llfn, template_parameters, None, - ); - } + ) + }; + debug_context(self).add_nested_di_node(function_metadata, &[7]); + return function_metadata; fn get_function_signature<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, ) -> &'ll DIArray { if cx.sess().opts.debuginfo == DebugInfo::Limited { - return create_DIArray(DIB(cx), &[]); + return create_DIArray(cx, &[]); } let mut signature = Vec::with_capacity(fn_abi.args.len() + 1); @@ -439,7 +488,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { .extend(fn_abi.args.iter().map(|arg| Some(type_di_node(cx, arg.layout.ty)))); } - create_DIArray(DIB(cx), &signature[..]) + create_DIArray(cx, &signature[..]) } fn get_template_parameters<'ll, 'tcx>( @@ -448,7 +497,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { substs: SubstsRef<'tcx>, ) -> &'ll DIArray { if substs.types().next().is_none() { - return create_DIArray(DIB(cx), &[]); + return create_DIArray(cx, &[]); } // Again, only create type information if full debuginfo is enabled @@ -461,15 +510,17 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_di_node(cx, actual_type); let name = name.as_str(); - Some(unsafe { - Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( + let template_param = unsafe { + llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), None, name.as_ptr().cast(), name.len(), actual_type_metadata, - )) - }) + ) + }; + debug_context(cx).add_di_node(template_param); + Some(Some(template_param)) } else { None } @@ -479,7 +530,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { vec![] }; - create_DIArray(DIB(cx), &template_params) + create_DIArray(cx, &template_params) } fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec { @@ -552,7 +603,10 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { ) -> &'ll DILocation { let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo()); - unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) } + let dbg_loc = + unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) }; + debug_context(self).add_di_node(dbg_loc); + dbg_loc } fn create_vtable_debuginfo( @@ -598,7 +652,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let align = self.align_of(variable_type); let name = variable_name.as_str(); - unsafe { + let dbg_var = unsafe { llvm::LLVMRustDIBuilderCreateVariable( DIB(self), dwarf_tag, @@ -613,6 +667,8 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { argument_index, align.bytes() as u32, ) - } + }; + debug_context(self).add_di_node(dbg_var); + dbg_var } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs index d5ea48c311b94..d2c7e4f1dec91 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs @@ -42,6 +42,7 @@ pub fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DISco false, // ExportSymbols (only relevant for C++ anonymous namespaces) ) }; + debug_context(cx).add_di_node(scope); debug_context(cx).namespace_map.borrow_mut().insert(def_id, scope); scope diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs index fe9851cfa5612..645d8e4b594b5 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs @@ -26,10 +26,13 @@ pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool { #[allow(non_snake_case)] pub fn create_DIArray<'ll>( - builder: &DIBuilder<'ll>, + cx: &CodegenCx<'ll, '_>, arr: &[Option<&'ll DIDescriptor>], ) -> &'ll DIArray { - unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) } + let di_array = + unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(DIB(cx), arr.as_ptr(), arr.len() as u32) }; + debug_context(cx).add_di_node(di_array); + di_array } #[inline] diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 13baaddccd4df..648ba07fd014f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1075,6 +1075,7 @@ extern "C" { pub fn LLVMGetUndef(Ty: &Type) -> &Value; // Operations on metadata + pub fn LLVMIsAMDNode(Val: &Value) -> Option<&Value>; pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value; pub fn LLVMMDNodeInContext<'a>( C: &'a Context, @@ -1082,6 +1083,8 @@ extern "C" { Count: c_uint, ) -> &'a Value; pub fn LLVMAddNamedMetadataOperand<'a>(M: &'a Module, Name: *const c_char, Val: &'a Value); + pub fn LLVMGetMDNodeNumOperands(V: &Value) -> c_uint; + pub fn LLVMGetMDNodeOperands<'a>(V: &'a Value, Dest: *mut Option<&'a Value>); // Operations on scalar constants pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 862805236311d..4598db6cbbd21 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -3,6 +3,7 @@ use crate::context::TypeLowering; use crate::llvm_util::get_version; use crate::type_::Type; use rustc_codegen_ssa::traits::*; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::bug; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; @@ -226,72 +227,74 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { /// of that field's type - this is useful for taking the address of /// that field and ensuring the struct has the right alignment. fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { - if let Abi::Scalar(scalar) = self.abi { - // Use a different cache for scalars because pointers to DSTs - // can be either fat or thin (data pointers of fat pointers). - if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) { + ensure_sufficient_stack(|| { + if let Abi::Scalar(scalar) = self.abi { + // Use a different cache for scalars because pointers to DSTs + // can be either fat or thin (data pointers of fat pointers). + if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) { + return llty; + } + let llty = match *self.ty.kind() { + ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { + cx.type_ptr_to(cx.layout_of(ty).llvm_type(cx)) + } + ty::Adt(def, _) if def.is_box() => { + cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx)) + } + ty::FnPtr(sig) => { + cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty())) + } + _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO), + }; + cx.scalar_lltypes.borrow_mut().insert(self.ty, llty); return llty; } - let llty = match *self.ty.kind() { - ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { - cx.type_ptr_to(cx.layout_of(ty).llvm_type(cx)) - } - ty::Adt(def, _) if def.is_box() => { - cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx)) - } - ty::FnPtr(sig) => { - cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty())) - } - _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO), - }; - cx.scalar_lltypes.borrow_mut().insert(self.ty, llty); - return llty; - } - - // Check the cache. - let variant_index = match self.variants { - Variants::Single { index } => Some(index), - _ => None, - }; - if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) { - return llty.lltype; - } - debug!("llvm_type({:#?})", self); + // Check the cache. + let variant_index = match self.variants { + Variants::Single { index } => Some(index), + _ => None, + }; + if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) { + return llty.lltype; + } - assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty); + debug!("llvm_type({:#?})", self); - // Make sure lifetimes are erased, to avoid generating distinct LLVM - // types for Rust types that only differ in the choice of lifetimes. - let normal_ty = cx.tcx.erase_regions(self.ty); + assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty); - let mut defer = None; - let mut field_remapping = None; - let llty = if self.ty != normal_ty { - let mut layout = cx.layout_of(normal_ty); - if let Some(v) = variant_index { - layout = layout.for_variant(cx, v); - } - layout.llvm_type(cx) - } else { - uncached_llvm_type(cx, *self, &mut defer, &mut field_remapping) - }; - debug!("--> mapped {:#?} to llty={:?}", self, llty); + // Make sure lifetimes are erased, to avoid generating distinct LLVM + // types for Rust types that only differ in the choice of lifetimes. + let normal_ty = cx.tcx.erase_regions(self.ty); - cx.type_lowering - .borrow_mut() - .insert((self.ty, variant_index), TypeLowering { lltype: llty, field_remapping }); + let mut defer = None; + let mut field_remapping = None; + let llty = if self.ty != normal_ty { + let mut layout = cx.layout_of(normal_ty); + if let Some(v) = variant_index { + layout = layout.for_variant(cx, v); + } + layout.llvm_type(cx) + } else { + uncached_llvm_type(cx, *self, &mut defer, &mut field_remapping) + }; + debug!("--> mapped {:#?} to llty={:?}", self, llty); - if let Some((llty, layout)) = defer { - let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout); - cx.set_struct_body(llty, &llfields, packed); cx.type_lowering .borrow_mut() - .get_mut(&(self.ty, variant_index)) - .unwrap() - .field_remapping = new_field_remapping; - } - llty + .insert((self.ty, variant_index), TypeLowering { lltype: llty, field_remapping }); + + if let Some((llty, layout)) = defer { + let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout); + cx.set_struct_body(llty, &llfields, packed); + cx.type_lowering + .borrow_mut() + .get_mut(&(self.ty, variant_index)) + .unwrap() + .field_remapping = new_field_remapping; + } + llty + }) } fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index ae43464791d23..a61cce6a9bf51 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -13,6 +13,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Mutability}; @@ -57,7 +58,7 @@ fn push_debuginfo_type_name<'tcx>( // .natvis visualizers (and perhaps other existing native debuggers?) let cpp_like_debuginfo = cpp_like_debuginfo(tcx); - match *t.kind() { + ensure_sufficient_stack(|| match *t.kind() { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), @@ -424,7 +425,7 @@ fn push_debuginfo_type_name<'tcx>( t ); } - } + }); /// MSVC names enums differently than other platforms so that the debugging visualization // format (natvis) is able to understand enums and render the active variant correctly in the diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index faea2111d9210..2d41fe458f5cd 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -12,6 +12,7 @@ //! initialization and can otherwise silence errors, if //! move analysis runs after promotion on broken MIR. +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_middle::mir::traversal::ReversePostorder; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -926,7 +927,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { if self.is_temp_kind(*local) { - *local = self.promote_temp(*local); + *local = ensure_sufficient_stack(|| self.promote_temp(*local)); } } } diff --git a/compiler/rustc_data_structures/src/stack.rs b/compiler/rustc_data_structures/src/stack.rs index 3bdd67512321b..6a7661a925370 100644 --- a/compiler/rustc_data_structures/src/stack.rs +++ b/compiler/rustc_data_structures/src/stack.rs @@ -16,3 +16,8 @@ const STACK_PER_RECURSION: usize = 1 * 1024 * 1024; // 1MB pub fn ensure_sufficient_stack(f: impl FnOnce() -> R) -> R { stacker::maybe_grow(RED_ZONE, STACK_PER_RECURSION, f) } + +pub fn ensure_recursive_stack(stack_size: usize, f: impl FnOnce() -> R) -> R { + let full_size = stack_size + RED_ZONE; + stacker::maybe_grow(full_size, full_size, f) +} diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 59bd46ae353b2..9f20ef8d6e18e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -35,6 +35,7 @@ use crate::hir::*; use crate::itemlikevisit::{ItemLikeVisitor, ParItemLikeVisitor}; use rustc_ast::walk_list; use rustc_ast::{Attribute, Label}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::Span; @@ -707,7 +708,7 @@ pub fn walk_variant<'v, V: Visitor<'v>>( pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { visitor.visit_id(typ.hir_id); - match typ.kind { + ensure_sufficient_stack(|| match typ.kind { TyKind::Slice(ref ty) => visitor.visit_ty(ty), TyKind::Ptr(ref mutable_type) => visitor.visit_ty(&mutable_type.ty), TyKind::Rptr(ref lifetime, ref mutable_type) => { @@ -741,7 +742,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) { } TyKind::Typeof(ref expression) => visitor.visit_anon_const(expression), TyKind::Infer | TyKind::Err => {} - } + }) } pub fn walk_inf<'v, V: Visitor<'v>>(visitor: &mut V, inf: &'v InferArg) { @@ -1119,7 +1120,7 @@ pub fn walk_let_expr<'v, V: Visitor<'v>>(visitor: &mut V, let_expr: &'v Let<'v>) pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) { visitor.visit_id(expression.hir_id); - match expression.kind { + ensure_sufficient_stack(|| match expression.kind { ExprKind::Box(ref subexpression) => visitor.visit_expr(subexpression), ExprKind::Array(subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); @@ -1225,7 +1226,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>) visitor.visit_expr(subexpression); } ExprKind::Lit(_) | ExprKind::Err => {} - } + }) } pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) { diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs index 8ccd59e8e37ff..011ff30b81c85 100644 --- a/compiler/rustc_hir/src/stable_hash_impls.rs +++ b/compiler/rustc_hir/src/stable_hash_impls.rs @@ -1,10 +1,11 @@ -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; - use crate::hir::{ AttributeMap, BodyId, Crate, Expr, ForeignItemId, ImplItemId, ItemId, OwnerNodes, TraitItemId, Ty, }; use crate::hir_id::{HirId, ItemLocalId}; + +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_span::def_id::DefPathHash; /// Requirements for a `StableHashingContext` to be used in this crate. @@ -98,7 +99,7 @@ impl HashStable for BodyId { impl HashStable for Expr<'_> { fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { - hcx.hash_hir_expr(self, hasher) + ensure_sufficient_stack(|| hcx.hash_hir_expr(self, hasher)) } } diff --git a/compiler/rustc_hir_pretty/Cargo.toml b/compiler/rustc_hir_pretty/Cargo.toml index 46a8e7deeed04..f8cdf544f193b 100644 --- a/compiler/rustc_hir_pretty/Cargo.toml +++ b/compiler/rustc_hir_pretty/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_target = { path = "../rustc_target" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 87ff94577836c..b0f52e5fcf272 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -5,6 +5,7 @@ use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; use rustc_ast_pretty::pprust::{Comments, PrintState}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::{GenericArg, GenericParam, GenericParamKind, Node, Term}; use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}; @@ -1359,7 +1360,7 @@ impl<'a> State<'a> { self.print_outer_attributes(self.attrs(expr.hir_id)); self.ibox(INDENT_UNIT); self.ann.pre(self, AnnNode::Expr(expr)); - match expr.kind { + ensure_sufficient_stack(|| match expr.kind { hir::ExprKind::Box(ref expr) => { self.word_space("box"); self.print_expr_maybe_paren(expr, parser::PREC_PREFIX); @@ -1545,7 +1546,7 @@ impl<'a> State<'a> { self.word("/*ERROR*/"); self.pclose(); } - } + }); self.ann.post(self, AnnNode::Expr(expr)); self.end() } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ec416722c214e..7826cbeda4528 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -33,6 +33,7 @@ use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::intern::{Interned, WithStableHash}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -466,7 +467,7 @@ impl<'a, 'tcx> HashStable> for TyS<'tcx> { outer_exclusive_binder: _, } = self; - kind.hash_stable(hcx, hasher) + ensure_sufficient_stack(|| kind.hash_stable(hcx, hasher)) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 38362a4cbb925..9d73bdc47ad3e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -4,6 +4,7 @@ use crate::ty::{self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCt use rustc_apfloat::ieee::{Double, Single}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sso::SsoHashSet; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{DefId, DefIdSet, CRATE_DEF_ID, LOCAL_CRATE}; @@ -553,49 +554,57 @@ pub trait PrettyPrinter<'tcx>: } fn pretty_print_type(mut self, ty: Ty<'tcx>) -> Result { - define_scoped_cx!(self); - - match *ty.kind() { - ty::Bool => p!("bool"), - ty::Char => p!("char"), - ty::Int(t) => p!(write("{}", t.name_str())), - ty::Uint(t) => p!(write("{}", t.name_str())), - ty::Float(t) => p!(write("{}", t.name_str())), - ty::RawPtr(ref tm) => { - p!(write( - "*{} ", - match tm.mutbl { - hir::Mutability::Mut => "mut", - hir::Mutability::Not => "const", + ensure_sufficient_stack(|| { + define_scoped_cx!(self); + + match *ty.kind() { + ty::Bool => p!("bool"), + ty::Char => p!("char"), + ty::Int(t) => p!(write("{}", t.name_str())), + ty::Uint(t) => p!(write("{}", t.name_str())), + ty::Float(t) => p!(write("{}", t.name_str())), + ty::RawPtr(ref tm) => { + p!(write( + "*{} ", + match tm.mutbl { + hir::Mutability::Mut => "mut", + hir::Mutability::Not => "const", + } + )); + p!(print(tm.ty)) + } + ty::Ref(r, ty, mutbl) => { + p!("&"); + if self.should_print_region(r) { + p!(print(r), " "); } - )); - p!(print(tm.ty)) - } - ty::Ref(r, ty, mutbl) => { - p!("&"); - if self.should_print_region(r) { - p!(print(r), " "); + p!(print(ty::TypeAndMut { ty, mutbl })) } - p!(print(ty::TypeAndMut { ty, mutbl })) - } - ty::Never => p!("!"), - ty::Tuple(ref tys) => { - p!("(", comma_sep(tys.iter())); - if tys.len() == 1 { - p!(","); + ty::Never => p!("!"), + ty::Tuple(ref tys) => { + p!("(", comma_sep(tys.iter())); + if tys.len() == 1 { + p!(","); + } + p!(")") } - p!(")") - } - ty::FnDef(def_id, substs) => { - let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs); - p!(print(sig), " {{", print_value_path(def_id, substs), "}}"); - } - ty::FnPtr(ref bare_fn) => p!(print(bare_fn)), - ty::Infer(infer_ty) => { - let verbose = self.tcx().sess.verbose(); - if let ty::TyVar(ty_vid) = infer_ty { - if let Some(name) = self.ty_infer_name(ty_vid) { - p!(write("{}", name)) + ty::FnDef(def_id, substs) => { + let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs); + p!(print(sig), " {{", print_value_path(def_id, substs), "}}"); + } + ty::FnPtr(ref bare_fn) => p!(print(bare_fn)), + ty::Infer(infer_ty) => { + let verbose = self.tcx().sess.verbose(); + if let ty::TyVar(ty_vid) = infer_ty { + if let Some(name) = self.ty_infer_name(ty_vid) { + p!(write("{}", name)) + } else { + if verbose { + p!(write("{:?}", infer_ty)) + } else { + p!(write("{}", infer_ty)) + } + } } else { if verbose { p!(write("{:?}", infer_ty)) @@ -603,115 +612,74 @@ pub trait PrettyPrinter<'tcx>: p!(write("{}", infer_ty)) } } - } else { - if verbose { p!(write("{:?}", infer_ty)) } else { p!(write("{}", infer_ty)) } } - } - ty::Error(_) => p!("[type error]"), - ty::Param(ref param_ty) => p!(print(param_ty)), - ty::Bound(debruijn, bound_ty) => match bound_ty.kind { - ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?, - ty::BoundTyKind::Param(p) => p!(write("{}", p)), - }, - ty::Adt(def, substs) => { - p!(print_def_path(def.did(), substs)); - } - ty::Dynamic(data, r) => { - let print_r = self.should_print_region(r); - if print_r { - p!("("); + ty::Error(_) => p!("[type error]"), + ty::Param(ref param_ty) => p!(print(param_ty)), + ty::Bound(debruijn, bound_ty) => match bound_ty.kind { + ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?, + ty::BoundTyKind::Param(p) => p!(write("{}", p)), + }, + ty::Adt(def, substs) => { + p!(print_def_path(def.did(), substs)); } - p!("dyn ", print(data)); - if print_r { - p!(" + ", print(r), ")"); + ty::Dynamic(data, r) => { + let print_r = self.should_print_region(r); + if print_r { + p!("("); + } + p!("dyn ", print(data)); + if print_r { + p!(" + ", print(r), ")"); + } } - } - ty::Foreign(def_id) => { - p!(print_def_path(def_id, &[])); - } - ty::Projection(ref data) => p!(print(data)), - ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), - ty::Opaque(def_id, substs) => { - // FIXME(eddyb) print this with `print_def_path`. - // We use verbose printing in 'NO_QUERIES' mode, to - // avoid needing to call `predicates_of`. This should - // only affect certain debug messages (e.g. messages printed - // from `rustc_middle::ty` during the computation of `tcx.predicates_of`), - // and should have no effect on any compiler output. - if self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get()) { - p!(write("Opaque({:?}, {:?})", def_id, substs)); - return Ok(self); + ty::Foreign(def_id) => { + p!(print_def_path(def_id, &[])); } + ty::Projection(ref data) => p!(print(data)), + ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), + ty::Opaque(def_id, substs) => { + // FIXME(eddyb) print this with `print_def_path`. + // We use verbose printing in 'NO_QUERIES' mode, to + // avoid needing to call `predicates_of`. This should + // only affect certain debug messages (e.g. messages printed + // from `rustc_middle::ty` during the computation of `tcx.predicates_of`), + // and should have no effect on any compiler output. + if self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get()) { + p!(write("Opaque({:?}, {:?})", def_id, substs)); + return Ok(self); + } - let parent = self.tcx().parent(def_id).expect("opaque types always have a parent"); - match self.tcx().def_kind(parent) { - DefKind::TyAlias | DefKind::AssocTy => { - if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() { - if d == def_id { - // If the type alias directly starts with the `impl` of the - // opaque type we're printing, then skip the `::{opaque#1}`. - p!(print_def_path(parent, substs)); - return Ok(self); + let parent = + self.tcx().parent(def_id).expect("opaque types always have a parent"); + match self.tcx().def_kind(parent) { + DefKind::TyAlias | DefKind::AssocTy => { + if let ty::Opaque(d, _) = *self.tcx().type_of(parent).kind() { + if d == def_id { + // If the type alias directly starts with the `impl` of the + // opaque type we're printing, then skip the `::{opaque#1}`. + p!(print_def_path(parent, substs)); + return Ok(self); + } } + // Complex opaque type, e.g. `type Foo = (i32, impl Debug);` + p!(print_def_path(def_id, substs)); + return Ok(self); } - // Complex opaque type, e.g. `type Foo = (i32, impl Debug);` - p!(print_def_path(def_id, substs)); - return Ok(self); + _ => return self.pretty_print_opaque_impl_type(def_id, substs), } - _ => return self.pretty_print_opaque_impl_type(def_id, substs), - } - } - ty::Str => p!("str"), - ty::Generator(did, substs, movability) => { - p!(write("[")); - match movability { - hir::Movability::Movable => {} - hir::Movability::Static => p!("static "), } - - if !self.tcx().sess.verbose() { - p!("generator"); - // FIXME(eddyb) should use `def_span`. - if let Some(did) = did.as_local() { - let span = self.tcx().def_span(did); - p!(write( - "@{}", - // This may end up in stderr diagnostics but it may also be emitted - // into MIR. Hence we use the remapped path if available - self.tcx().sess.source_map().span_to_embeddable_string(span) - )); - } else { - p!(write("@"), print_def_path(did, substs)); - } - } else { - p!(print_def_path(did, substs)); - p!(" upvar_tys=("); - if !substs.as_generator().is_valid() { - p!("unavailable"); - } else { - self = self.comma_sep(substs.as_generator().upvar_tys())?; + ty::Str => p!("str"), + ty::Generator(did, substs, movability) => { + p!(write("[")); + match movability { + hir::Movability::Movable => {} + hir::Movability::Static => p!("static "), } - p!(")"); - if substs.as_generator().is_valid() { - p!(" ", print(substs.as_generator().witness())); - } - } - - p!("]") - } - ty::GeneratorWitness(types) => { - p!(in_binder(&types)); - } - ty::Closure(did, substs) => { - p!(write("[")); - if !self.tcx().sess.verbose() { - p!(write("closure")); - // FIXME(eddyb) should use `def_span`. - if let Some(did) = did.as_local() { - if self.tcx().sess.opts.debugging_opts.span_free_formats { - p!("@", print_def_path(did.to_def_id(), substs)); - } else { + if !self.tcx().sess.verbose() { + p!("generator"); + // FIXME(eddyb) should use `def_span`. + if let Some(did) = did.as_local() { let span = self.tcx().def_span(did); p!(write( "@{}", @@ -719,50 +687,92 @@ pub trait PrettyPrinter<'tcx>: // into MIR. Hence we use the remapped path if available self.tcx().sess.source_map().span_to_embeddable_string(span) )); + } else { + p!(write("@"), print_def_path(did, substs)); } } else { - p!(write("@"), print_def_path(did, substs)); - } - } else { - p!(print_def_path(did, substs)); - if !substs.as_closure().is_valid() { - p!(" closure_substs=(unavailable)"); - p!(write(" substs={:?}", substs)); - } else { - p!(" closure_kind_ty=", print(substs.as_closure().kind_ty())); - p!( - " closure_sig_as_fn_ptr_ty=", - print(substs.as_closure().sig_as_fn_ptr_ty()) - ); + p!(print_def_path(did, substs)); p!(" upvar_tys=("); - self = self.comma_sep(substs.as_closure().upvar_tys())?; + if !substs.as_generator().is_valid() { + p!("unavailable"); + } else { + self = self.comma_sep(substs.as_generator().upvar_tys())?; + } p!(")"); + + if substs.as_generator().is_valid() { + p!(" ", print(substs.as_generator().witness())); + } } + + p!("]") } - p!("]"); - } - ty::Array(ty, sz) => { - p!("[", print(ty), "; "); - if self.tcx().sess.verbose() { - p!(write("{:?}", sz)); - } else if let ty::ConstKind::Unevaluated(..) = sz.val() { - // Do not try to evaluate unevaluated constants. If we are const evaluating an - // array length anon const, rustc will (with debug assertions) print the - // constant's path. Which will end up here again. - p!("_"); - } else if let Some(n) = sz.val().try_to_bits(self.tcx().data_layout.pointer_size) { - p!(write("{}", n)); - } else if let ty::ConstKind::Param(param) = sz.val() { - p!(print(param)); - } else { - p!("_"); + ty::GeneratorWitness(types) => { + p!(in_binder(&types)); } - p!("]") + ty::Closure(did, substs) => { + p!(write("[")); + if !self.tcx().sess.verbose() { + p!(write("closure")); + // FIXME(eddyb) should use `def_span`. + if let Some(did) = did.as_local() { + if self.tcx().sess.opts.debugging_opts.span_free_formats { + p!("@", print_def_path(did.to_def_id(), substs)); + } else { + let span = self.tcx().def_span(did); + p!(write( + "@{}", + // This may end up in stderr diagnostics but it may also be emitted + // into MIR. Hence we use the remapped path if available + self.tcx().sess.source_map().span_to_embeddable_string(span) + )); + } + } else { + p!(write("@"), print_def_path(did, substs)); + } + } else { + p!(print_def_path(did, substs)); + if !substs.as_closure().is_valid() { + p!(" closure_substs=(unavailable)"); + p!(write(" substs={:?}", substs)); + } else { + p!(" closure_kind_ty=", print(substs.as_closure().kind_ty())); + p!( + " closure_sig_as_fn_ptr_ty=", + print(substs.as_closure().sig_as_fn_ptr_ty()) + ); + p!(" upvar_tys=("); + self = self.comma_sep(substs.as_closure().upvar_tys())?; + p!(")"); + } + } + p!("]"); + } + ty::Array(ty, sz) => { + p!("[", print(ty), "; "); + if self.tcx().sess.verbose() { + p!(write("{:?}", sz)); + } else if let ty::ConstKind::Unevaluated(..) = sz.val() { + // Do not try to evaluate unevaluated constants. If we are const evaluating an + // array length anon const, rustc will (with debug assertions) print the + // constant's path. Which will end up here again. + p!("_"); + } else if let Some(n) = + sz.val().try_to_bits(self.tcx().data_layout.pointer_size) + { + p!(write("{}", n)); + } else if let ty::ConstKind::Param(param) = sz.val() { + p!(print(param)); + } else { + p!("_"); + } + p!("]") + } + ty::Slice(ty) => p!("[", print(ty), "]"), } - ty::Slice(ty) => p!("[", print(ty), "]"), - } - Ok(self) + Ok(self) + }) } fn pretty_print_opaque_impl_type( diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 4ef6ff1835ffd..06c5585b6163d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -8,6 +8,7 @@ use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt}; use rustc_data_structures::functor::IdFunctor; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::Namespace; use rustc_index::vec::{Idx, IndexVec}; @@ -976,52 +977,56 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { self, folder: &mut F, ) -> Result { - let kind = match *self.kind() { - ty::RawPtr(tm) => ty::RawPtr(tm.try_fold_with(folder)?), - ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?), - ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?), - ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?), - ty::Dynamic(trait_ty, region) => { - ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?) - } - ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), - ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?), - ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?), - ty::Ref(r, ty, mutbl) => { - ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) - } - ty::Generator(did, substs, movability) => { - ty::Generator(did, substs.try_fold_with(folder)?, movability) - } - ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), - ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?), - ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?), - ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?), - - ty::Bool - | ty::Char - | ty::Str - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Error(_) - | ty::Infer(_) - | ty::Param(..) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Never - | ty::Foreign(..) => return Ok(self), - }; - - Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }) + ensure_sufficient_stack(|| { + let kind = match *self.kind() { + ty::RawPtr(tm) => ty::RawPtr(tm.try_fold_with(folder)?), + ty::Array(typ, sz) => { + ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?) + } + ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?), + ty::Adt(tid, substs) => ty::Adt(tid, substs.try_fold_with(folder)?), + ty::Dynamic(trait_ty, region) => { + ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?) + } + ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), + ty::FnDef(def_id, substs) => ty::FnDef(def_id, substs.try_fold_with(folder)?), + ty::FnPtr(f) => ty::FnPtr(f.try_fold_with(folder)?), + ty::Ref(r, ty, mutbl) => { + ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl) + } + ty::Generator(did, substs, movability) => { + ty::Generator(did, substs.try_fold_with(folder)?, movability) + } + ty::GeneratorWitness(types) => ty::GeneratorWitness(types.try_fold_with(folder)?), + ty::Closure(did, substs) => ty::Closure(did, substs.try_fold_with(folder)?), + ty::Projection(data) => ty::Projection(data.try_fold_with(folder)?), + ty::Opaque(did, substs) => ty::Opaque(did, substs.try_fold_with(folder)?), + + ty::Bool + | ty::Char + | ty::Str + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Error(_) + | ty::Infer(_) + | ty::Param(..) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Never + | ty::Foreign(..) => return Ok(self), + }; + + Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) }) + }) } fn try_fold_with>(self, folder: &mut F) -> Result { - folder.try_fold_ty(self) + ensure_sufficient_stack(|| folder.try_fold_ty(self)) } fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { - match self.kind() { + ensure_sufficient_stack(|| match self.kind() { ty::RawPtr(ref tm) => tm.visit_with(visitor), ty::Array(typ, sz) => { typ.visit_with(visitor)?; @@ -1059,11 +1064,11 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { | ty::Param(..) | ty::Never | ty::Foreign(..) => ControlFlow::CONTINUE, - } + }) } fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - visitor.visit_ty(*self) + ensure_sufficient_stack(|| visitor.visit_ty(*self)) } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index f382f79af29db..f679684ba683c 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -28,7 +28,7 @@ impl<'tcx> Cx<'tcx> { } crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Box<[ExprId]> { - exprs.iter().map(|expr| self.mirror_expr_inner(expr)).collect() + ensure_sufficient_stack(|| exprs.iter().map(|expr| self.mirror_expr_inner(expr)).collect()) } pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId { diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 99ea73fe2fe10..aec0de42e6e7b 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -86,6 +86,7 @@ use self::VarKind::*; use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::*; @@ -825,7 +826,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode { debug!("propagate_through_expr: {:?}", expr); - match expr.kind { + ensure_sufficient_stack(|| match expr.kind { // Interesting cases with control flow or which gen/kill hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => { self.access_path(expr.hir_id, path, succ, ACC_READ | ACC_USE) @@ -1099,7 +1100,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Note that labels have been resolved, so we don't need to look // at the label ident hir::ExprKind::Block(ref blk, _) => self.propagate_through_block(&blk, succ), - } + }) } fn propagate_through_place_components(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNode { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9ea66c0b59d9f..8ea4eb5731250 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -16,6 +16,7 @@ use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; @@ -26,11 +27,11 @@ use rustc_index::vec::Idx; use rustc_middle::ty::DefIdTree; use rustc_middle::{bug, span_bug}; use rustc_session::lint; +use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{BytePos, Span}; use smallvec::{smallvec, SmallVec}; -use rustc_span::source_map::{respan, Spanned}; use std::collections::{hash_map::Entry, BTreeSet}; use std::mem::{replace, take}; use tracing::debug; @@ -3074,7 +3075,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.record_candidate_traits_for_expr_if_necessary(expr); // Next, resolve the node. - match expr.kind { + ensure_sufficient_stack(|| match expr.kind { ExprKind::Path(ref qself, ref path) => { self.smart_resolve_path(expr.id, qself.as_ref(), path, PathSource::Expr(parent)); visit::walk_expr(self, expr); @@ -3223,7 +3224,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { _ => { visit::walk_expr(self, expr); } - } + }) } fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) { diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index ce3069265d020..318f40ce46b69 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -9,6 +9,7 @@ use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot}; use rustc_ast::walk_list; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{struct_span_err, Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -867,7 +868,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { #[tracing::instrument(level = "debug", skip(self))] fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) { - match ty.kind { + ensure_sufficient_stack(|| match ty.kind { hir::TyKind::BareFn(ref c) => { let next_early_index = self.next_early_index(); let lifetime_span: Option = @@ -1118,7 +1119,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } _ => intravisit::walk_ty(self, ty), - } + }) } fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 1caf93e5fe055..a4fe0fc626bfc 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -15,6 +15,7 @@ use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, }; @@ -2368,7 +2369,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn ast_ty_to_ty_inner(&self, ast_ty: &hir::Ty<'_>, borrowed: bool, in_path: bool) -> Ty<'tcx> { let tcx = self.tcx(); - let result_ty = match ast_ty.kind { + let result_ty = ensure_sufficient_stack(|| match ast_ty.kind { hir::TyKind::Slice(ref ty) => tcx.mk_slice(self.ast_ty_to_ty(ty)), hir::TyKind::Ptr(ref mt) => { tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) @@ -2479,7 +2480,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ty_infer(None, ast_ty.span) } hir::TyKind::Err => tcx.ty_error(), - }; + }); debug!(?result_ty);