1#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
5#![allow(rustdoc::private_intra_doc_links)]
7
8extern crate ra_ap_rustc_index as rustc_index;
15
16extern crate ra_ap_rustc_abi as rustc_abi;
17
18extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
19
20extern crate ra_ap_rustc_ast_ir as rustc_ast_ir;
21
22extern crate ra_ap_rustc_type_ir as rustc_type_ir;
23
24extern crate ra_ap_rustc_next_trait_solver as rustc_next_trait_solver;
25
26extern crate self as hir_ty;
27
28mod infer;
29mod inhabitedness;
30mod lower;
31pub mod next_solver;
32mod opaques;
33mod specialization;
34mod target_feature;
35mod utils;
36mod variance;
37
38pub mod autoderef;
39pub mod consteval;
40pub mod db;
41pub mod diagnostics;
42pub mod display;
43pub mod drop;
44pub mod dyn_compatibility;
45pub mod generics;
46pub mod lang_items;
47pub mod layout;
48pub mod method_resolution;
49pub mod mir;
50pub mod primitive;
51pub mod traits;
52
53#[cfg(test)]
54mod test_db;
55#[cfg(test)]
56mod tests;
57
58use std::hash::Hash;
59
60use hir_def::{CallableDefId, TypeOrConstParamId, type_ref::Rawness};
61use hir_expand::name::Name;
62use indexmap::{IndexMap, map::Entry};
63use intern::{Symbol, sym};
64use mir::{MirEvalError, VTableMap};
65use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
66use rustc_type_ir::{
67 BoundVarIndexKind, TypeSuperVisitable, TypeVisitableExt, UpcastFrom,
68 inherent::{IntoKind, SliceLike, Ty as _},
69};
70use syntax::ast::{ConstArg, make};
71use traits::FnTrait;
72
73use crate::{
74 db::HirDatabase,
75 display::{DisplayTarget, HirDisplay},
76 infer::unify::InferenceTable,
77 next_solver::{
78 AliasTy, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, Canonical,
79 CanonicalVarKind, CanonicalVars, Const, ConstKind, DbInterner, FnSig, PolyFnSig, Predicate,
80 Region, RegionKind, TraitRef, Ty, TyKind, Tys, abi,
81 },
82};
83
84pub use autoderef::autoderef;
85pub use infer::{
86 Adjust, Adjustment, AutoBorrow, BindingMode, InferenceDiagnostic, InferenceResult,
87 InferenceTyDiagnosticSource, OverloadedDeref, PointerCast,
88 cast::CastError,
89 closure::analysis::{CaptureKind, CapturedItem},
90 could_coerce, could_unify, could_unify_deeply,
91};
92pub use lower::{
93 GenericPredicates, ImplTraits, LifetimeElisionKind, TyDefId, TyLoweringContext, ValueTyDefId,
94 associated_type_shorthand_candidates, diagnostics::*,
95};
96pub use next_solver::interner::{attach_db, attach_db_allow_change, with_attached_db};
97pub use target_feature::TargetFeatures;
98pub use traits::{ParamEnvAndCrate, check_orphan_rules};
99pub use utils::{
100 TargetFeatureIsSafeInTarget, Unsafety, all_super_traits, direct_super_traits,
101 is_fn_unsafe_to_call, target_feature_is_safe_in_target,
102};
103
104#[derive(Debug, Default, Clone, PartialEq, Eq)]
108pub enum MemoryMap<'db> {
109 #[default]
110 Empty,
111 Simple(Box<[u8]>),
112 Complex(Box<ComplexMemoryMap<'db>>),
113}
114
115#[derive(Debug, Default, Clone, PartialEq, Eq)]
116pub struct ComplexMemoryMap<'db> {
117 memory: IndexMap<usize, Box<[u8]>, FxBuildHasher>,
118 vtable: VTableMap<'db>,
119}
120
121impl ComplexMemoryMap<'_> {
122 fn insert(&mut self, addr: usize, val: Box<[u8]>) {
123 match self.memory.entry(addr) {
124 Entry::Occupied(mut e) => {
125 if e.get().len() < val.len() {
126 e.insert(val);
127 }
128 }
129 Entry::Vacant(e) => {
130 e.insert(val);
131 }
132 }
133 }
134}
135
136impl<'db> MemoryMap<'db> {
137 pub fn vtable_ty(&self, id: usize) -> Result<Ty<'db>, MirEvalError<'db>> {
138 match self {
139 MemoryMap::Empty | MemoryMap::Simple(_) => Err(MirEvalError::InvalidVTableId(id)),
140 MemoryMap::Complex(cm) => cm.vtable.ty(id),
141 }
142 }
143
144 fn simple(v: Box<[u8]>) -> Self {
145 MemoryMap::Simple(v)
146 }
147
148 fn transform_addresses(
152 &self,
153 mut f: impl FnMut(&[u8], usize) -> Result<usize, MirEvalError<'db>>,
154 ) -> Result<FxHashMap<usize, usize>, MirEvalError<'db>> {
155 let mut transform = |(addr, val): (&usize, &[u8])| {
156 let addr = *addr;
157 let align = if addr == 0 { 64 } else { (addr - (addr & (addr - 1))).min(64) };
158 f(val, align).map(|it| (addr, it))
159 };
160 match self {
161 MemoryMap::Empty => Ok(Default::default()),
162 MemoryMap::Simple(m) => transform((&0, m)).map(|(addr, val)| {
163 let mut map = FxHashMap::with_capacity_and_hasher(1, rustc_hash::FxBuildHasher);
164 map.insert(addr, val);
165 map
166 }),
167 MemoryMap::Complex(cm) => {
168 cm.memory.iter().map(|(addr, val)| transform((addr, val))).collect()
169 }
170 }
171 }
172
173 fn get(&self, addr: usize, size: usize) -> Option<&[u8]> {
174 if size == 0 {
175 Some(&[])
176 } else {
177 match self {
178 MemoryMap::Empty => Some(&[]),
179 MemoryMap::Simple(m) if addr == 0 => m.get(0..size),
180 MemoryMap::Simple(_) => None,
181 MemoryMap::Complex(cm) => cm.memory.get(&addr)?.get(0..size),
182 }
183 }
184 }
185}
186
187pub fn param_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<usize> {
189 generics::generics(db, id.parent).type_or_const_param_idx(id)
190}
191
192#[derive(Debug, Copy, Clone, Eq)]
193pub enum FnAbi {
194 Aapcs,
195 AapcsUnwind,
196 AvrInterrupt,
197 AvrNonBlockingInterrupt,
198 C,
199 CCmseNonsecureCall,
200 CCmseNonsecureEntry,
201 CDecl,
202 CDeclUnwind,
203 CUnwind,
204 Efiapi,
205 Fastcall,
206 FastcallUnwind,
207 Msp430Interrupt,
208 PtxKernel,
209 RiscvInterruptM,
210 RiscvInterruptS,
211 Rust,
212 RustCall,
213 RustCold,
214 RustIntrinsic,
215 Stdcall,
216 StdcallUnwind,
217 System,
218 SystemUnwind,
219 Sysv64,
220 Sysv64Unwind,
221 Thiscall,
222 ThiscallUnwind,
223 Unadjusted,
224 Vectorcall,
225 VectorcallUnwind,
226 Wasm,
227 Win64,
228 Win64Unwind,
229 X86Interrupt,
230 Unknown,
231}
232
233impl PartialEq for FnAbi {
234 fn eq(&self, _other: &Self) -> bool {
235 true
237 }
238}
239
240impl Hash for FnAbi {
241 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
242 core::mem::discriminant(&Self::Unknown).hash(state);
245 }
246}
247
248impl FnAbi {
249 #[rustfmt::skip]
250 pub fn from_symbol(s: &Symbol) -> FnAbi {
251 match s {
252 s if *s == sym::aapcs_dash_unwind => FnAbi::AapcsUnwind,
253 s if *s == sym::aapcs => FnAbi::Aapcs,
254 s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt,
255 s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt,
256 s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall,
257 s if *s == sym::C_dash_cmse_dash_nonsecure_dash_entry => FnAbi::CCmseNonsecureEntry,
258 s if *s == sym::C_dash_unwind => FnAbi::CUnwind,
259 s if *s == sym::C => FnAbi::C,
260 s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind,
261 s if *s == sym::cdecl => FnAbi::CDecl,
262 s if *s == sym::efiapi => FnAbi::Efiapi,
263 s if *s == sym::fastcall_dash_unwind => FnAbi::FastcallUnwind,
264 s if *s == sym::fastcall => FnAbi::Fastcall,
265 s if *s == sym::msp430_dash_interrupt => FnAbi::Msp430Interrupt,
266 s if *s == sym::ptx_dash_kernel => FnAbi::PtxKernel,
267 s if *s == sym::riscv_dash_interrupt_dash_m => FnAbi::RiscvInterruptM,
268 s if *s == sym::riscv_dash_interrupt_dash_s => FnAbi::RiscvInterruptS,
269 s if *s == sym::rust_dash_call => FnAbi::RustCall,
270 s if *s == sym::rust_dash_cold => FnAbi::RustCold,
271 s if *s == sym::rust_dash_intrinsic => FnAbi::RustIntrinsic,
272 s if *s == sym::Rust => FnAbi::Rust,
273 s if *s == sym::stdcall_dash_unwind => FnAbi::StdcallUnwind,
274 s if *s == sym::stdcall => FnAbi::Stdcall,
275 s if *s == sym::system_dash_unwind => FnAbi::SystemUnwind,
276 s if *s == sym::system => FnAbi::System,
277 s if *s == sym::sysv64_dash_unwind => FnAbi::Sysv64Unwind,
278 s if *s == sym::sysv64 => FnAbi::Sysv64,
279 s if *s == sym::thiscall_dash_unwind => FnAbi::ThiscallUnwind,
280 s if *s == sym::thiscall => FnAbi::Thiscall,
281 s if *s == sym::unadjusted => FnAbi::Unadjusted,
282 s if *s == sym::vectorcall_dash_unwind => FnAbi::VectorcallUnwind,
283 s if *s == sym::vectorcall => FnAbi::Vectorcall,
284 s if *s == sym::wasm => FnAbi::Wasm,
285 s if *s == sym::win64_dash_unwind => FnAbi::Win64Unwind,
286 s if *s == sym::win64 => FnAbi::Win64,
287 s if *s == sym::x86_dash_interrupt => FnAbi::X86Interrupt,
288 _ => FnAbi::Unknown,
289 }
290 }
291
292 pub fn as_str(self) -> &'static str {
293 match self {
294 FnAbi::Aapcs => "aapcs",
295 FnAbi::AapcsUnwind => "aapcs-unwind",
296 FnAbi::AvrInterrupt => "avr-interrupt",
297 FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt",
298 FnAbi::C => "C",
299 FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call",
300 FnAbi::CCmseNonsecureEntry => "C-cmse-nonsecure-entry",
301 FnAbi::CDecl => "C-decl",
302 FnAbi::CDeclUnwind => "cdecl-unwind",
303 FnAbi::CUnwind => "C-unwind",
304 FnAbi::Efiapi => "efiapi",
305 FnAbi::Fastcall => "fastcall",
306 FnAbi::FastcallUnwind => "fastcall-unwind",
307 FnAbi::Msp430Interrupt => "msp430-interrupt",
308 FnAbi::PtxKernel => "ptx-kernel",
309 FnAbi::RiscvInterruptM => "riscv-interrupt-m",
310 FnAbi::RiscvInterruptS => "riscv-interrupt-s",
311 FnAbi::Rust => "Rust",
312 FnAbi::RustCall => "rust-call",
313 FnAbi::RustCold => "rust-cold",
314 FnAbi::RustIntrinsic => "rust-intrinsic",
315 FnAbi::Stdcall => "stdcall",
316 FnAbi::StdcallUnwind => "stdcall-unwind",
317 FnAbi::System => "system",
318 FnAbi::SystemUnwind => "system-unwind",
319 FnAbi::Sysv64 => "sysv64",
320 FnAbi::Sysv64Unwind => "sysv64-unwind",
321 FnAbi::Thiscall => "thiscall",
322 FnAbi::ThiscallUnwind => "thiscall-unwind",
323 FnAbi::Unadjusted => "unadjusted",
324 FnAbi::Vectorcall => "vectorcall",
325 FnAbi::VectorcallUnwind => "vectorcall-unwind",
326 FnAbi::Wasm => "wasm",
327 FnAbi::Win64 => "win64",
328 FnAbi::Win64Unwind => "win64-unwind",
329 FnAbi::X86Interrupt => "x86-interrupt",
330 FnAbi::Unknown => "unknown-abi",
331 }
332 }
333}
334
335#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
336pub enum ImplTraitId<'db> {
337 ReturnTypeImplTrait(hir_def::FunctionId, next_solver::ImplTraitIdx<'db>),
338 TypeAliasImplTrait(hir_def::TypeAliasId, next_solver::ImplTraitIdx<'db>),
339}
340
341pub fn replace_errors_with_variables<'db, T>(interner: DbInterner<'db>, t: &T) -> Canonical<'db, T>
345where
346 T: rustc_type_ir::TypeFoldable<DbInterner<'db>> + Clone,
347{
348 use rustc_type_ir::{FallibleTypeFolder, TypeSuperFoldable};
349 struct ErrorReplacer<'db> {
350 interner: DbInterner<'db>,
351 vars: Vec<CanonicalVarKind<'db>>,
352 binder: rustc_type_ir::DebruijnIndex,
353 }
354 impl<'db> FallibleTypeFolder<DbInterner<'db>> for ErrorReplacer<'db> {
355 #[cfg(debug_assertions)]
356 type Error = ();
357 #[cfg(not(debug_assertions))]
358 type Error = std::convert::Infallible;
359
360 fn cx(&self) -> DbInterner<'db> {
361 self.interner
362 }
363
364 fn try_fold_binder<T>(&mut self, t: Binder<'db, T>) -> Result<Binder<'db, T>, Self::Error>
365 where
366 T: rustc_type_ir::TypeFoldable<DbInterner<'db>>,
367 {
368 self.binder.shift_in(1);
369 let result = t.try_super_fold_with(self);
370 self.binder.shift_out(1);
371 result
372 }
373
374 fn try_fold_ty(&mut self, t: Ty<'db>) -> Result<Ty<'db>, Self::Error> {
375 if !t.has_type_flags(
376 rustc_type_ir::TypeFlags::HAS_ERROR
377 | rustc_type_ir::TypeFlags::HAS_TY_INFER
378 | rustc_type_ir::TypeFlags::HAS_CT_INFER
379 | rustc_type_ir::TypeFlags::HAS_RE_INFER,
380 ) {
381 return Ok(t);
382 }
383
384 #[cfg(debug_assertions)]
385 let error = || Err(());
386 #[cfg(not(debug_assertions))]
387 let error = || Ok(Ty::new_error(self.interner, crate::next_solver::ErrorGuaranteed));
388
389 match t.kind() {
390 TyKind::Error(_) => {
391 let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
392 self.vars.push(CanonicalVarKind::Ty {
393 ui: rustc_type_ir::UniverseIndex::ZERO,
394 sub_root: var,
395 });
396 Ok(Ty::new_bound(
397 self.interner,
398 self.binder,
399 BoundTy { var, kind: BoundTyKind::Anon },
400 ))
401 }
402 TyKind::Infer(_) => error(),
403 TyKind::Bound(BoundVarIndexKind::Bound(index), _) if index > self.binder => error(),
404 _ => t.try_super_fold_with(self),
405 }
406 }
407
408 fn try_fold_const(&mut self, ct: Const<'db>) -> Result<Const<'db>, Self::Error> {
409 if !ct.has_type_flags(
410 rustc_type_ir::TypeFlags::HAS_ERROR
411 | rustc_type_ir::TypeFlags::HAS_TY_INFER
412 | rustc_type_ir::TypeFlags::HAS_CT_INFER
413 | rustc_type_ir::TypeFlags::HAS_RE_INFER,
414 ) {
415 return Ok(ct);
416 }
417
418 #[cfg(debug_assertions)]
419 let error = || Err(());
420 #[cfg(not(debug_assertions))]
421 let error = || Ok(Const::error(self.interner));
422
423 match ct.kind() {
424 ConstKind::Error(_) => {
425 let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
426 self.vars.push(CanonicalVarKind::Const(rustc_type_ir::UniverseIndex::ZERO));
427 Ok(Const::new_bound(self.interner, self.binder, BoundConst { var }))
428 }
429 ConstKind::Infer(_) => error(),
430 ConstKind::Bound(BoundVarIndexKind::Bound(index), _) if index > self.binder => {
431 error()
432 }
433 _ => ct.try_super_fold_with(self),
434 }
435 }
436
437 fn try_fold_region(&mut self, region: Region<'db>) -> Result<Region<'db>, Self::Error> {
438 #[cfg(debug_assertions)]
439 let error = || Err(());
440 #[cfg(not(debug_assertions))]
441 let error = || Ok(Region::error(self.interner));
442
443 match region.kind() {
444 RegionKind::ReError(_) => {
445 let var = rustc_type_ir::BoundVar::from_usize(self.vars.len());
446 self.vars.push(CanonicalVarKind::Region(rustc_type_ir::UniverseIndex::ZERO));
447 Ok(Region::new_bound(
448 self.interner,
449 self.binder,
450 BoundRegion { var, kind: BoundRegionKind::Anon },
451 ))
452 }
453 RegionKind::ReVar(_) => error(),
454 RegionKind::ReBound(BoundVarIndexKind::Bound(index), _) if index > self.binder => {
455 error()
456 }
457 _ => Ok(region),
458 }
459 }
460 }
461
462 let mut error_replacer =
463 ErrorReplacer { vars: Vec::new(), binder: rustc_type_ir::DebruijnIndex::ZERO, interner };
464 let value = match t.clone().try_fold_with(&mut error_replacer) {
465 Ok(t) => t,
466 Err(_) => panic!("Encountered unbound or inference vars in {t:?}"),
467 };
468 Canonical {
469 value,
470 max_universe: rustc_type_ir::UniverseIndex::ZERO,
471 variables: CanonicalVars::new_from_iter(interner, error_replacer.vars),
472 }
473}
474
475pub fn callable_sig_from_fn_trait<'db>(
477 self_ty: Ty<'db>,
478 trait_env: ParamEnvAndCrate<'db>,
479 db: &'db dyn HirDatabase,
480) -> Option<(FnTrait, PolyFnSig<'db>)> {
481 let mut table = InferenceTable::new(db, trait_env.param_env, trait_env.krate, None);
482 let lang_items = table.interner().lang_items();
483
484 let fn_once_trait = FnTrait::FnOnce.get_id(lang_items)?;
485 let output_assoc_type = fn_once_trait
486 .trait_items(db)
487 .associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
488
489 let args_ty = table.next_ty_var();
493 let args = [self_ty, args_ty];
494 let trait_ref = TraitRef::new(table.interner(), fn_once_trait.into(), args);
495 let projection = Ty::new_alias(
496 table.interner(),
497 rustc_type_ir::AliasTyKind::Projection,
498 AliasTy::new(table.interner(), output_assoc_type.into(), args),
499 );
500
501 let pred = Predicate::upcast_from(trait_ref, table.interner());
502 if !table.try_obligation(pred).no_solution() {
503 table.register_obligation(pred);
504 let return_ty = table.normalize_alias_ty(projection);
505 for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
506 let fn_x_trait = fn_x.get_id(lang_items)?;
507 let trait_ref = TraitRef::new(table.interner(), fn_x_trait.into(), args);
508 if !table
509 .try_obligation(Predicate::upcast_from(trait_ref, table.interner()))
510 .no_solution()
511 {
512 let ret_ty = table.resolve_completely(return_ty);
513 let args_ty = table.resolve_completely(args_ty);
514 let TyKind::Tuple(params) = args_ty.kind() else {
515 return None;
516 };
517 let inputs_and_output = Tys::new_from_iter(
518 table.interner(),
519 params.iter().chain(std::iter::once(ret_ty)),
520 );
521
522 return Some((
523 fn_x,
524 Binder::dummy(FnSig {
525 inputs_and_output,
526 c_variadic: false,
527 safety: abi::Safety::Safe,
528 abi: FnAbi::RustCall,
529 }),
530 ));
531 }
532 }
533 unreachable!("It should at least implement FnOnce at this point");
534 } else {
535 None
536 }
537}
538
539struct ParamCollector {
540 params: FxHashSet<TypeOrConstParamId>,
541}
542
543impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for ParamCollector {
544 type Result = ();
545
546 fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
547 if let TyKind::Param(param) = ty.kind() {
548 self.params.insert(param.id.into());
549 }
550
551 ty.super_visit_with(self);
552 }
553
554 fn visit_const(&mut self, konst: Const<'db>) -> Self::Result {
555 if let ConstKind::Param(param) = konst.kind() {
556 self.params.insert(param.id.into());
557 }
558
559 konst.super_visit_with(self);
560 }
561}
562
563pub fn collect_params<'db, T>(value: &T) -> Vec<TypeOrConstParamId>
565where
566 T: ?Sized + rustc_type_ir::TypeVisitable<DbInterner<'db>>,
567{
568 let mut collector = ParamCollector { params: FxHashSet::default() };
569 value.visit_with(&mut collector);
570 Vec::from_iter(collector.params)
571}
572
573struct TypeInferenceVarCollector<'db> {
574 type_inference_vars: Vec<Ty<'db>>,
575}
576
577impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for TypeInferenceVarCollector<'db> {
578 type Result = ();
579
580 fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
581 use crate::rustc_type_ir::Flags;
582 if ty.is_ty_var() {
583 self.type_inference_vars.push(ty);
584 } else if ty.flags().intersects(rustc_type_ir::TypeFlags::HAS_TY_INFER) {
585 ty.super_visit_with(self);
586 } else {
587 }
590 }
591}
592
593pub fn collect_type_inference_vars<'db, T>(value: &T) -> Vec<Ty<'db>>
594where
595 T: ?Sized + rustc_type_ir::TypeVisitable<DbInterner<'db>>,
596{
597 let mut collector = TypeInferenceVarCollector { type_inference_vars: vec![] };
598 value.visit_with(&mut collector);
599 collector.type_inference_vars
600}
601
602pub fn known_const_to_ast<'db>(
603 konst: Const<'db>,
604 db: &'db dyn HirDatabase,
605 display_target: DisplayTarget,
606) -> Option<ConstArg> {
607 Some(make::expr_const_value(konst.display(db, display_target).to_string().as_str()))
608}
609
610#[derive(Debug, Copy, Clone)]
611pub(crate) enum DeclOrigin {
612 LetExpr,
613 LocalDecl {
615 has_else: bool,
616 },
617}
618
619#[derive(Debug, Copy, Clone)]
623pub(crate) struct DeclContext {
624 pub(crate) origin: DeclOrigin,
625}
626
627pub fn setup_tracing() -> Option<tracing::subscriber::DefaultGuard> {
628 use std::env;
629 use std::sync::LazyLock;
630 use tracing_subscriber::{Registry, layer::SubscriberExt};
631 use tracing_tree::HierarchicalLayer;
632
633 static ENABLE: LazyLock<bool> = LazyLock::new(|| env::var("CHALK_DEBUG").is_ok());
634 if !*ENABLE {
635 return None;
636 }
637
638 let filter: tracing_subscriber::filter::Targets =
639 env::var("CHALK_DEBUG").ok().and_then(|it| it.parse().ok()).unwrap_or_default();
640 let layer = HierarchicalLayer::default()
641 .with_indent_lines(true)
642 .with_ansi(false)
643 .with_indent_amount(2)
644 .with_writer(std::io::stderr);
645 let subscriber = Registry::default().with(filter).with(layer);
646 Some(tracing::subscriber::set_default(subscriber))
647}