1use std::cell::{Cell, RefCell};
2use std::fmt;
3
4pub use at::DefineOpaqueTypes;
5use free_regions::RegionRelations;
6pub use freshen::TypeFreshener;
7use lexical_region_resolve::LexicalRegionResolutions;
8pub use lexical_region_resolve::RegionResolutionError;
9pub use opaque_types::{OpaqueTypeStorage, OpaqueTypeStorageEntries, OpaqueTypeTable};
10use region_constraints::{
11 GenericKind, RegionConstraintCollector, RegionConstraintStorage, VarInfos, VerifyBound,
12};
13pub use relate::StructurallyRelateAliases;
14pub use relate::combine::PredicateEmittingRelation;
15use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
16use rustc_data_structures::undo_log::{Rollback, UndoLogs};
17use rustc_data_structures::unify as ut;
18use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed};
19use rustc_hir as hir;
20use rustc_hir::def_id::{DefId, LocalDefId};
21use rustc_macros::extension;
22pub use rustc_macros::{TypeFoldable, TypeVisitable};
23use rustc_middle::bug;
24use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
25use rustc_middle::mir::ConstraintCategory;
26use rustc_middle::traits::select;
27use rustc_middle::traits::solve::Goal;
28use rustc_middle::ty::error::{ExpectedFound, TypeError};
29use rustc_middle::ty::{
30 self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs,
31 GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueHiddenType, OpaqueTypeKey,
32 PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder,
33 TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
34};
35use rustc_span::{DUMMY_SP, Span, Symbol};
36use snapshot::undo_log::InferCtxtUndoLogs;
37use tracing::{debug, instrument};
38use type_variable::TypeVariableOrigin;
39
40use crate::infer::region_constraints::UndoLog;
41use crate::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey};
42use crate::traits::{
43 self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
44};
45
46pub mod at;
47pub mod canonical;
48mod context;
49mod free_regions;
50mod freshen;
51mod lexical_region_resolve;
52mod opaque_types;
53pub mod outlives;
54mod projection;
55pub mod region_constraints;
56pub mod relate;
57pub mod resolve;
58pub(crate) mod snapshot;
59mod type_variable;
60mod unify_key;
61
62#[must_use]
70#[derive(Debug)]
71pub struct InferOk<'tcx, T> {
72 pub value: T,
73 pub obligations: PredicateObligations<'tcx>,
74}
75pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>;
76
77pub(crate) type FixupResult<T> = Result<T, FixupError>; pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable<
80 ut::InPlace<T, &'a mut ut::UnificationStorage<T>, &'a mut InferCtxtUndoLogs<'tcx>>,
81>;
82
83#[derive(Clone)]
88pub struct InferCtxtInner<'tcx> {
89 undo_log: InferCtxtUndoLogs<'tcx>,
90
91 projection_cache: traits::ProjectionCacheStorage<'tcx>,
95
96 type_variable_storage: type_variable::TypeVariableStorage<'tcx>,
100
101 const_unification_storage: ut::UnificationTableStorage<ConstVidKey<'tcx>>,
103
104 int_unification_storage: ut::UnificationTableStorage<ty::IntVid>,
106
107 float_unification_storage: ut::UnificationTableStorage<ty::FloatVid>,
109
110 region_constraint_storage: Option<RegionConstraintStorage<'tcx>>,
117
118 region_obligations: Vec<TypeOutlivesConstraint<'tcx>>,
151
152 opaque_type_storage: OpaqueTypeStorage<'tcx>,
154}
155
156impl<'tcx> InferCtxtInner<'tcx> {
157 fn new() -> InferCtxtInner<'tcx> {
158 InferCtxtInner {
159 undo_log: InferCtxtUndoLogs::default(),
160
161 projection_cache: Default::default(),
162 type_variable_storage: Default::default(),
163 const_unification_storage: Default::default(),
164 int_unification_storage: Default::default(),
165 float_unification_storage: Default::default(),
166 region_constraint_storage: Some(Default::default()),
167 region_obligations: vec![],
168 opaque_type_storage: Default::default(),
169 }
170 }
171
172 #[inline]
173 pub fn region_obligations(&self) -> &[TypeOutlivesConstraint<'tcx>] {
174 &self.region_obligations
175 }
176
177 #[inline]
178 pub fn projection_cache(&mut self) -> traits::ProjectionCache<'_, 'tcx> {
179 self.projection_cache.with_log(&mut self.undo_log)
180 }
181
182 #[inline]
183 fn try_type_variables_probe_ref(
184 &self,
185 vid: ty::TyVid,
186 ) -> Option<&type_variable::TypeVariableValue<'tcx>> {
187 self.type_variable_storage.eq_relations_ref().try_probe_value(vid)
190 }
191
192 #[inline]
193 fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'tcx> {
194 self.type_variable_storage.with_log(&mut self.undo_log)
195 }
196
197 #[inline]
198 pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
199 self.opaque_type_storage.with_log(&mut self.undo_log)
200 }
201
202 #[inline]
203 fn int_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::IntVid> {
204 self.int_unification_storage.with_log(&mut self.undo_log)
205 }
206
207 #[inline]
208 fn float_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::FloatVid> {
209 self.float_unification_storage.with_log(&mut self.undo_log)
210 }
211
212 #[inline]
213 fn const_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ConstVidKey<'tcx>> {
214 self.const_unification_storage.with_log(&mut self.undo_log)
215 }
216
217 #[inline]
218 pub fn unwrap_region_constraints(&mut self) -> RegionConstraintCollector<'_, 'tcx> {
219 self.region_constraint_storage
220 .as_mut()
221 .expect("region constraints already solved")
222 .with_log(&mut self.undo_log)
223 }
224}
225
226pub struct InferCtxt<'tcx> {
227 pub tcx: TyCtxt<'tcx>,
228
229 typing_mode: TypingMode<'tcx>,
232
233 pub considering_regions: bool,
237
238 skip_leak_check: bool,
243
244 pub inner: RefCell<InferCtxtInner<'tcx>>,
245
246 lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
248
249 pub selection_cache: select::SelectionCache<'tcx, ty::ParamEnv<'tcx>>,
252
253 pub evaluation_cache: select::EvaluationCache<'tcx, ty::ParamEnv<'tcx>>,
256
257 pub reported_trait_errors:
260 RefCell<FxIndexMap<Span, (Vec<Goal<'tcx, ty::Predicate<'tcx>>>, ErrorGuaranteed)>>,
261
262 pub reported_signature_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,
263
264 tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
272
273 universe: Cell<ty::UniverseIndex>,
283
284 next_trait_solver: bool,
285
286 pub obligation_inspector: Cell<Option<ObligationInspector<'tcx>>>,
287}
288
289#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
291pub enum ValuePairs<'tcx> {
292 Regions(ExpectedFound<ty::Region<'tcx>>),
293 Terms(ExpectedFound<ty::Term<'tcx>>),
294 Aliases(ExpectedFound<ty::AliasTerm<'tcx>>),
295 TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
296 PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
297 ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
298 ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
299}
300
301impl<'tcx> ValuePairs<'tcx> {
302 pub fn ty(&self) -> Option<(Ty<'tcx>, Ty<'tcx>)> {
303 if let ValuePairs::Terms(ExpectedFound { expected, found }) = self
304 && let Some(expected) = expected.as_type()
305 && let Some(found) = found.as_type()
306 {
307 Some((expected, found))
308 } else {
309 None
310 }
311 }
312}
313
314#[derive(Clone, Debug)]
319pub struct TypeTrace<'tcx> {
320 pub cause: ObligationCause<'tcx>,
321 pub values: ValuePairs<'tcx>,
322}
323
324#[derive(Clone, Debug)]
328pub enum SubregionOrigin<'tcx> {
329 Subtype(Box<TypeTrace<'tcx>>),
331
332 RelateObjectBound(Span),
335
336 RelateParamBound(Span, Ty<'tcx>, Option<Span>),
339
340 RelateRegionParamBound(Span, Option<Ty<'tcx>>),
343
344 Reborrow(Span),
346
347 ReferenceOutlivesReferent(Ty<'tcx>, Span),
349
350 CompareImplItemObligation {
353 span: Span,
354 impl_item_def_id: LocalDefId,
355 trait_item_def_id: DefId,
356 },
357
358 CheckAssociatedTypeBounds {
360 parent: Box<SubregionOrigin<'tcx>>,
361 impl_item_def_id: LocalDefId,
362 trait_item_def_id: DefId,
363 },
364
365 AscribeUserTypeProvePredicate(Span),
366}
367
368#[cfg(target_pointer_width = "64")]
370rustc_data_structures::static_assert_size!(SubregionOrigin<'_>, 32);
371
372impl<'tcx> SubregionOrigin<'tcx> {
373 pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> {
374 match self {
375 Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(),
376 Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span),
377 _ => ConstraintCategory::BoringNoLocation,
378 }
379 }
380}
381
382#[derive(Clone, Copy, Debug)]
384pub enum BoundRegionConversionTime {
385 FnCall,
387
388 HigherRankedType,
390
391 AssocTypeProjection(DefId),
393}
394
395#[derive(Copy, Clone, Debug)]
399pub enum RegionVariableOrigin {
400 Misc(Span),
404
405 PatternRegion(Span),
407
408 BorrowRegion(Span),
410
411 Autoref(Span),
413
414 Coercion(Span),
416
417 RegionParameterDefinition(Span, Symbol),
422
423 BoundRegion(Span, ty::BoundRegionKind, BoundRegionConversionTime),
426
427 UpvarRegion(ty::UpvarId, Span),
428
429 Nll(NllRegionVariableOrigin),
432}
433
434#[derive(Copy, Clone, Debug)]
435pub enum NllRegionVariableOrigin {
436 FreeRegion,
440
441 Placeholder(ty::PlaceholderRegion),
444
445 Existential {
446 from_forall: bool,
457 },
458}
459
460#[derive(Copy, Clone, Debug)]
461pub struct FixupError {
462 unresolved: TyOrConstInferVar,
463}
464
465impl fmt::Display for FixupError {
466 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467 match self.unresolved {
468 TyOrConstInferVar::TyInt(_) => write!(
469 f,
470 "cannot determine the type of this integer; \
471 add a suffix to specify the type explicitly"
472 ),
473 TyOrConstInferVar::TyFloat(_) => write!(
474 f,
475 "cannot determine the type of this number; \
476 add a suffix to specify the type explicitly"
477 ),
478 TyOrConstInferVar::Ty(_) => write!(f, "unconstrained type"),
479 TyOrConstInferVar::Const(_) => write!(f, "unconstrained const value"),
480 }
481 }
482}
483
484#[derive(Clone, Debug)]
486pub struct TypeOutlivesConstraint<'tcx> {
487 pub sub_region: ty::Region<'tcx>,
488 pub sup_type: Ty<'tcx>,
489 pub origin: SubregionOrigin<'tcx>,
490}
491
492pub struct InferCtxtBuilder<'tcx> {
494 tcx: TyCtxt<'tcx>,
495 considering_regions: bool,
496 skip_leak_check: bool,
497 next_trait_solver: bool,
500}
501
502#[extension(pub trait TyCtxtInferExt<'tcx>)]
503impl<'tcx> TyCtxt<'tcx> {
504 fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
505 InferCtxtBuilder {
506 tcx: self,
507 considering_regions: true,
508 skip_leak_check: false,
509 next_trait_solver: self.next_trait_solver_globally(),
510 }
511 }
512}
513
514impl<'tcx> InferCtxtBuilder<'tcx> {
515 pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self {
516 self.next_trait_solver = next_trait_solver;
517 self
518 }
519
520 pub fn ignoring_regions(mut self) -> Self {
521 self.considering_regions = false;
522 self
523 }
524
525 pub fn skip_leak_check(mut self, skip_leak_check: bool) -> Self {
526 self.skip_leak_check = skip_leak_check;
527 self
528 }
529
530 pub fn build_with_canonical<T>(
538 mut self,
539 span: Span,
540 input: &CanonicalQueryInput<'tcx, T>,
541 ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
542 where
543 T: TypeFoldable<TyCtxt<'tcx>>,
544 {
545 let infcx = self.build(input.typing_mode);
546 let (value, args) = infcx.instantiate_canonical(span, &input.canonical);
547 (infcx, value, args)
548 }
549
550 pub fn build_with_typing_env(
551 mut self,
552 TypingEnv { typing_mode, param_env }: TypingEnv<'tcx>,
553 ) -> (InferCtxt<'tcx>, ty::ParamEnv<'tcx>) {
554 (self.build(typing_mode), param_env)
555 }
556
557 pub fn build(&mut self, typing_mode: TypingMode<'tcx>) -> InferCtxt<'tcx> {
558 let InferCtxtBuilder { tcx, considering_regions, skip_leak_check, next_trait_solver } =
559 *self;
560 InferCtxt {
561 tcx,
562 typing_mode,
563 considering_regions,
564 skip_leak_check,
565 inner: RefCell::new(InferCtxtInner::new()),
566 lexical_region_resolutions: RefCell::new(None),
567 selection_cache: Default::default(),
568 evaluation_cache: Default::default(),
569 reported_trait_errors: Default::default(),
570 reported_signature_mismatch: Default::default(),
571 tainted_by_errors: Cell::new(None),
572 universe: Cell::new(ty::UniverseIndex::ROOT),
573 next_trait_solver,
574 obligation_inspector: Cell::new(None),
575 }
576 }
577}
578
579impl<'tcx, T> InferOk<'tcx, T> {
580 pub fn into_value_registering_obligations<E: 'tcx>(
582 self,
583 infcx: &InferCtxt<'tcx>,
584 fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
585 ) -> T {
586 let InferOk { value, obligations } = self;
587 fulfill_cx.register_predicate_obligations(infcx, obligations);
588 value
589 }
590}
591
592impl<'tcx> InferOk<'tcx, ()> {
593 pub fn into_obligations(self) -> PredicateObligations<'tcx> {
594 self.obligations
595 }
596}
597
598impl<'tcx> InferCtxt<'tcx> {
599 pub fn dcx(&self) -> DiagCtxtHandle<'_> {
600 self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
601 }
602
603 pub fn next_trait_solver(&self) -> bool {
604 self.next_trait_solver
605 }
606
607 #[inline(always)]
608 pub fn typing_mode(&self) -> TypingMode<'tcx> {
609 self.typing_mode
610 }
611
612 pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> T {
613 t.fold_with(&mut self.freshener())
614 }
615
616 pub fn type_var_origin(&self, vid: TyVid) -> TypeVariableOrigin {
620 self.inner.borrow_mut().type_variables().var_origin(vid)
621 }
622
623 pub fn const_var_origin(&self, vid: ConstVid) -> Option<ConstVariableOrigin> {
627 match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
628 ConstVariableValue::Known { .. } => None,
629 ConstVariableValue::Unknown { origin, .. } => Some(origin),
630 }
631 }
632
633 pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
634 freshen::TypeFreshener::new(self)
635 }
636
637 pub fn unresolved_variables(&self) -> Vec<Ty<'tcx>> {
638 let mut inner = self.inner.borrow_mut();
639 let mut vars: Vec<Ty<'_>> = inner
640 .type_variables()
641 .unresolved_variables()
642 .into_iter()
643 .map(|t| Ty::new_var(self.tcx, t))
644 .collect();
645 vars.extend(
646 (0..inner.int_unification_table().len())
647 .map(|i| ty::IntVid::from_usize(i))
648 .filter(|&vid| inner.int_unification_table().probe_value(vid).is_unknown())
649 .map(|v| Ty::new_int_var(self.tcx, v)),
650 );
651 vars.extend(
652 (0..inner.float_unification_table().len())
653 .map(|i| ty::FloatVid::from_usize(i))
654 .filter(|&vid| inner.float_unification_table().probe_value(vid).is_unknown())
655 .map(|v| Ty::new_float_var(self.tcx, v)),
656 );
657 vars
658 }
659
660 #[instrument(skip(self), level = "debug")]
661 pub fn sub_regions(
662 &self,
663 origin: SubregionOrigin<'tcx>,
664 a: ty::Region<'tcx>,
665 b: ty::Region<'tcx>,
666 ) {
667 self.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin, a, b);
668 }
669
670 pub fn coerce_predicate(
686 &self,
687 cause: &ObligationCause<'tcx>,
688 param_env: ty::ParamEnv<'tcx>,
689 predicate: ty::PolyCoercePredicate<'tcx>,
690 ) -> Result<InferResult<'tcx, ()>, (TyVid, TyVid)> {
691 let subtype_predicate = predicate.map_bound(|p| ty::SubtypePredicate {
692 a_is_expected: false, a: p.a,
694 b: p.b,
695 });
696 self.subtype_predicate(cause, param_env, subtype_predicate)
697 }
698
699 pub fn subtype_predicate(
700 &self,
701 cause: &ObligationCause<'tcx>,
702 param_env: ty::ParamEnv<'tcx>,
703 predicate: ty::PolySubtypePredicate<'tcx>,
704 ) -> Result<InferResult<'tcx, ()>, (TyVid, TyVid)> {
705 let r_a = self.shallow_resolve(predicate.skip_binder().a);
719 let r_b = self.shallow_resolve(predicate.skip_binder().b);
720 match (r_a.kind(), r_b.kind()) {
721 (&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
722 return Err((a_vid, b_vid));
723 }
724 _ => {}
725 }
726
727 self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| {
728 if a_is_expected {
729 Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b))
730 } else {
731 Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a))
732 }
733 })
734 }
735
736 pub fn num_ty_vars(&self) -> usize {
738 self.inner.borrow_mut().type_variables().num_vars()
739 }
740
741 pub fn next_ty_var(&self, span: Span) -> Ty<'tcx> {
742 self.next_ty_var_with_origin(TypeVariableOrigin { span, param_def_id: None })
743 }
744
745 pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
746 let vid = self.inner.borrow_mut().type_variables().new_var(self.universe(), origin);
747 Ty::new_var(self.tcx, vid)
748 }
749
750 pub fn next_ty_var_id_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> TyVid {
751 let origin = TypeVariableOrigin { span, param_def_id: None };
752 self.inner.borrow_mut().type_variables().new_var(universe, origin)
753 }
754
755 pub fn next_ty_var_in_universe(&self, span: Span, universe: ty::UniverseIndex) -> Ty<'tcx> {
756 let vid = self.next_ty_var_id_in_universe(span, universe);
757 Ty::new_var(self.tcx, vid)
758 }
759
760 pub fn next_const_var(&self, span: Span) -> ty::Const<'tcx> {
761 self.next_const_var_with_origin(ConstVariableOrigin { span, param_def_id: None })
762 }
763
764 pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> ty::Const<'tcx> {
765 let vid = self
766 .inner
767 .borrow_mut()
768 .const_unification_table()
769 .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
770 .vid;
771 ty::Const::new_var(self.tcx, vid)
772 }
773
774 pub fn next_const_var_in_universe(
775 &self,
776 span: Span,
777 universe: ty::UniverseIndex,
778 ) -> ty::Const<'tcx> {
779 let origin = ConstVariableOrigin { span, param_def_id: None };
780 let vid = self
781 .inner
782 .borrow_mut()
783 .const_unification_table()
784 .new_key(ConstVariableValue::Unknown { origin, universe })
785 .vid;
786 ty::Const::new_var(self.tcx, vid)
787 }
788
789 pub fn next_int_var(&self) -> Ty<'tcx> {
790 let next_int_var_id =
791 self.inner.borrow_mut().int_unification_table().new_key(ty::IntVarValue::Unknown);
792 Ty::new_int_var(self.tcx, next_int_var_id)
793 }
794
795 pub fn next_float_var(&self) -> Ty<'tcx> {
796 let next_float_var_id =
797 self.inner.borrow_mut().float_unification_table().new_key(ty::FloatVarValue::Unknown);
798 Ty::new_float_var(self.tcx, next_float_var_id)
799 }
800
801 pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> {
805 self.next_region_var_in_universe(origin, self.universe())
806 }
807
808 pub fn next_region_var_in_universe(
812 &self,
813 origin: RegionVariableOrigin,
814 universe: ty::UniverseIndex,
815 ) -> ty::Region<'tcx> {
816 let region_var =
817 self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin);
818 ty::Region::new_var(self.tcx, region_var)
819 }
820
821 pub fn next_term_var_of_kind(&self, term: ty::Term<'tcx>, span: Span) -> ty::Term<'tcx> {
822 match term.kind() {
823 ty::TermKind::Ty(_) => self.next_ty_var(span).into(),
824 ty::TermKind::Const(_) => self.next_const_var(span).into(),
825 }
826 }
827
828 pub fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex {
834 self.inner.borrow_mut().unwrap_region_constraints().universe(r)
835 }
836
837 pub fn num_region_vars(&self) -> usize {
839 self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
840 }
841
842 #[instrument(skip(self), level = "debug")]
844 pub fn next_nll_region_var(&self, origin: NllRegionVariableOrigin) -> ty::Region<'tcx> {
845 self.next_region_var(RegionVariableOrigin::Nll(origin))
846 }
847
848 #[instrument(skip(self), level = "debug")]
850 pub fn next_nll_region_var_in_universe(
851 &self,
852 origin: NllRegionVariableOrigin,
853 universe: ty::UniverseIndex,
854 ) -> ty::Region<'tcx> {
855 self.next_region_var_in_universe(RegionVariableOrigin::Nll(origin), universe)
856 }
857
858 pub fn var_for_def(&self, span: Span, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
859 match param.kind {
860 GenericParamDefKind::Lifetime => {
861 self.next_region_var(RegionVariableOrigin::RegionParameterDefinition(
864 span, param.name,
865 ))
866 .into()
867 }
868 GenericParamDefKind::Type { .. } => {
869 let ty_var_id = self.inner.borrow_mut().type_variables().new_var(
878 self.universe(),
879 TypeVariableOrigin { param_def_id: Some(param.def_id), span },
880 );
881
882 Ty::new_var(self.tcx, ty_var_id).into()
883 }
884 GenericParamDefKind::Const { .. } => {
885 let origin = ConstVariableOrigin { param_def_id: Some(param.def_id), span };
886 let const_var_id = self
887 .inner
888 .borrow_mut()
889 .const_unification_table()
890 .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() })
891 .vid;
892 ty::Const::new_var(self.tcx, const_var_id).into()
893 }
894 }
895 }
896
897 pub fn fresh_args_for_item(&self, span: Span, def_id: DefId) -> GenericArgsRef<'tcx> {
900 GenericArgs::for_item(self.tcx, def_id, |param, _| self.var_for_def(span, param))
901 }
902
903 #[must_use = "this method does not have any side effects"]
909 pub fn tainted_by_errors(&self) -> Option<ErrorGuaranteed> {
910 self.tainted_by_errors.get()
911 }
912
913 pub fn set_tainted_by_errors(&self, e: ErrorGuaranteed) {
916 debug!("set_tainted_by_errors(ErrorGuaranteed)");
917 self.tainted_by_errors.set(Some(e));
918 }
919
920 pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin {
921 let mut inner = self.inner.borrow_mut();
922 let inner = &mut *inner;
923 inner.unwrap_region_constraints().var_origin(vid)
924 }
925
926 pub fn get_region_var_infos(&self) -> VarInfos {
929 let inner = self.inner.borrow();
930 assert!(!UndoLogs::<UndoLog<'_>>::in_snapshot(&inner.undo_log));
931 let storage = inner.region_constraint_storage.as_ref().expect("regions already resolved");
932 assert!(storage.data.is_empty(), "{:#?}", storage.data);
933 storage.var_infos.clone()
937 }
938
939 #[instrument(level = "debug", skip(self), ret)]
940 pub fn take_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
941 self.inner.borrow_mut().opaque_type_storage.take_opaque_types().collect()
942 }
943
944 #[instrument(level = "debug", skip(self), ret)]
945 pub fn clone_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
946 self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect()
947 }
948
949 #[inline(always)]
950 pub fn can_define_opaque_ty(&self, id: impl Into<DefId>) -> bool {
951 debug_assert!(!self.next_trait_solver());
952 match self.typing_mode() {
953 TypingMode::Analysis {
954 defining_opaque_types_and_generators: defining_opaque_types,
955 }
956 | TypingMode::Borrowck { defining_opaque_types } => {
957 id.into().as_local().is_some_and(|def_id| defining_opaque_types.contains(&def_id))
958 }
959 TypingMode::Coherence
963 | TypingMode::PostBorrowckAnalysis { .. }
964 | TypingMode::PostAnalysis => false,
965 }
966 }
967
968 pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
969 self.resolve_vars_if_possible(t).to_string()
970 }
971
972 pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
975 use self::type_variable::TypeVariableValue;
976
977 match self.inner.borrow_mut().type_variables().probe(vid) {
978 TypeVariableValue::Known { value } => Ok(value),
979 TypeVariableValue::Unknown { universe } => Err(universe),
980 }
981 }
982
983 pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
984 if let ty::Infer(v) = *ty.kind() {
985 match v {
986 ty::TyVar(v) => {
987 let known = self.inner.borrow_mut().type_variables().probe(v).known();
1000 known.map_or(ty, |t| self.shallow_resolve(t))
1001 }
1002
1003 ty::IntVar(v) => {
1004 match self.inner.borrow_mut().int_unification_table().probe_value(v) {
1005 ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty),
1006 ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty),
1007 ty::IntVarValue::Unknown => ty,
1008 }
1009 }
1010
1011 ty::FloatVar(v) => {
1012 match self.inner.borrow_mut().float_unification_table().probe_value(v) {
1013 ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty),
1014 ty::FloatVarValue::Unknown => ty,
1015 }
1016 }
1017
1018 ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => ty,
1019 }
1020 } else {
1021 ty
1022 }
1023 }
1024
1025 pub fn shallow_resolve_const(&self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
1026 match ct.kind() {
1027 ty::ConstKind::Infer(infer_ct) => match infer_ct {
1028 InferConst::Var(vid) => self
1029 .inner
1030 .borrow_mut()
1031 .const_unification_table()
1032 .probe_value(vid)
1033 .known()
1034 .unwrap_or(ct),
1035 InferConst::Fresh(_) => ct,
1036 },
1037 ty::ConstKind::Param(_)
1038 | ty::ConstKind::Bound(_, _)
1039 | ty::ConstKind::Placeholder(_)
1040 | ty::ConstKind::Unevaluated(_)
1041 | ty::ConstKind::Value(_)
1042 | ty::ConstKind::Error(_)
1043 | ty::ConstKind::Expr(_) => ct,
1044 }
1045 }
1046
1047 pub fn shallow_resolve_term(&self, term: ty::Term<'tcx>) -> ty::Term<'tcx> {
1048 match term.kind() {
1049 ty::TermKind::Ty(ty) => self.shallow_resolve(ty).into(),
1050 ty::TermKind::Const(ct) => self.shallow_resolve_const(ct).into(),
1051 }
1052 }
1053
1054 pub fn root_var(&self, var: ty::TyVid) -> ty::TyVid {
1055 self.inner.borrow_mut().type_variables().root_var(var)
1056 }
1057
1058 pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
1059 self.inner.borrow_mut().const_unification_table().find(var).vid
1060 }
1061
1062 pub fn opportunistic_resolve_int_var(&self, vid: ty::IntVid) -> Ty<'tcx> {
1065 let mut inner = self.inner.borrow_mut();
1066 let value = inner.int_unification_table().probe_value(vid);
1067 match value {
1068 ty::IntVarValue::IntType(ty) => Ty::new_int(self.tcx, ty),
1069 ty::IntVarValue::UintType(ty) => Ty::new_uint(self.tcx, ty),
1070 ty::IntVarValue::Unknown => {
1071 Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid))
1072 }
1073 }
1074 }
1075
1076 pub fn opportunistic_resolve_float_var(&self, vid: ty::FloatVid) -> Ty<'tcx> {
1079 let mut inner = self.inner.borrow_mut();
1080 let value = inner.float_unification_table().probe_value(vid);
1081 match value {
1082 ty::FloatVarValue::Known(ty) => Ty::new_float(self.tcx, ty),
1083 ty::FloatVarValue::Unknown => {
1084 Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid))
1085 }
1086 }
1087 }
1088
1089 pub fn resolve_vars_if_possible<T>(&self, value: T) -> T
1096 where
1097 T: TypeFoldable<TyCtxt<'tcx>>,
1098 {
1099 if let Err(guar) = value.error_reported() {
1100 self.set_tainted_by_errors(guar);
1101 }
1102 if !value.has_non_region_infer() {
1103 return value;
1104 }
1105 let mut r = resolve::OpportunisticVarResolver::new(self);
1106 value.fold_with(&mut r)
1107 }
1108
1109 pub fn resolve_numeric_literals_with_default<T>(&self, value: T) -> T
1110 where
1111 T: TypeFoldable<TyCtxt<'tcx>>,
1112 {
1113 if !value.has_infer() {
1114 return value; }
1116 let mut r = InferenceLiteralEraser { tcx: self.tcx };
1117 value.fold_with(&mut r)
1118 }
1119
1120 pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result<ty::Const<'tcx>, ty::UniverseIndex> {
1121 match self.inner.borrow_mut().const_unification_table().probe_value(vid) {
1122 ConstVariableValue::Known { value } => Ok(value),
1123 ConstVariableValue::Unknown { origin: _, universe } => Err(universe),
1124 }
1125 }
1126
1127 pub fn fully_resolve<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> FixupResult<T> {
1135 match resolve::fully_resolve(self, value) {
1136 Ok(value) => {
1137 if value.has_non_region_infer() {
1138 bug!("`{value:?}` is not fully resolved");
1139 }
1140 if value.has_infer_regions() {
1141 let guar = self.dcx().delayed_bug(format!("`{value:?}` is not fully resolved"));
1142 Ok(fold_regions(self.tcx, value, |re, _| {
1143 if re.is_var() { ty::Region::new_error(self.tcx, guar) } else { re }
1144 }))
1145 } else {
1146 Ok(value)
1147 }
1148 }
1149 Err(e) => Err(e),
1150 }
1151 }
1152
1153 pub fn instantiate_binder_with_fresh_vars<T>(
1161 &self,
1162 span: Span,
1163 lbrct: BoundRegionConversionTime,
1164 value: ty::Binder<'tcx, T>,
1165 ) -> T
1166 where
1167 T: TypeFoldable<TyCtxt<'tcx>> + Copy,
1168 {
1169 if let Some(inner) = value.no_bound_vars() {
1170 return inner;
1171 }
1172
1173 let bound_vars = value.bound_vars();
1174 let mut args = Vec::with_capacity(bound_vars.len());
1175
1176 for bound_var_kind in bound_vars {
1177 let arg: ty::GenericArg<'_> = match bound_var_kind {
1178 ty::BoundVariableKind::Ty(_) => self.next_ty_var(span).into(),
1179 ty::BoundVariableKind::Region(br) => {
1180 self.next_region_var(RegionVariableOrigin::BoundRegion(span, br, lbrct)).into()
1181 }
1182 ty::BoundVariableKind::Const => self.next_const_var(span).into(),
1183 };
1184 args.push(arg);
1185 }
1186
1187 struct ToFreshVars<'tcx> {
1188 args: Vec<ty::GenericArg<'tcx>>,
1189 }
1190
1191 impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'tcx> {
1192 fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx> {
1193 self.args[br.var.index()].expect_region()
1194 }
1195 fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> {
1196 self.args[bt.var.index()].expect_ty()
1197 }
1198 fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> {
1199 self.args[bv.index()].expect_const()
1200 }
1201 }
1202 let delegate = ToFreshVars { args };
1203 self.tcx.replace_bound_vars_uncached(value, delegate)
1204 }
1205
1206 pub(crate) fn verify_generic_bound(
1208 &self,
1209 origin: SubregionOrigin<'tcx>,
1210 kind: GenericKind<'tcx>,
1211 a: ty::Region<'tcx>,
1212 bound: VerifyBound<'tcx>,
1213 ) {
1214 debug!("verify_generic_bound({:?}, {:?} <: {:?})", kind, a, bound);
1215
1216 self.inner
1217 .borrow_mut()
1218 .unwrap_region_constraints()
1219 .verify_generic_bound(origin, kind, a, bound);
1220 }
1221
1222 pub fn closure_kind(&self, closure_ty: Ty<'tcx>) -> Option<ty::ClosureKind> {
1226 let unresolved_kind_ty = match *closure_ty.kind() {
1227 ty::Closure(_, args) => args.as_closure().kind_ty(),
1228 ty::CoroutineClosure(_, args) => args.as_coroutine_closure().kind_ty(),
1229 _ => bug!("unexpected type {closure_ty}"),
1230 };
1231 let closure_kind_ty = self.shallow_resolve(unresolved_kind_ty);
1232 closure_kind_ty.to_opt_closure_kind()
1233 }
1234
1235 pub fn universe(&self) -> ty::UniverseIndex {
1236 self.universe.get()
1237 }
1238
1239 pub fn create_next_universe(&self) -> ty::UniverseIndex {
1242 let u = self.universe.get().next_universe();
1243 debug!("create_next_universe {u:?}");
1244 self.universe.set(u);
1245 u
1246 }
1247
1248 pub fn typing_env(&self, param_env: ty::ParamEnv<'tcx>) -> ty::TypingEnv<'tcx> {
1252 let typing_mode = match self.typing_mode() {
1253 ty::TypingMode::Analysis { defining_opaque_types_and_generators: _ }
1258 | ty::TypingMode::Borrowck { defining_opaque_types: _ } => {
1259 TypingMode::non_body_analysis()
1260 }
1261 mode @ (ty::TypingMode::Coherence
1262 | ty::TypingMode::PostBorrowckAnalysis { .. }
1263 | ty::TypingMode::PostAnalysis) => mode,
1264 };
1265 ty::TypingEnv { typing_mode, param_env }
1266 }
1267
1268 pub fn pseudo_canonicalize_query<V>(
1272 &self,
1273 param_env: ty::ParamEnv<'tcx>,
1274 value: V,
1275 ) -> PseudoCanonicalInput<'tcx, V>
1276 where
1277 V: TypeVisitable<TyCtxt<'tcx>>,
1278 {
1279 debug_assert!(!value.has_infer());
1280 debug_assert!(!value.has_placeholders());
1281 debug_assert!(!param_env.has_infer());
1282 debug_assert!(!param_env.has_placeholders());
1283 self.typing_env(param_env).as_query_input(value)
1284 }
1285
1286 #[inline]
1289 pub fn is_ty_infer_var_definitely_unchanged(&self) -> impl Fn(TyOrConstInferVar) -> bool {
1290 let inner = self.inner.try_borrow();
1292
1293 move |infer_var: TyOrConstInferVar| match (infer_var, &inner) {
1294 (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
1295 use self::type_variable::TypeVariableValue;
1296
1297 matches!(
1298 inner.try_type_variables_probe_ref(ty_var),
1299 Some(TypeVariableValue::Unknown { .. })
1300 )
1301 }
1302 _ => false,
1303 }
1304 }
1305
1306 #[inline(always)]
1316 pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar) -> bool {
1317 match infer_var {
1318 TyOrConstInferVar::Ty(v) => {
1319 use self::type_variable::TypeVariableValue;
1320
1321 match self.inner.borrow_mut().type_variables().inlined_probe(v) {
1324 TypeVariableValue::Unknown { .. } => false,
1325 TypeVariableValue::Known { .. } => true,
1326 }
1327 }
1328
1329 TyOrConstInferVar::TyInt(v) => {
1330 self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known()
1334 }
1335
1336 TyOrConstInferVar::TyFloat(v) => {
1337 self.inner.borrow_mut().float_unification_table().probe_value(v).is_known()
1342 }
1343
1344 TyOrConstInferVar::Const(v) => {
1345 match self.inner.borrow_mut().const_unification_table().probe_value(v) {
1350 ConstVariableValue::Unknown { .. } => false,
1351 ConstVariableValue::Known { .. } => true,
1352 }
1353 }
1354 }
1355 }
1356
1357 pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'tcx>) {
1359 debug_assert!(
1360 self.obligation_inspector.get().is_none(),
1361 "shouldn't override a set obligation inspector"
1362 );
1363 self.obligation_inspector.set(Some(inspector));
1364 }
1365}
1366
1367#[derive(Copy, Clone, Debug)]
1370pub enum TyOrConstInferVar {
1371 Ty(TyVid),
1373 TyInt(IntVid),
1375 TyFloat(FloatVid),
1377
1378 Const(ConstVid),
1380}
1381
1382impl<'tcx> TyOrConstInferVar {
1383 pub fn maybe_from_generic_arg(arg: GenericArg<'tcx>) -> Option<Self> {
1387 match arg.kind() {
1388 GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
1389 GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
1390 GenericArgKind::Lifetime(_) => None,
1391 }
1392 }
1393
1394 pub fn maybe_from_term(term: Term<'tcx>) -> Option<Self> {
1398 match term.kind() {
1399 TermKind::Ty(ty) => Self::maybe_from_ty(ty),
1400 TermKind::Const(ct) => Self::maybe_from_const(ct),
1401 }
1402 }
1403
1404 fn maybe_from_ty(ty: Ty<'tcx>) -> Option<Self> {
1407 match *ty.kind() {
1408 ty::Infer(ty::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)),
1409 ty::Infer(ty::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)),
1410 ty::Infer(ty::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)),
1411 _ => None,
1412 }
1413 }
1414
1415 fn maybe_from_const(ct: ty::Const<'tcx>) -> Option<Self> {
1418 match ct.kind() {
1419 ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
1420 _ => None,
1421 }
1422 }
1423}
1424
1425struct InferenceLiteralEraser<'tcx> {
1428 tcx: TyCtxt<'tcx>,
1429}
1430
1431impl<'tcx> TypeFolder<TyCtxt<'tcx>> for InferenceLiteralEraser<'tcx> {
1432 fn cx(&self) -> TyCtxt<'tcx> {
1433 self.tcx
1434 }
1435
1436 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1437 match ty.kind() {
1438 ty::Infer(ty::IntVar(_) | ty::FreshIntTy(_)) => self.tcx.types.i32,
1439 ty::Infer(ty::FloatVar(_) | ty::FreshFloatTy(_)) => self.tcx.types.f64,
1440 _ => ty.super_fold_with(self),
1441 }
1442 }
1443}
1444
1445impl<'tcx> TypeTrace<'tcx> {
1446 pub fn span(&self) -> Span {
1447 self.cause.span
1448 }
1449
1450 pub fn types(cause: &ObligationCause<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> TypeTrace<'tcx> {
1451 TypeTrace {
1452 cause: cause.clone(),
1453 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1454 }
1455 }
1456
1457 pub fn trait_refs(
1458 cause: &ObligationCause<'tcx>,
1459 a: ty::TraitRef<'tcx>,
1460 b: ty::TraitRef<'tcx>,
1461 ) -> TypeTrace<'tcx> {
1462 TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) }
1463 }
1464
1465 pub fn consts(
1466 cause: &ObligationCause<'tcx>,
1467 a: ty::Const<'tcx>,
1468 b: ty::Const<'tcx>,
1469 ) -> TypeTrace<'tcx> {
1470 TypeTrace {
1471 cause: cause.clone(),
1472 values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())),
1473 }
1474 }
1475}
1476
1477impl<'tcx> SubregionOrigin<'tcx> {
1478 pub fn span(&self) -> Span {
1479 match *self {
1480 SubregionOrigin::Subtype(ref a) => a.span(),
1481 SubregionOrigin::RelateObjectBound(a) => a,
1482 SubregionOrigin::RelateParamBound(a, ..) => a,
1483 SubregionOrigin::RelateRegionParamBound(a, _) => a,
1484 SubregionOrigin::Reborrow(a) => a,
1485 SubregionOrigin::ReferenceOutlivesReferent(_, a) => a,
1486 SubregionOrigin::CompareImplItemObligation { span, .. } => span,
1487 SubregionOrigin::AscribeUserTypeProvePredicate(span) => span,
1488 SubregionOrigin::CheckAssociatedTypeBounds { ref parent, .. } => parent.span(),
1489 }
1490 }
1491
1492 pub fn from_obligation_cause<F>(cause: &traits::ObligationCause<'tcx>, default: F) -> Self
1493 where
1494 F: FnOnce() -> Self,
1495 {
1496 match *cause.code() {
1497 traits::ObligationCauseCode::ReferenceOutlivesReferent(ref_type) => {
1498 SubregionOrigin::ReferenceOutlivesReferent(ref_type, cause.span)
1499 }
1500
1501 traits::ObligationCauseCode::CompareImplItem {
1502 impl_item_def_id,
1503 trait_item_def_id,
1504 kind: _,
1505 } => SubregionOrigin::CompareImplItemObligation {
1506 span: cause.span,
1507 impl_item_def_id,
1508 trait_item_def_id,
1509 },
1510
1511 traits::ObligationCauseCode::CheckAssociatedTypeBounds {
1512 impl_item_def_id,
1513 trait_item_def_id,
1514 } => SubregionOrigin::CheckAssociatedTypeBounds {
1515 impl_item_def_id,
1516 trait_item_def_id,
1517 parent: Box::new(default()),
1518 },
1519
1520 traits::ObligationCauseCode::AscribeUserTypeProvePredicate(span) => {
1521 SubregionOrigin::AscribeUserTypeProvePredicate(span)
1522 }
1523
1524 traits::ObligationCauseCode::ObjectTypeBound(ty, _reg) => {
1525 SubregionOrigin::RelateRegionParamBound(cause.span, Some(ty))
1526 }
1527
1528 _ => default(),
1529 }
1530 }
1531}
1532
1533impl RegionVariableOrigin {
1534 pub fn span(&self) -> Span {
1535 match *self {
1536 RegionVariableOrigin::Misc(a)
1537 | RegionVariableOrigin::PatternRegion(a)
1538 | RegionVariableOrigin::BorrowRegion(a)
1539 | RegionVariableOrigin::Autoref(a)
1540 | RegionVariableOrigin::Coercion(a)
1541 | RegionVariableOrigin::RegionParameterDefinition(a, ..)
1542 | RegionVariableOrigin::BoundRegion(a, ..)
1543 | RegionVariableOrigin::UpvarRegion(_, a) => a,
1544 RegionVariableOrigin::Nll(..) => bug!("NLL variable used with `span`"),
1545 }
1546 }
1547}
1548
1549impl<'tcx> InferCtxt<'tcx> {
1550 pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
1553 let block = block.innermost_block();
1554 if let Some(expr) = &block.expr {
1555 expr.span
1556 } else if let Some(stmt) = block.stmts.last() {
1557 stmt.span
1559 } else {
1560 block.span
1562 }
1563 }
1564
1565 pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
1568 match self.tcx.hir_node(hir_id) {
1569 hir::Node::Block(blk)
1570 | hir::Node::Expr(&hir::Expr { kind: hir::ExprKind::Block(blk, _), .. }) => {
1571 self.find_block_span(blk)
1572 }
1573 hir::Node::Expr(e) => e.span,
1574 _ => DUMMY_SP,
1575 }
1576 }
1577}