rustc_borrowck/type_check/
mod.rs

1//! This pass type-checks the MIR to ensure it is not broken.
2
3use std::rc::Rc;
4use std::{fmt, iter, mem};
5
6use rustc_abi::FieldIdx;
7use rustc_data_structures::frozen::Frozen;
8use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
9use rustc_errors::ErrorGuaranteed;
10use rustc_hir as hir;
11use rustc_hir::def::DefKind;
12use rustc_hir::def_id::LocalDefId;
13use rustc_hir::lang_items::LangItem;
14use rustc_index::{IndexSlice, IndexVec};
15use rustc_infer::infer::canonical::QueryRegionConstraints;
16use rustc_infer::infer::outlives::env::RegionBoundPairs;
17use rustc_infer::infer::region_constraints::RegionConstraintData;
18use rustc_infer::infer::{
19    BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin,
20};
21use rustc_infer::traits::PredicateObligations;
22use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
23use rustc_middle::mir::*;
24use rustc_middle::traits::query::NoSolution;
25use rustc_middle::ty::adjustment::PointerCoercion;
26use rustc_middle::ty::cast::CastTy;
27use rustc_middle::ty::{
28    self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
29    GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, TypeVisitableExt,
30    UserArgs, UserTypeAnnotationIndex, fold_regions,
31};
32use rustc_middle::{bug, span_bug};
33use rustc_mir_dataflow::move_paths::MoveData;
34use rustc_mir_dataflow::points::DenseLocationMap;
35use rustc_span::def_id::CRATE_DEF_ID;
36use rustc_span::source_map::Spanned;
37use rustc_span::{Span, sym};
38use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
39use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
40use tracing::{debug, instrument, trace};
41
42use crate::borrow_set::BorrowSet;
43use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
44use crate::diagnostics::UniverseInfo;
45use crate::member_constraints::MemberConstraintSet;
46use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
47use crate::polonius::{PoloniusContext, PoloniusLivenessContext};
48use crate::region_infer::TypeTest;
49use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices};
50use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
51use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations};
52use crate::universal_regions::{DefiningTy, UniversalRegions};
53use crate::{BorrowCheckRootCtxt, BorrowckInferCtxt, path_utils};
54
55macro_rules! span_mirbug {
56    ($context:expr, $elem:expr, $($message:tt)*) => ({
57        $crate::type_check::mirbug(
58            $context.tcx(),
59            $context.last_span,
60            format!(
61                "broken MIR in {:?} ({:?}): {}",
62                $context.body().source.def_id(),
63                $elem,
64                format_args!($($message)*),
65            ),
66        )
67    })
68}
69
70mod canonical;
71mod constraint_conversion;
72pub(crate) mod free_region_relations;
73mod input_output;
74pub(crate) mod liveness;
75mod opaque_types;
76mod relate_tys;
77
78/// Type checks the given `mir` in the context of the inference
79/// context `infcx`. Returns any region constraints that have yet to
80/// be proven. This result includes liveness constraints that
81/// ensure that regions appearing in the types of all local variables
82/// are live at all points where that local variable may later be
83/// used.
84///
85/// This phase of type-check ought to be infallible -- this is because
86/// the original, HIR-based type-check succeeded. So if any errors
87/// occur here, we will get a `bug!` reported.
88///
89/// # Parameters
90///
91/// - `infcx` -- inference context to use
92/// - `body` -- MIR body to type-check
93/// - `promoted` -- map of promoted constants within `body`
94/// - `universal_regions` -- the universal regions from `body`s function signature
95/// - `location_table` -- for datalog polonius, the map between `Location`s and `RichLocation`s
96/// - `borrow_set` -- information about borrows occurring in `body`
97/// - `polonius_facts` -- when using Polonius, this is the generated set of Polonius facts
98/// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
99/// - `location_map` -- map between MIR `Location` and `PointIndex`
100pub(crate) fn type_check<'tcx>(
101    root_cx: &mut BorrowCheckRootCtxt<'tcx>,
102    infcx: &BorrowckInferCtxt<'tcx>,
103    body: &Body<'tcx>,
104    promoted: &IndexSlice<Promoted, Body<'tcx>>,
105    universal_regions: UniversalRegions<'tcx>,
106    location_table: &PoloniusLocationTable,
107    borrow_set: &BorrowSet<'tcx>,
108    polonius_facts: &mut Option<PoloniusFacts>,
109    move_data: &MoveData<'tcx>,
110    location_map: Rc<DenseLocationMap>,
111) -> MirTypeckResults<'tcx> {
112    let mut constraints = MirTypeckRegionConstraints {
113        placeholder_indices: PlaceholderIndices::default(),
114        placeholder_index_to_region: IndexVec::default(),
115        liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&location_map)),
116        outlives_constraints: OutlivesConstraintSet::default(),
117        member_constraints: MemberConstraintSet::default(),
118        type_tests: Vec::default(),
119        universe_causes: FxIndexMap::default(),
120    };
121
122    let CreateResult {
123        universal_region_relations,
124        region_bound_pairs,
125        normalized_inputs_and_output,
126        known_type_outlives_obligations,
127    } = free_region_relations::create(infcx, infcx.param_env, universal_regions, &mut constraints);
128
129    let pre_obligations = infcx.take_registered_region_obligations();
130    assert!(
131        pre_obligations.is_empty(),
132        "there should be no incoming region obligations = {pre_obligations:#?}",
133    );
134    let pre_assumptions = infcx.take_registered_region_assumptions();
135    assert!(
136        pre_assumptions.is_empty(),
137        "there should be no incoming region assumptions = {pre_assumptions:#?}",
138    );
139
140    debug!(?normalized_inputs_and_output);
141
142    let polonius_liveness = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
143        Some(PoloniusLivenessContext::default())
144    } else {
145        None
146    };
147
148    let mut typeck = TypeChecker {
149        root_cx,
150        infcx,
151        last_span: body.span,
152        body,
153        promoted,
154        user_type_annotations: &body.user_type_annotations,
155        region_bound_pairs: &region_bound_pairs,
156        known_type_outlives_obligations: &known_type_outlives_obligations,
157        reported_errors: Default::default(),
158        universal_regions: &universal_region_relations.universal_regions,
159        location_table,
160        polonius_facts,
161        borrow_set,
162        constraints: &mut constraints,
163        polonius_liveness,
164    };
165
166    typeck.check_user_type_annotations();
167    typeck.visit_body(body);
168    typeck.equate_inputs_and_outputs(&normalized_inputs_and_output);
169    typeck.check_signature_annotation();
170
171    liveness::generate(&mut typeck, &location_map, move_data);
172
173    let opaque_type_values =
174        opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
175
176    // We're done with typeck, we can finalize the polonius liveness context for region inference.
177    let polonius_context = typeck.polonius_liveness.take().map(|liveness_context| {
178        PoloniusContext::create_from_liveness(
179            liveness_context,
180            infcx.num_region_vars(),
181            typeck.constraints.liveness_constraints.points(),
182        )
183    });
184
185    // In case type check encountered an error region, we suppress unhelpful extra
186    // errors in by clearing out all outlives bounds that we may end up checking.
187    if let Some(guar) = universal_region_relations.universal_regions.encountered_re_error() {
188        debug!("encountered an error region; removing constraints!");
189        constraints.outlives_constraints = Default::default();
190        constraints.member_constraints = Default::default();
191        constraints.type_tests = Default::default();
192        root_cx.set_tainted_by_errors(guar);
193        infcx.set_tainted_by_errors(guar);
194    }
195
196    MirTypeckResults {
197        constraints,
198        universal_region_relations,
199        opaque_type_values,
200        polonius_context,
201    }
202}
203
204#[track_caller]
205fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
206    // We sometimes see MIR failures (notably predicate failures) due to
207    // the fact that we check rvalue sized predicates here. So use `span_delayed_bug`
208    // to avoid reporting bugs in those cases.
209    tcx.dcx().span_delayed_bug(span, msg);
210}
211
212enum FieldAccessError {
213    OutOfRange { field_count: usize },
214}
215
216/// The MIR type checker. Visits the MIR and enforces all the
217/// constraints needed for it to be valid and well-typed. Along the
218/// way, it accrues region constraints -- these can later be used by
219/// NLL region checking.
220struct TypeChecker<'a, 'tcx> {
221    root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
222    infcx: &'a BorrowckInferCtxt<'tcx>,
223    last_span: Span,
224    body: &'a Body<'tcx>,
225    /// The bodies of all promoteds. As promoteds have a completely separate CFG
226    /// recursing into them may corrupt your data structures if you're not careful.
227    promoted: &'a IndexSlice<Promoted, Body<'tcx>>,
228    /// User type annotations are shared between the main MIR and the MIR of
229    /// all of the promoted items.
230    user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
231    region_bound_pairs: &'a RegionBoundPairs<'tcx>,
232    known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
233    reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
234    universal_regions: &'a UniversalRegions<'tcx>,
235    location_table: &'a PoloniusLocationTable,
236    polonius_facts: &'a mut Option<PoloniusFacts>,
237    borrow_set: &'a BorrowSet<'tcx>,
238    constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
239    /// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints.
240    polonius_liveness: Option<PoloniusLivenessContext>,
241}
242
243/// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions
244/// inference computation.
245pub(crate) struct MirTypeckResults<'tcx> {
246    pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
247    pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
248    pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
249    pub(crate) polonius_context: Option<PoloniusContext>,
250}
251
252/// A collection of region constraints that must be satisfied for the
253/// program to be considered well-typed.
254pub(crate) struct MirTypeckRegionConstraints<'tcx> {
255    /// Maps from a `ty::Placeholder` to the corresponding
256    /// `PlaceholderIndex` bit that we will use for it.
257    ///
258    /// To keep everything in sync, do not insert this set
259    /// directly. Instead, use the `placeholder_region` helper.
260    pub(crate) placeholder_indices: PlaceholderIndices,
261
262    /// Each time we add a placeholder to `placeholder_indices`, we
263    /// also create a corresponding "representative" region vid for
264    /// that wraps it. This vector tracks those. This way, when we
265    /// convert the same `ty::RePlaceholder(p)` twice, we can map to
266    /// the same underlying `RegionVid`.
267    pub(crate) placeholder_index_to_region: IndexVec<PlaceholderIndex, ty::Region<'tcx>>,
268
269    /// In general, the type-checker is not responsible for enforcing
270    /// liveness constraints; this job falls to the region inferencer,
271    /// which performs a liveness analysis. However, in some limited
272    /// cases, the MIR type-checker creates temporary regions that do
273    /// not otherwise appear in the MIR -- in particular, the
274    /// late-bound regions that it instantiates at call-sites -- and
275    /// hence it must report on their liveness constraints.
276    pub(crate) liveness_constraints: LivenessValues,
277
278    pub(crate) outlives_constraints: OutlivesConstraintSet<'tcx>,
279
280    pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
281
282    pub(crate) universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
283
284    pub(crate) type_tests: Vec<TypeTest<'tcx>>,
285}
286
287impl<'tcx> MirTypeckRegionConstraints<'tcx> {
288    /// Creates a `Region` for a given `PlaceholderRegion`, or returns the
289    /// region that corresponds to a previously created one.
290    fn placeholder_region(
291        &mut self,
292        infcx: &InferCtxt<'tcx>,
293        placeholder: ty::PlaceholderRegion,
294    ) -> ty::Region<'tcx> {
295        let placeholder_index = self.placeholder_indices.insert(placeholder);
296        match self.placeholder_index_to_region.get(placeholder_index) {
297            Some(&v) => v,
298            None => {
299                let origin = NllRegionVariableOrigin::Placeholder(placeholder);
300                let region = infcx.next_nll_region_var_in_universe(origin, placeholder.universe);
301                self.placeholder_index_to_region.push(region);
302                region
303            }
304        }
305    }
306}
307
308/// The `Locations` type summarizes *where* region constraints are
309/// required to hold. Normally, this is at a particular point which
310/// created the obligation, but for constraints that the user gave, we
311/// want the constraint to hold at all points.
312#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
313pub enum Locations {
314    /// Indicates that a type constraint should always be true. This
315    /// is particularly important in the new borrowck analysis for
316    /// things like the type of the return slot. Consider this
317    /// example:
318    ///
319    /// ```compile_fail,E0515
320    /// fn foo<'a>(x: &'a u32) -> &'a u32 {
321    ///     let y = 22;
322    ///     return &y; // error
323    /// }
324    /// ```
325    ///
326    /// Here, we wind up with the signature from the return type being
327    /// something like `&'1 u32` where `'1` is a universal region. But
328    /// the type of the return slot `_0` is something like `&'2 u32`
329    /// where `'2` is an existential region variable. The type checker
330    /// requires that `&'2 u32 = &'1 u32` -- but at what point? In the
331    /// older NLL analysis, we required this only at the entry point
332    /// to the function. By the nature of the constraints, this wound
333    /// up propagating to all points reachable from start (because
334    /// `'1` -- as a universal region -- is live everywhere). In the
335    /// newer analysis, though, this doesn't work: `_0` is considered
336    /// dead at the start (it has no usable value) and hence this type
337    /// equality is basically a no-op. Then, later on, when we do `_0
338    /// = &'3 y`, that region `'3` never winds up related to the
339    /// universal region `'1` and hence no error occurs. Therefore, we
340    /// use Locations::All instead, which ensures that the `'1` and
341    /// `'2` are equal everything. We also use this for other
342    /// user-given type annotations; e.g., if the user wrote `let mut
343    /// x: &'static u32 = ...`, we would ensure that all values
344    /// assigned to `x` are of `'static` lifetime.
345    ///
346    /// The span points to the place the constraint arose. For example,
347    /// it points to the type in a user-given type annotation. If
348    /// there's no sensible span then it's DUMMY_SP.
349    All(Span),
350
351    /// An outlives constraint that only has to hold at a single location,
352    /// usually it represents a point where references flow from one spot to
353    /// another (e.g., `x = y`)
354    Single(Location),
355}
356
357impl Locations {
358    pub fn from_location(&self) -> Option<Location> {
359        match self {
360            Locations::All(_) => None,
361            Locations::Single(from_location) => Some(*from_location),
362        }
363    }
364
365    /// Gets a span representing the location.
366    pub fn span(&self, body: &Body<'_>) -> Span {
367        match self {
368            Locations::All(span) => *span,
369            Locations::Single(l) => body.source_info(*l).span,
370        }
371    }
372}
373
374impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
375    fn tcx(&self) -> TyCtxt<'tcx> {
376        self.infcx.tcx
377    }
378
379    fn body(&self) -> &Body<'tcx> {
380        self.body
381    }
382
383    fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> RegionVid {
384        if let ty::RePlaceholder(placeholder) = r.kind() {
385            self.constraints.placeholder_region(self.infcx, placeholder).as_var()
386        } else {
387            self.universal_regions.to_region_vid(r)
388        }
389    }
390
391    fn unsized_feature_enabled(&self) -> bool {
392        self.tcx().features().unsized_fn_params()
393    }
394
395    /// Equate the inferred type and the annotated type for user type annotations
396    #[instrument(skip(self), level = "debug")]
397    fn check_user_type_annotations(&mut self) {
398        debug!(?self.user_type_annotations);
399        let tcx = self.tcx();
400        for user_annotation in self.user_type_annotations {
401            let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
402            let annotation = self.instantiate_canonical(span, user_ty);
403            if let ty::UserTypeKind::TypeOf(def, args) = annotation.kind
404                && let DefKind::InlineConst = tcx.def_kind(def)
405            {
406                assert!(annotation.bounds.is_empty());
407                self.check_inline_const(inferred_ty, def.expect_local(), args, span);
408            } else {
409                self.ascribe_user_type(inferred_ty, annotation, span);
410            }
411        }
412    }
413
414    #[instrument(skip(self, data), level = "debug")]
415    fn push_region_constraints(
416        &mut self,
417        locations: Locations,
418        category: ConstraintCategory<'tcx>,
419        data: &QueryRegionConstraints<'tcx>,
420    ) {
421        debug!("constraints generated: {:#?}", data);
422
423        constraint_conversion::ConstraintConversion::new(
424            self.infcx,
425            self.universal_regions,
426            self.region_bound_pairs,
427            self.infcx.param_env,
428            self.known_type_outlives_obligations,
429            locations,
430            locations.span(self.body),
431            category,
432            self.constraints,
433        )
434        .convert_all(data);
435    }
436
437    /// Try to relate `sub <: sup`
438    fn sub_types(
439        &mut self,
440        sub: Ty<'tcx>,
441        sup: Ty<'tcx>,
442        locations: Locations,
443        category: ConstraintCategory<'tcx>,
444    ) -> Result<(), NoSolution> {
445        // Use this order of parameters because the sup type is usually the
446        // "expected" type in diagnostics.
447        self.relate_types(sup, ty::Contravariant, sub, locations, category)
448    }
449
450    #[instrument(skip(self, category), level = "debug")]
451    fn eq_types(
452        &mut self,
453        expected: Ty<'tcx>,
454        found: Ty<'tcx>,
455        locations: Locations,
456        category: ConstraintCategory<'tcx>,
457    ) -> Result<(), NoSolution> {
458        self.relate_types(expected, ty::Invariant, found, locations, category)
459    }
460
461    #[instrument(skip(self), level = "debug")]
462    fn relate_type_and_user_type(
463        &mut self,
464        a: Ty<'tcx>,
465        v: ty::Variance,
466        user_ty: &UserTypeProjection,
467        locations: Locations,
468        category: ConstraintCategory<'tcx>,
469    ) -> Result<(), NoSolution> {
470        let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
471        trace!(?annotated_type);
472        let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
473
474        let tcx = self.infcx.tcx;
475
476        for proj in &user_ty.projs {
477            if !self.infcx.next_trait_solver()
478                && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind()
479            {
480                // There is nothing that we can compare here if we go through an opaque type.
481                // We're always in its defining scope as we can otherwise not project through
482                // it, so we're constraining it anyways.
483                return Ok(());
484            }
485            let projected_ty = curr_projected_ty.projection_ty_core(
486                tcx,
487                proj,
488                |ty| self.structurally_resolve(ty, locations),
489                |ty, variant_index, field, ()| PlaceTy::field_ty(tcx, ty, variant_index, field),
490                |_| unreachable!(),
491            );
492            curr_projected_ty = projected_ty;
493        }
494        trace!(?curr_projected_ty);
495
496        // Need to renormalize `a` as typecheck may have failed to normalize
497        // higher-ranked aliases if normalization was ambiguous due to inference.
498        let a = self.normalize(a, locations);
499        let ty = self.normalize(curr_projected_ty.ty, locations);
500        self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
501
502        Ok(())
503    }
504
505    fn check_promoted(&mut self, promoted_body: &'a Body<'tcx>, location: Location) {
506        // Determine the constraints from the promoted MIR by running the type
507        // checker on the promoted MIR, then transfer the constraints back to
508        // the main MIR, changing the locations to the provided location.
509
510        let parent_body = mem::replace(&mut self.body, promoted_body);
511
512        // Use new sets of constraints and closure bounds so that we can
513        // modify their locations.
514        let polonius_facts = &mut None;
515        let mut constraints = Default::default();
516        let mut liveness_constraints =
517            LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
518
519        // Don't try to add borrow_region facts for the promoted MIR as they refer
520        // to the wrong locations.
521        let mut swap_constraints = |this: &mut Self| {
522            mem::swap(this.polonius_facts, polonius_facts);
523            mem::swap(&mut this.constraints.outlives_constraints, &mut constraints);
524            mem::swap(&mut this.constraints.liveness_constraints, &mut liveness_constraints);
525        };
526
527        swap_constraints(self);
528
529        self.visit_body(promoted_body);
530
531        self.body = parent_body;
532
533        // Merge the outlives constraints back in, at the given location.
534        swap_constraints(self);
535        let locations = location.to_locations();
536        for constraint in constraints.outlives().iter() {
537            let mut constraint = *constraint;
538            constraint.locations = locations;
539            if let ConstraintCategory::Return(_)
540            | ConstraintCategory::UseAsConst
541            | ConstraintCategory::UseAsStatic = constraint.category
542            {
543                // "Returning" from a promoted is an assignment to a
544                // temporary from the user's point of view.
545                constraint.category = ConstraintCategory::Boring;
546            }
547            self.constraints.outlives_constraints.push(constraint)
548        }
549        // If the region is live at least one location in the promoted MIR,
550        // then add a liveness constraint to the main MIR for this region
551        // at the location provided as an argument to this method
552        //
553        // add_location doesn't care about ordering so not a problem for the live regions to be
554        // unordered.
555        #[allow(rustc::potential_query_instability)]
556        for region in liveness_constraints.live_regions_unordered() {
557            self.constraints.liveness_constraints.add_location(region, location);
558        }
559    }
560
561    fn check_inline_const(
562        &mut self,
563        inferred_ty: Ty<'tcx>,
564        def_id: LocalDefId,
565        args: UserArgs<'tcx>,
566        span: Span,
567    ) {
568        assert!(args.user_self_ty.is_none());
569        let tcx = self.tcx();
570        let const_ty = tcx.type_of(def_id).instantiate(tcx, args.args);
571        if let Err(terr) =
572            self.eq_types(const_ty, inferred_ty, Locations::All(span), ConstraintCategory::Boring)
573        {
574            span_bug!(
575                span,
576                "bad inline const pattern: ({:?} = {:?}) {:?}",
577                const_ty,
578                inferred_ty,
579                terr
580            );
581        }
582        let args = self.infcx.resolve_vars_if_possible(args.args);
583        let predicates = self.prove_closure_bounds(tcx, def_id, args, Locations::All(span));
584        self.normalize_and_prove_instantiated_predicates(
585            def_id.to_def_id(),
586            predicates,
587            Locations::All(span),
588        );
589    }
590}
591
592impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
593    fn visit_span(&mut self, span: Span) {
594        if !span.is_dummy() {
595            debug!(?span);
596            self.last_span = span;
597        }
598    }
599
600    #[instrument(skip(self, body), level = "debug")]
601    fn visit_body(&mut self, body: &Body<'tcx>) {
602        debug_assert!(std::ptr::eq(self.body, body));
603
604        for (local, local_decl) in body.local_decls.iter_enumerated() {
605            self.visit_local_decl(local, local_decl);
606        }
607
608        for (block, block_data) in body.basic_blocks.iter_enumerated() {
609            let mut location = Location { block, statement_index: 0 };
610            for stmt in &block_data.statements {
611                self.visit_statement(stmt, location);
612                location.statement_index += 1;
613            }
614
615            self.visit_terminator(block_data.terminator(), location);
616            self.check_iscleanup(block_data);
617        }
618    }
619
620    #[instrument(skip(self), level = "debug")]
621    fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
622        self.super_statement(stmt, location);
623        let tcx = self.tcx();
624        match &stmt.kind {
625            StatementKind::Assign(box (place, rv)) => {
626                // Assignments to temporaries are not "interesting";
627                // they are not caused by the user, but rather artifacts
628                // of lowering. Assignments to other sorts of places *are* interesting
629                // though.
630                let category = match place.as_local() {
631                    Some(RETURN_PLACE) => {
632                        let defining_ty = &self.universal_regions.defining_ty;
633                        if defining_ty.is_const() {
634                            if tcx.is_static(defining_ty.def_id()) {
635                                ConstraintCategory::UseAsStatic
636                            } else {
637                                ConstraintCategory::UseAsConst
638                            }
639                        } else {
640                            ConstraintCategory::Return(ReturnConstraint::Normal)
641                        }
642                    }
643                    Some(l)
644                        if matches!(
645                            self.body.local_decls[l].local_info(),
646                            LocalInfo::AggregateTemp
647                        ) =>
648                    {
649                        ConstraintCategory::Usage
650                    }
651                    Some(l) if !self.body.local_decls[l].is_user_variable() => {
652                        ConstraintCategory::Boring
653                    }
654                    _ => ConstraintCategory::Assignment,
655                };
656                debug!(
657                    "assignment category: {:?} {:?}",
658                    category,
659                    place.as_local().map(|l| &self.body.local_decls[l])
660                );
661
662                let place_ty = place.ty(self.body, tcx).ty;
663                debug!(?place_ty);
664                let place_ty = self.normalize(place_ty, location);
665                debug!("place_ty normalized: {:?}", place_ty);
666                let rv_ty = rv.ty(self.body, tcx);
667                debug!(?rv_ty);
668                let rv_ty = self.normalize(rv_ty, location);
669                debug!("normalized rv_ty: {:?}", rv_ty);
670                if let Err(terr) =
671                    self.sub_types(rv_ty, place_ty, location.to_locations(), category)
672                {
673                    span_mirbug!(
674                        self,
675                        stmt,
676                        "bad assignment ({:?} = {:?}): {:?}",
677                        place_ty,
678                        rv_ty,
679                        terr
680                    );
681                }
682
683                if let Some(annotation_index) = self.rvalue_user_ty(rv)
684                    && let Err(terr) = self.relate_type_and_user_type(
685                        rv_ty,
686                        ty::Invariant,
687                        &UserTypeProjection { base: annotation_index, projs: vec![] },
688                        location.to_locations(),
689                        ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
690                    )
691                {
692                    let annotation = &self.user_type_annotations[annotation_index];
693                    span_mirbug!(
694                        self,
695                        stmt,
696                        "bad user type on rvalue ({:?} = {:?}): {:?}",
697                        annotation,
698                        rv_ty,
699                        terr
700                    );
701                }
702
703                if !self.unsized_feature_enabled() {
704                    let trait_ref = ty::TraitRef::new(
705                        tcx,
706                        tcx.require_lang_item(LangItem::Sized, self.last_span),
707                        [place_ty],
708                    );
709                    self.prove_trait_ref(
710                        trait_ref,
711                        location.to_locations(),
712                        ConstraintCategory::SizedBound,
713                    );
714                }
715            }
716            StatementKind::AscribeUserType(box (place, projection), variance) => {
717                let place_ty = place.ty(self.body, tcx).ty;
718                if let Err(terr) = self.relate_type_and_user_type(
719                    place_ty,
720                    *variance,
721                    projection,
722                    Locations::All(stmt.source_info.span),
723                    ConstraintCategory::TypeAnnotation(AnnotationSource::Ascription),
724                ) {
725                    let annotation = &self.user_type_annotations[projection.base];
726                    span_mirbug!(
727                        self,
728                        stmt,
729                        "bad type assert ({:?} <: {:?} with projections {:?}): {:?}",
730                        place_ty,
731                        annotation,
732                        projection.projs,
733                        terr
734                    );
735                }
736            }
737            StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..))
738            | StatementKind::FakeRead(..)
739            | StatementKind::StorageLive(..)
740            | StatementKind::StorageDead(..)
741            | StatementKind::Retag { .. }
742            | StatementKind::Coverage(..)
743            | StatementKind::ConstEvalCounter
744            | StatementKind::PlaceMention(..)
745            | StatementKind::BackwardIncompatibleDropHint { .. }
746            | StatementKind::Nop => {}
747            StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..))
748            | StatementKind::Deinit(..)
749            | StatementKind::SetDiscriminant { .. } => {
750                bug!("Statement not allowed in this MIR phase")
751            }
752        }
753    }
754
755    #[instrument(skip(self), level = "debug")]
756    fn visit_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
757        self.super_terminator(term, term_location);
758        let tcx = self.tcx();
759        debug!("terminator kind: {:?}", term.kind);
760        match &term.kind {
761            TerminatorKind::Goto { .. }
762            | TerminatorKind::UnwindResume
763            | TerminatorKind::UnwindTerminate(_)
764            | TerminatorKind::Return
765            | TerminatorKind::CoroutineDrop
766            | TerminatorKind::Unreachable
767            | TerminatorKind::Drop { .. }
768            | TerminatorKind::FalseEdge { .. }
769            | TerminatorKind::FalseUnwind { .. }
770            | TerminatorKind::InlineAsm { .. } => {
771                // no checks needed for these
772            }
773
774            TerminatorKind::SwitchInt { discr, .. } => {
775                let switch_ty = discr.ty(self.body, tcx);
776                if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
777                    span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
778                }
779                // FIXME: check the values
780            }
781            TerminatorKind::Call { func, args, .. }
782            | TerminatorKind::TailCall { func, args, .. } => {
783                let (call_source, destination, is_diverging) = match term.kind {
784                    TerminatorKind::Call { call_source, destination, target, .. } => {
785                        (call_source, destination, target.is_none())
786                    }
787                    TerminatorKind::TailCall { .. } => {
788                        (CallSource::Normal, RETURN_PLACE.into(), false)
789                    }
790                    _ => unreachable!(),
791                };
792
793                let func_ty = func.ty(self.body, tcx);
794                debug!("func_ty.kind: {:?}", func_ty.kind());
795
796                let sig = match func_ty.kind() {
797                    ty::FnDef(..) | ty::FnPtr(..) => func_ty.fn_sig(tcx),
798                    _ => {
799                        span_mirbug!(self, term, "call to non-function {:?}", func_ty);
800                        return;
801                    }
802                };
803                let (unnormalized_sig, map) = tcx.instantiate_bound_regions(sig, |br| {
804                    use crate::renumber::RegionCtxt;
805
806                    let region_ctxt_fn = || {
807                        let reg_info = match br.kind {
808                            ty::BoundRegionKind::Anon => sym::anon,
809                            ty::BoundRegionKind::Named(def_id) => tcx.item_name(def_id),
810                            ty::BoundRegionKind::ClosureEnv => sym::env,
811                            ty::BoundRegionKind::NamedAnon(_) => {
812                                bug!("only used for pretty printing")
813                            }
814                        };
815
816                        RegionCtxt::LateBound(reg_info)
817                    };
818
819                    self.infcx.next_region_var(
820                        RegionVariableOrigin::BoundRegion(
821                            term.source_info.span,
822                            br.kind,
823                            BoundRegionConversionTime::FnCall,
824                        ),
825                        region_ctxt_fn,
826                    )
827                });
828                debug!(?unnormalized_sig);
829                // IMPORTANT: We have to prove well formed for the function signature before
830                // we normalize it, as otherwise types like `<&'a &'b () as Trait>::Assoc`
831                // get normalized away, causing us to ignore the `'b: 'a` bound used by the function.
832                //
833                // Normalization results in a well formed type if the input is well formed, so we
834                // don't have to check it twice.
835                //
836                // See #91068 for an example.
837                self.prove_predicates(
838                    unnormalized_sig.inputs_and_output.iter().map(|ty| {
839                        ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
840                            ty.into(),
841                        )))
842                    }),
843                    term_location.to_locations(),
844                    ConstraintCategory::Boring,
845                );
846
847                let sig = self.deeply_normalize(unnormalized_sig, term_location);
848                // HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))`
849                // with built-in `Fn` implementations, since the impl may not be
850                // well-formed itself.
851                if sig != unnormalized_sig {
852                    self.prove_predicates(
853                        sig.inputs_and_output.iter().map(|ty| {
854                            ty::Binder::dummy(ty::PredicateKind::Clause(
855                                ty::ClauseKind::WellFormed(ty.into()),
856                            ))
857                        }),
858                        term_location.to_locations(),
859                        ConstraintCategory::Boring,
860                    );
861                }
862
863                self.check_call_dest(term, &sig, destination, is_diverging, term_location);
864
865                // The ordinary liveness rules will ensure that all
866                // regions in the type of the callee are live here. We
867                // then further constrain the late-bound regions that
868                // were instantiated at the call site to be live as
869                // well. The resulting is that all the input (and
870                // output) types in the signature must be live, since
871                // all the inputs that fed into it were live.
872                for &late_bound_region in map.values() {
873                    let region_vid = self.universal_regions.to_region_vid(late_bound_region);
874                    self.constraints.liveness_constraints.add_location(region_vid, term_location);
875                }
876
877                self.check_call_inputs(term, func, &sig, args, term_location, call_source);
878            }
879            TerminatorKind::Assert { cond, msg, .. } => {
880                let cond_ty = cond.ty(self.body, tcx);
881                if cond_ty != tcx.types.bool {
882                    span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
883                }
884
885                if let AssertKind::BoundsCheck { len, index } = &**msg {
886                    if len.ty(self.body, tcx) != tcx.types.usize {
887                        span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
888                    }
889                    if index.ty(self.body, tcx) != tcx.types.usize {
890                        span_mirbug!(self, index, "bounds-check index non-usize {:?}", index)
891                    }
892                }
893            }
894            TerminatorKind::Yield { value, resume_arg, .. } => {
895                match self.body.yield_ty() {
896                    None => span_mirbug!(self, term, "yield in non-coroutine"),
897                    Some(ty) => {
898                        let value_ty = value.ty(self.body, tcx);
899                        if let Err(terr) = self.sub_types(
900                            value_ty,
901                            ty,
902                            term_location.to_locations(),
903                            ConstraintCategory::Yield,
904                        ) {
905                            span_mirbug!(
906                                self,
907                                term,
908                                "type of yield value is {:?}, but the yield type is {:?}: {:?}",
909                                value_ty,
910                                ty,
911                                terr
912                            );
913                        }
914                    }
915                }
916
917                match self.body.resume_ty() {
918                    None => span_mirbug!(self, term, "yield in non-coroutine"),
919                    Some(ty) => {
920                        let resume_ty = resume_arg.ty(self.body, tcx);
921                        if let Err(terr) = self.sub_types(
922                            ty,
923                            resume_ty.ty,
924                            term_location.to_locations(),
925                            ConstraintCategory::Yield,
926                        ) {
927                            span_mirbug!(
928                                self,
929                                term,
930                                "type of resume place is {:?}, but the resume type is {:?}: {:?}",
931                                resume_ty,
932                                ty,
933                                terr
934                            );
935                        }
936                    }
937                }
938            }
939        }
940    }
941
942    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
943        self.super_local_decl(local, local_decl);
944
945        for user_ty in
946            local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
947        {
948            let span = self.user_type_annotations[user_ty.base].span;
949
950            let ty = if local_decl.is_nonref_binding() {
951                local_decl.ty
952            } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
953                // If we have a binding of the form `let ref x: T = ..`
954                // then remove the outermost reference so we can check the
955                // type annotation for the remaining type.
956                rty
957            } else {
958                bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
959            };
960
961            if let Err(terr) = self.relate_type_and_user_type(
962                ty,
963                ty::Invariant,
964                user_ty,
965                Locations::All(span),
966                ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
967            ) {
968                span_mirbug!(
969                    self,
970                    local,
971                    "bad user type on variable {:?}: {:?} != {:?} ({:?})",
972                    local,
973                    local_decl.ty,
974                    local_decl.user_ty,
975                    terr,
976                );
977            }
978        }
979
980        // When `unsized_fn_params` is enabled, only function calls
981        // and nullary ops are checked in `check_call_dest`.
982        if !self.unsized_feature_enabled() {
983            match self.body.local_kind(local) {
984                LocalKind::ReturnPointer | LocalKind::Arg => {
985                    // return values of normal functions are required to be
986                    // sized by typeck, but return values of ADT constructors are
987                    // not because we don't include a `Self: Sized` bounds on them.
988                    //
989                    // Unbound parts of arguments were never required to be Sized
990                    // - maybe we should make that a warning.
991                    return;
992                }
993                LocalKind::Temp => {
994                    let span = local_decl.source_info.span;
995                    let ty = local_decl.ty;
996                    self.ensure_place_sized(ty, span);
997                }
998            }
999        }
1000    }
1001
1002    #[instrument(skip(self), level = "debug")]
1003    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
1004        self.super_rvalue(rvalue, location);
1005        let tcx = self.tcx();
1006        let span = self.body.source_info(location).span;
1007        match rvalue {
1008            Rvalue::Aggregate(ak, ops) => self.check_aggregate_rvalue(rvalue, ak, ops, location),
1009
1010            Rvalue::Repeat(operand, len) => {
1011                let array_ty = rvalue.ty(self.body.local_decls(), tcx);
1012                self.prove_predicate(
1013                    ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
1014                    Locations::Single(location),
1015                    ConstraintCategory::Boring,
1016                );
1017
1018                // If the length cannot be evaluated we must assume that the length can be larger
1019                // than 1.
1020                // If the length is larger than 1, the repeat expression will need to copy the
1021                // element, so we require the `Copy` trait.
1022                if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) {
1023                    match operand {
1024                        Operand::Copy(..) | Operand::Constant(..) => {
1025                            // These are always okay: direct use of a const, or a value that can
1026                            // evidently be copied.
1027                        }
1028                        Operand::Move(place) => {
1029                            // Make sure that repeated elements implement `Copy`.
1030                            let ty = place.ty(self.body, tcx).ty;
1031                            let trait_ref = ty::TraitRef::new(
1032                                tcx,
1033                                tcx.require_lang_item(LangItem::Copy, span),
1034                                [ty],
1035                            );
1036
1037                            self.prove_trait_ref(
1038                                trait_ref,
1039                                Locations::Single(location),
1040                                ConstraintCategory::CopyBound,
1041                            );
1042                        }
1043                    }
1044                }
1045            }
1046
1047            &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
1048                let trait_ref =
1049                    ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [ty]);
1050
1051                self.prove_trait_ref(
1052                    trait_ref,
1053                    location.to_locations(),
1054                    ConstraintCategory::SizedBound,
1055                );
1056            }
1057            &Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
1058            &Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
1059
1060            Rvalue::ShallowInitBox(_operand, ty) => {
1061                let trait_ref =
1062                    ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [*ty]);
1063
1064                self.prove_trait_ref(
1065                    trait_ref,
1066                    location.to_locations(),
1067                    ConstraintCategory::SizedBound,
1068                );
1069            }
1070
1071            Rvalue::Cast(cast_kind, op, ty) => {
1072                match *cast_kind {
1073                    CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
1074                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1075                        let src_ty = op.ty(self.body, tcx);
1076                        let mut src_sig = src_ty.fn_sig(tcx);
1077                        if let ty::FnDef(def_id, _) = src_ty.kind()
1078                            && let ty::FnPtr(_, target_hdr) = *ty.kind()
1079                            && tcx.codegen_fn_attrs(def_id).safe_target_features
1080                            && target_hdr.safety.is_safe()
1081                            && let Some(safe_sig) = tcx.adjust_target_feature_sig(
1082                                *def_id,
1083                                src_sig,
1084                                self.body.source.def_id(),
1085                            )
1086                        {
1087                            src_sig = safe_sig;
1088                        }
1089
1090                        // HACK: This shouldn't be necessary... We can remove this when we actually
1091                        // get binders with where clauses, then elaborate implied bounds into that
1092                        // binder, and implement a higher-ranked subtyping algorithm that actually
1093                        // respects these implied bounds.
1094                        //
1095                        // This protects against the case where we are casting from a higher-ranked
1096                        // fn item to a non-higher-ranked fn pointer, where the cast throws away
1097                        // implied bounds that would've needed to be checked at the call site. This
1098                        // only works when we're casting to a non-higher-ranked fn ptr, since
1099                        // placeholders in the target signature could have untracked implied
1100                        // bounds, resulting in incorrect errors.
1101                        //
1102                        // We check that this signature is WF before subtyping the signature with
1103                        // the target fn sig.
1104                        if src_sig.has_bound_regions()
1105                            && let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind()
1106                            && let target_sig = target_fn_tys.with(target_hdr)
1107                            && let Some(target_sig) = target_sig.no_bound_vars()
1108                        {
1109                            let src_sig = self.infcx.instantiate_binder_with_fresh_vars(
1110                                span,
1111                                BoundRegionConversionTime::HigherRankedType,
1112                                src_sig,
1113                            );
1114                            let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
1115                            self.prove_predicate(
1116                                ty::ClauseKind::WellFormed(src_ty.into()),
1117                                location.to_locations(),
1118                                ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1119                            );
1120
1121                            let src_ty = self.normalize(src_ty, location);
1122                            if let Err(terr) = self.sub_types(
1123                                src_ty,
1124                                *ty,
1125                                location.to_locations(),
1126                                ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1127                            ) {
1128                                span_mirbug!(
1129                                    self,
1130                                    rvalue,
1131                                    "equating {:?} with {:?} yields {:?}",
1132                                    target_sig,
1133                                    src_sig,
1134                                    terr
1135                                );
1136                            };
1137                        }
1138
1139                        let src_ty = Ty::new_fn_ptr(tcx, src_sig);
1140                        // HACK: We want to assert that the signature of the source fn is
1141                        // well-formed, because we don't enforce that via the WF of FnDef
1142                        // types normally. This should be removed when we improve the tracking
1143                        // of implied bounds of fn signatures.
1144                        self.prove_predicate(
1145                            ty::ClauseKind::WellFormed(src_ty.into()),
1146                            location.to_locations(),
1147                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1148                        );
1149
1150                        // The type that we see in the fcx is like
1151                        // `foo::<'a, 'b>`, where `foo` is the path to a
1152                        // function definition. When we extract the
1153                        // signature, it comes from the `fn_sig` query,
1154                        // and hence may contain unnormalized results.
1155                        let src_ty = self.normalize(src_ty, location);
1156                        if let Err(terr) = self.sub_types(
1157                            src_ty,
1158                            *ty,
1159                            location.to_locations(),
1160                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1161                        ) {
1162                            span_mirbug!(
1163                                self,
1164                                rvalue,
1165                                "equating {:?} with {:?} yields {:?}",
1166                                src_ty,
1167                                ty,
1168                                terr
1169                            );
1170                        }
1171                    }
1172
1173                    CastKind::PointerCoercion(
1174                        PointerCoercion::ClosureFnPointer(safety),
1175                        coercion_source,
1176                    ) => {
1177                        let sig = match op.ty(self.body, tcx).kind() {
1178                            ty::Closure(_, args) => args.as_closure().sig(),
1179                            _ => bug!(),
1180                        };
1181                        let ty_fn_ptr_from =
1182                            Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, safety));
1183
1184                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1185                        if let Err(terr) = self.sub_types(
1186                            ty_fn_ptr_from,
1187                            *ty,
1188                            location.to_locations(),
1189                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1190                        ) {
1191                            span_mirbug!(
1192                                self,
1193                                rvalue,
1194                                "equating {:?} with {:?} yields {:?}",
1195                                ty_fn_ptr_from,
1196                                ty,
1197                                terr
1198                            );
1199                        }
1200                    }
1201
1202                    CastKind::PointerCoercion(
1203                        PointerCoercion::UnsafeFnPointer,
1204                        coercion_source,
1205                    ) => {
1206                        let fn_sig = op.ty(self.body, tcx).fn_sig(tcx);
1207
1208                        // The type that we see in the fcx is like
1209                        // `foo::<'a, 'b>`, where `foo` is the path to a
1210                        // function definition. When we extract the
1211                        // signature, it comes from the `fn_sig` query,
1212                        // and hence may contain unnormalized results.
1213                        let fn_sig = self.normalize(fn_sig, location);
1214
1215                        let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
1216
1217                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1218                        if let Err(terr) = self.sub_types(
1219                            ty_fn_ptr_from,
1220                            *ty,
1221                            location.to_locations(),
1222                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1223                        ) {
1224                            span_mirbug!(
1225                                self,
1226                                rvalue,
1227                                "equating {:?} with {:?} yields {:?}",
1228                                ty_fn_ptr_from,
1229                                ty,
1230                                terr
1231                            );
1232                        }
1233                    }
1234
1235                    CastKind::PointerCoercion(PointerCoercion::Unsize, coercion_source) => {
1236                        let &ty = ty;
1237                        let trait_ref = ty::TraitRef::new(
1238                            tcx,
1239                            tcx.require_lang_item(LangItem::CoerceUnsized, span),
1240                            [op.ty(self.body, tcx), ty],
1241                        );
1242
1243                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1244                        let unsize_to = fold_regions(tcx, ty, |r, _| {
1245                            if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
1246                        });
1247                        self.prove_trait_ref(
1248                            trait_ref,
1249                            location.to_locations(),
1250                            ConstraintCategory::Cast {
1251                                is_implicit_coercion,
1252                                unsize_to: Some(unsize_to),
1253                            },
1254                        );
1255                    }
1256
1257                    CastKind::PointerCoercion(
1258                        PointerCoercion::MutToConstPointer,
1259                        coercion_source,
1260                    ) => {
1261                        let ty::RawPtr(ty_from, hir::Mutability::Mut) =
1262                            op.ty(self.body, tcx).kind()
1263                        else {
1264                            span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
1265                            return;
1266                        };
1267                        let ty::RawPtr(ty_to, hir::Mutability::Not) = ty.kind() else {
1268                            span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
1269                            return;
1270                        };
1271                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1272                        if let Err(terr) = self.sub_types(
1273                            *ty_from,
1274                            *ty_to,
1275                            location.to_locations(),
1276                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1277                        ) {
1278                            span_mirbug!(
1279                                self,
1280                                rvalue,
1281                                "relating {:?} with {:?} yields {:?}",
1282                                ty_from,
1283                                ty_to,
1284                                terr
1285                            );
1286                        }
1287                    }
1288
1289                    CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
1290                        let ty_from = op.ty(self.body, tcx);
1291
1292                        let opt_ty_elem_mut = match ty_from.kind() {
1293                            ty::RawPtr(array_ty, array_mut) => match array_ty.kind() {
1294                                ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)),
1295                                _ => None,
1296                            },
1297                            _ => None,
1298                        };
1299
1300                        let Some((ty_elem, ty_mut)) = opt_ty_elem_mut else {
1301                            span_mirbug!(
1302                                self,
1303                                rvalue,
1304                                "ArrayToPointer cast from unexpected type {:?}",
1305                                ty_from,
1306                            );
1307                            return;
1308                        };
1309
1310                        let (ty_to, ty_to_mut) = match ty.kind() {
1311                            ty::RawPtr(ty_to, ty_to_mut) => (ty_to, *ty_to_mut),
1312                            _ => {
1313                                span_mirbug!(
1314                                    self,
1315                                    rvalue,
1316                                    "ArrayToPointer cast to unexpected type {:?}",
1317                                    ty,
1318                                );
1319                                return;
1320                            }
1321                        };
1322
1323                        if ty_to_mut.is_mut() && ty_mut.is_not() {
1324                            span_mirbug!(
1325                                self,
1326                                rvalue,
1327                                "ArrayToPointer cast from const {:?} to mut {:?}",
1328                                ty,
1329                                ty_to
1330                            );
1331                            return;
1332                        }
1333
1334                        let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1335                        if let Err(terr) = self.sub_types(
1336                            *ty_elem,
1337                            *ty_to,
1338                            location.to_locations(),
1339                            ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1340                        ) {
1341                            span_mirbug!(
1342                                self,
1343                                rvalue,
1344                                "relating {:?} with {:?} yields {:?}",
1345                                ty_elem,
1346                                ty_to,
1347                                terr
1348                            )
1349                        }
1350                    }
1351
1352                    CastKind::PointerExposeProvenance => {
1353                        let ty_from = op.ty(self.body, tcx);
1354                        let cast_ty_from = CastTy::from_ty(ty_from);
1355                        let cast_ty_to = CastTy::from_ty(*ty);
1356                        match (cast_ty_from, cast_ty_to) {
1357                            (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
1358                            _ => {
1359                                span_mirbug!(
1360                                    self,
1361                                    rvalue,
1362                                    "Invalid PointerExposeProvenance cast {:?} -> {:?}",
1363                                    ty_from,
1364                                    ty
1365                                )
1366                            }
1367                        }
1368                    }
1369
1370                    CastKind::PointerWithExposedProvenance => {
1371                        let ty_from = op.ty(self.body, tcx);
1372                        let cast_ty_from = CastTy::from_ty(ty_from);
1373                        let cast_ty_to = CastTy::from_ty(*ty);
1374                        match (cast_ty_from, cast_ty_to) {
1375                            (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
1376                            _ => {
1377                                span_mirbug!(
1378                                    self,
1379                                    rvalue,
1380                                    "Invalid PointerWithExposedProvenance cast {:?} -> {:?}",
1381                                    ty_from,
1382                                    ty
1383                                )
1384                            }
1385                        }
1386                    }
1387                    CastKind::IntToInt => {
1388                        let ty_from = op.ty(self.body, tcx);
1389                        let cast_ty_from = CastTy::from_ty(ty_from);
1390                        let cast_ty_to = CastTy::from_ty(*ty);
1391                        match (cast_ty_from, cast_ty_to) {
1392                            (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
1393                            _ => {
1394                                span_mirbug!(
1395                                    self,
1396                                    rvalue,
1397                                    "Invalid IntToInt cast {:?} -> {:?}",
1398                                    ty_from,
1399                                    ty
1400                                )
1401                            }
1402                        }
1403                    }
1404                    CastKind::IntToFloat => {
1405                        let ty_from = op.ty(self.body, tcx);
1406                        let cast_ty_from = CastTy::from_ty(ty_from);
1407                        let cast_ty_to = CastTy::from_ty(*ty);
1408                        match (cast_ty_from, cast_ty_to) {
1409                            (Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
1410                            _ => {
1411                                span_mirbug!(
1412                                    self,
1413                                    rvalue,
1414                                    "Invalid IntToFloat cast {:?} -> {:?}",
1415                                    ty_from,
1416                                    ty
1417                                )
1418                            }
1419                        }
1420                    }
1421                    CastKind::FloatToInt => {
1422                        let ty_from = op.ty(self.body, tcx);
1423                        let cast_ty_from = CastTy::from_ty(ty_from);
1424                        let cast_ty_to = CastTy::from_ty(*ty);
1425                        match (cast_ty_from, cast_ty_to) {
1426                            (Some(CastTy::Float), Some(CastTy::Int(_))) => (),
1427                            _ => {
1428                                span_mirbug!(
1429                                    self,
1430                                    rvalue,
1431                                    "Invalid FloatToInt cast {:?} -> {:?}",
1432                                    ty_from,
1433                                    ty
1434                                )
1435                            }
1436                        }
1437                    }
1438                    CastKind::FloatToFloat => {
1439                        let ty_from = op.ty(self.body, tcx);
1440                        let cast_ty_from = CastTy::from_ty(ty_from);
1441                        let cast_ty_to = CastTy::from_ty(*ty);
1442                        match (cast_ty_from, cast_ty_to) {
1443                            (Some(CastTy::Float), Some(CastTy::Float)) => (),
1444                            _ => {
1445                                span_mirbug!(
1446                                    self,
1447                                    rvalue,
1448                                    "Invalid FloatToFloat cast {:?} -> {:?}",
1449                                    ty_from,
1450                                    ty
1451                                )
1452                            }
1453                        }
1454                    }
1455                    CastKind::FnPtrToPtr => {
1456                        let ty_from = op.ty(self.body, tcx);
1457                        let cast_ty_from = CastTy::from_ty(ty_from);
1458                        let cast_ty_to = CastTy::from_ty(*ty);
1459                        match (cast_ty_from, cast_ty_to) {
1460                            (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
1461                            _ => {
1462                                span_mirbug!(
1463                                    self,
1464                                    rvalue,
1465                                    "Invalid FnPtrToPtr cast {:?} -> {:?}",
1466                                    ty_from,
1467                                    ty
1468                                )
1469                            }
1470                        }
1471                    }
1472                    CastKind::PtrToPtr => {
1473                        let ty_from = op.ty(self.body, tcx);
1474                        let cast_ty_from = CastTy::from_ty(ty_from);
1475                        let cast_ty_to = CastTy::from_ty(*ty);
1476                        match (cast_ty_from, cast_ty_to) {
1477                            (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
1478                                let src_tail = self.struct_tail(src.ty, location);
1479                                let dst_tail = self.struct_tail(dst.ty, location);
1480
1481                                // This checks (lifetime part of) vtable validity for pointer casts,
1482                                // which is irrelevant when there are aren't principal traits on
1483                                // both sides (aka only auto traits).
1484                                //
1485                                // Note that other checks (such as denying `dyn Send` -> `dyn
1486                                // Debug`) are in `rustc_hir_typeck`.
1487                                if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) = *src_tail.kind()
1488                                    && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) = *dst_tail.kind()
1489                                    && src_tty.principal().is_some()
1490                                    && dst_tty.principal().is_some()
1491                                {
1492                                    // Remove auto traits.
1493                                    // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
1494                                    let src_obj = Ty::new_dynamic(
1495                                        tcx,
1496                                        tcx.mk_poly_existential_predicates(
1497                                            &src_tty.without_auto_traits().collect::<Vec<_>>(),
1498                                        ),
1499                                        // FIXME: Once we disallow casting `*const dyn Trait + 'short`
1500                                        // to `*const dyn Trait + 'long`, then this can just be `src_lt`.
1501                                        dst_lt,
1502                                        ty::Dyn,
1503                                    );
1504                                    let dst_obj = Ty::new_dynamic(
1505                                        tcx,
1506                                        tcx.mk_poly_existential_predicates(
1507                                            &dst_tty.without_auto_traits().collect::<Vec<_>>(),
1508                                        ),
1509                                        dst_lt,
1510                                        ty::Dyn,
1511                                    );
1512
1513                                    debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
1514
1515                                    self.sub_types(
1516                                        src_obj,
1517                                        dst_obj,
1518                                        location.to_locations(),
1519                                        ConstraintCategory::Cast {
1520                                            is_implicit_coercion: false,
1521                                            unsize_to: None,
1522                                        },
1523                                    )
1524                                    .unwrap();
1525                                }
1526                            }
1527                            _ => {
1528                                span_mirbug!(
1529                                    self,
1530                                    rvalue,
1531                                    "Invalid PtrToPtr cast {:?} -> {:?}",
1532                                    ty_from,
1533                                    ty
1534                                )
1535                            }
1536                        }
1537                    }
1538                    CastKind::Transmute => {
1539                        let ty_from = op.ty(self.body, tcx);
1540                        match ty_from.kind() {
1541                            ty::Pat(base, _) if base == ty => {}
1542                            _ => span_mirbug!(
1543                                self,
1544                                rvalue,
1545                                "Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR",
1546                            ),
1547                        }
1548                    }
1549                }
1550            }
1551
1552            Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
1553                self.add_reborrow_constraint(location, *region, borrowed_place);
1554            }
1555
1556            Rvalue::BinaryOp(
1557                BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
1558                box (left, right),
1559            ) => {
1560                let ty_left = left.ty(self.body, tcx);
1561                match ty_left.kind() {
1562                    // Types with regions are comparable if they have a common super-type.
1563                    ty::RawPtr(_, _) | ty::FnPtr(..) => {
1564                        let ty_right = right.ty(self.body, tcx);
1565                        let common_ty =
1566                            self.infcx.next_ty_var(self.body.source_info(location).span);
1567                        self.sub_types(
1568                            ty_left,
1569                            common_ty,
1570                            location.to_locations(),
1571                            ConstraintCategory::CallArgument(None),
1572                        )
1573                        .unwrap_or_else(|err| {
1574                            bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
1575                        });
1576                        if let Err(terr) = self.sub_types(
1577                            ty_right,
1578                            common_ty,
1579                            location.to_locations(),
1580                            ConstraintCategory::CallArgument(None),
1581                        ) {
1582                            span_mirbug!(
1583                                self,
1584                                rvalue,
1585                                "unexpected comparison types {:?} and {:?} yields {:?}",
1586                                ty_left,
1587                                ty_right,
1588                                terr
1589                            )
1590                        }
1591                    }
1592                    // For types with no regions we can just check that the
1593                    // both operands have the same type.
1594                    ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_)
1595                        if ty_left == right.ty(self.body, tcx) => {}
1596                    // Other types are compared by trait methods, not by
1597                    // `Rvalue::BinaryOp`.
1598                    _ => span_mirbug!(
1599                        self,
1600                        rvalue,
1601                        "unexpected comparison types {:?} and {:?}",
1602                        ty_left,
1603                        right.ty(self.body, tcx)
1604                    ),
1605                }
1606            }
1607
1608            Rvalue::WrapUnsafeBinder(op, ty) => {
1609                let operand_ty = op.ty(self.body, self.tcx());
1610                let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
1611                    unreachable!();
1612                };
1613                let expected_ty = self.infcx.instantiate_binder_with_fresh_vars(
1614                    self.body().source_info(location).span,
1615                    BoundRegionConversionTime::HigherRankedType,
1616                    binder_ty.into(),
1617                );
1618                self.sub_types(
1619                    operand_ty,
1620                    expected_ty,
1621                    location.to_locations(),
1622                    ConstraintCategory::Boring,
1623                )
1624                .unwrap();
1625            }
1626
1627            Rvalue::Use(_)
1628            | Rvalue::UnaryOp(_, _)
1629            | Rvalue::CopyForDeref(_)
1630            | Rvalue::BinaryOp(..)
1631            | Rvalue::RawPtr(..)
1632            | Rvalue::ThreadLocalRef(..)
1633            | Rvalue::Len(..)
1634            | Rvalue::Discriminant(..)
1635            | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
1636        }
1637    }
1638
1639    #[instrument(level = "debug", skip(self))]
1640    fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
1641        self.super_operand(op, location);
1642        if let Operand::Constant(constant) = op {
1643            let maybe_uneval = match constant.const_ {
1644                Const::Val(..) | Const::Ty(_, _) => None,
1645                Const::Unevaluated(uv, _) => Some(uv),
1646            };
1647
1648            if let Some(uv) = maybe_uneval {
1649                if uv.promoted.is_none() {
1650                    let tcx = self.tcx();
1651                    let def_id = uv.def;
1652                    if tcx.def_kind(def_id) == DefKind::InlineConst {
1653                        let def_id = def_id.expect_local();
1654                        let predicates = self.prove_closure_bounds(
1655                            tcx,
1656                            def_id,
1657                            uv.args,
1658                            location.to_locations(),
1659                        );
1660                        self.normalize_and_prove_instantiated_predicates(
1661                            def_id.to_def_id(),
1662                            predicates,
1663                            location.to_locations(),
1664                        );
1665                    }
1666                }
1667            }
1668        }
1669    }
1670
1671    #[instrument(level = "debug", skip(self))]
1672    fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
1673        self.super_const_operand(constant, location);
1674        let ty = constant.const_.ty();
1675
1676        self.infcx.tcx.for_each_free_region(&ty, |live_region| {
1677            let live_region_vid = self.universal_regions.to_region_vid(live_region);
1678            self.constraints.liveness_constraints.add_location(live_region_vid, location);
1679        });
1680
1681        let locations = location.to_locations();
1682        if let Some(annotation_index) = constant.user_ty {
1683            if let Err(terr) = self.relate_type_and_user_type(
1684                constant.const_.ty(),
1685                ty::Invariant,
1686                &UserTypeProjection { base: annotation_index, projs: vec![] },
1687                locations,
1688                ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
1689            ) {
1690                let annotation = &self.user_type_annotations[annotation_index];
1691                span_mirbug!(
1692                    self,
1693                    constant,
1694                    "bad constant user type {:?} vs {:?}: {:?}",
1695                    annotation,
1696                    constant.const_.ty(),
1697                    terr,
1698                );
1699            }
1700        } else {
1701            let tcx = self.tcx();
1702            let maybe_uneval = match constant.const_ {
1703                Const::Ty(_, ct) => match ct.kind() {
1704                    ty::ConstKind::Unevaluated(uv) => {
1705                        Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
1706                    }
1707                    _ => None,
1708                },
1709                Const::Unevaluated(uv, _) => Some(uv),
1710                _ => None,
1711            };
1712
1713            if let Some(uv) = maybe_uneval {
1714                if let Some(promoted) = uv.promoted {
1715                    let promoted_body = &self.promoted[promoted];
1716                    self.check_promoted(promoted_body, location);
1717                    let promoted_ty = promoted_body.return_ty();
1718                    if let Err(terr) =
1719                        self.eq_types(ty, promoted_ty, locations, ConstraintCategory::Boring)
1720                    {
1721                        span_mirbug!(
1722                            self,
1723                            promoted,
1724                            "bad promoted type ({:?}: {:?}): {:?}",
1725                            ty,
1726                            promoted_ty,
1727                            terr
1728                        );
1729                    };
1730                } else {
1731                    self.ascribe_user_type(
1732                        constant.const_.ty(),
1733                        ty::UserType::new(ty::UserTypeKind::TypeOf(
1734                            uv.def,
1735                            UserArgs { args: uv.args, user_self_ty: None },
1736                        )),
1737                        locations.span(self.body),
1738                    );
1739                }
1740            } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
1741                let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
1742                let normalized_ty = self.normalize(unnormalized_ty, locations);
1743                let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
1744
1745                if let Err(terr) =
1746                    self.eq_types(literal_ty, normalized_ty, locations, ConstraintCategory::Boring)
1747                {
1748                    span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
1749                }
1750            } else if let Const::Ty(_, ct) = constant.const_
1751                && let ty::ConstKind::Param(p) = ct.kind()
1752            {
1753                let body_def_id = self.universal_regions.defining_ty.def_id();
1754                let const_param = tcx.generics_of(body_def_id).const_param(p, tcx);
1755                self.ascribe_user_type(
1756                    constant.const_.ty(),
1757                    ty::UserType::new(ty::UserTypeKind::TypeOf(
1758                        const_param.def_id,
1759                        UserArgs {
1760                            args: self.universal_regions.defining_ty.args(),
1761                            user_self_ty: None,
1762                        },
1763                    )),
1764                    locations.span(self.body),
1765                );
1766            }
1767
1768            if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
1769                let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
1770                self.normalize_and_prove_instantiated_predicates(
1771                    def_id,
1772                    instantiated_predicates,
1773                    locations,
1774                );
1775
1776                assert_eq!(tcx.trait_impl_of_assoc(def_id), None);
1777                self.prove_predicates(
1778                    args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
1779                    locations,
1780                    ConstraintCategory::Boring,
1781                );
1782            }
1783        }
1784    }
1785
1786    fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
1787        self.super_place(place, context, location);
1788        let tcx = self.tcx();
1789        let place_ty = place.ty(self.body, tcx);
1790        if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
1791            let trait_ref = ty::TraitRef::new(
1792                tcx,
1793                tcx.require_lang_item(LangItem::Copy, self.last_span),
1794                [place_ty.ty],
1795            );
1796
1797            // To have a `Copy` operand, the type `T` of the
1798            // value must be `Copy`. Note that we prove that `T: Copy`,
1799            // rather than using the `is_copy_modulo_regions`
1800            // test. This is important because
1801            // `is_copy_modulo_regions` ignores the resulting region
1802            // obligations and assumes they pass. This can result in
1803            // bounds from `Copy` impls being unsoundly ignored (e.g.,
1804            // #29149). Note that we decide to use `Copy` before knowing
1805            // whether the bounds fully apply: in effect, the rule is
1806            // that if a value of some type could implement `Copy`, then
1807            // it must.
1808            self.prove_trait_ref(trait_ref, location.to_locations(), ConstraintCategory::CopyBound);
1809        }
1810    }
1811
1812    fn visit_projection_elem(
1813        &mut self,
1814        place: PlaceRef<'tcx>,
1815        elem: PlaceElem<'tcx>,
1816        context: PlaceContext,
1817        location: Location,
1818    ) {
1819        let tcx = self.tcx();
1820        let base_ty = place.ty(self.body(), tcx);
1821        match elem {
1822            // All these projections don't add any constraints, so there's nothing to
1823            // do here. We check their invariants in the MIR validator after all.
1824            ProjectionElem::Deref
1825            | ProjectionElem::Index(_)
1826            | ProjectionElem::ConstantIndex { .. }
1827            | ProjectionElem::Subslice { .. }
1828            | ProjectionElem::Downcast(..) => {}
1829            ProjectionElem::Field(field, fty) => {
1830                let fty = self.normalize(fty, location);
1831                let ty = PlaceTy::field_ty(tcx, base_ty.ty, base_ty.variant_index, field);
1832                let ty = self.normalize(ty, location);
1833                debug!(?fty, ?ty);
1834
1835                if let Err(terr) = self.relate_types(
1836                    ty,
1837                    context.ambient_variance(),
1838                    fty,
1839                    location.to_locations(),
1840                    ConstraintCategory::Boring,
1841                ) {
1842                    span_mirbug!(self, place, "bad field access ({:?}: {:?}): {:?}", ty, fty, terr);
1843                }
1844            }
1845            ProjectionElem::OpaqueCast(ty) => {
1846                let ty = self.normalize(ty, location);
1847                self.relate_types(
1848                    ty,
1849                    context.ambient_variance(),
1850                    base_ty.ty,
1851                    location.to_locations(),
1852                    ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
1853                )
1854                .unwrap();
1855            }
1856            ProjectionElem::UnwrapUnsafeBinder(ty) => {
1857                let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
1858                    unreachable!();
1859                };
1860                let found_ty = self.infcx.instantiate_binder_with_fresh_vars(
1861                    self.body.source_info(location).span,
1862                    BoundRegionConversionTime::HigherRankedType,
1863                    binder_ty.into(),
1864                );
1865                self.relate_types(
1866                    ty,
1867                    context.ambient_variance(),
1868                    found_ty,
1869                    location.to_locations(),
1870                    ConstraintCategory::Boring,
1871                )
1872                .unwrap();
1873            }
1874            ProjectionElem::Subtype(_) => {
1875                bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
1876            }
1877        }
1878    }
1879}
1880
1881impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1882    fn check_call_dest(
1883        &mut self,
1884        term: &Terminator<'tcx>,
1885        sig: &ty::FnSig<'tcx>,
1886        destination: Place<'tcx>,
1887        is_diverging: bool,
1888        term_location: Location,
1889    ) {
1890        let tcx = self.tcx();
1891        if is_diverging {
1892            // The signature in this call can reference region variables,
1893            // so erase them before calling a query.
1894            let output_ty = self.tcx().erase_regions(sig.output());
1895            if !output_ty
1896                .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env))
1897            {
1898                span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
1899            }
1900        } else {
1901            let dest_ty = destination.ty(self.body, tcx).ty;
1902            let dest_ty = self.normalize(dest_ty, term_location);
1903            let category = match destination.as_local() {
1904                Some(RETURN_PLACE) => {
1905                    if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
1906                        self.universal_regions.defining_ty
1907                    {
1908                        if tcx.is_static(def_id) {
1909                            ConstraintCategory::UseAsStatic
1910                        } else {
1911                            ConstraintCategory::UseAsConst
1912                        }
1913                    } else {
1914                        ConstraintCategory::Return(ReturnConstraint::Normal)
1915                    }
1916                }
1917                Some(l) if !self.body.local_decls[l].is_user_variable() => {
1918                    ConstraintCategory::Boring
1919                }
1920                // The return type of a call is interesting for diagnostics.
1921                _ => ConstraintCategory::Assignment,
1922            };
1923
1924            let locations = term_location.to_locations();
1925
1926            if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
1927                span_mirbug!(
1928                    self,
1929                    term,
1930                    "call dest mismatch ({:?} <- {:?}): {:?}",
1931                    dest_ty,
1932                    sig.output(),
1933                    terr
1934                );
1935            }
1936
1937            // When `unsized_fn_params` is not enabled,
1938            // this check is done at `check_local`.
1939            if self.unsized_feature_enabled() {
1940                let span = term.source_info.span;
1941                self.ensure_place_sized(dest_ty, span);
1942            }
1943        }
1944    }
1945
1946    #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
1947    fn check_call_inputs(
1948        &mut self,
1949        term: &Terminator<'tcx>,
1950        func: &Operand<'tcx>,
1951        sig: &ty::FnSig<'tcx>,
1952        args: &[Spanned<Operand<'tcx>>],
1953        term_location: Location,
1954        call_source: CallSource,
1955    ) {
1956        if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
1957            span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
1958        }
1959
1960        let func_ty = func.ty(self.body, self.infcx.tcx);
1961        if let ty::FnDef(def_id, _) = *func_ty.kind() {
1962            // Some of the SIMD intrinsics are special: they need a particular argument to be a
1963            // constant. (Eventually this should use const-generics, but those are not up for the
1964            // task yet: https://github.com/rust-lang/rust/issues/85229.)
1965            if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
1966                self.tcx().intrinsic(def_id).map(|i| i.name)
1967            {
1968                let idx = match name {
1969                    sym::simd_shuffle => 2,
1970                    _ => 1,
1971                };
1972                if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) {
1973                    self.tcx().dcx().emit_err(SimdIntrinsicArgConst {
1974                        span: term.source_info.span,
1975                        arg: idx + 1,
1976                        intrinsic: name.to_string(),
1977                    });
1978                }
1979            }
1980        }
1981        debug!(?func_ty);
1982
1983        for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
1984            let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
1985
1986            let op_arg_ty = self.normalize(op_arg_ty, term_location);
1987            let category = if call_source.from_hir_call() {
1988                ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
1989            } else {
1990                ConstraintCategory::Boring
1991            };
1992            if let Err(terr) =
1993                self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
1994            {
1995                span_mirbug!(
1996                    self,
1997                    term,
1998                    "bad arg #{:?} ({:?} <- {:?}): {:?}",
1999                    n,
2000                    fn_arg,
2001                    op_arg_ty,
2002                    terr
2003                );
2004            }
2005        }
2006    }
2007
2008    fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
2009        let is_cleanup = block_data.is_cleanup;
2010        match block_data.terminator().kind {
2011            TerminatorKind::Goto { target } => {
2012                self.assert_iscleanup(block_data, target, is_cleanup)
2013            }
2014            TerminatorKind::SwitchInt { ref targets, .. } => {
2015                for target in targets.all_targets() {
2016                    self.assert_iscleanup(block_data, *target, is_cleanup);
2017                }
2018            }
2019            TerminatorKind::UnwindResume => {
2020                if !is_cleanup {
2021                    span_mirbug!(self, block_data, "resume on non-cleanup block!")
2022                }
2023            }
2024            TerminatorKind::UnwindTerminate(_) => {
2025                if !is_cleanup {
2026                    span_mirbug!(self, block_data, "terminate on non-cleanup block!")
2027                }
2028            }
2029            TerminatorKind::Return => {
2030                if is_cleanup {
2031                    span_mirbug!(self, block_data, "return on cleanup block")
2032                }
2033            }
2034            TerminatorKind::TailCall { .. } => {
2035                if is_cleanup {
2036                    span_mirbug!(self, block_data, "tailcall on cleanup block")
2037                }
2038            }
2039            TerminatorKind::CoroutineDrop { .. } => {
2040                if is_cleanup {
2041                    span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
2042                }
2043            }
2044            TerminatorKind::Yield { resume, drop, .. } => {
2045                if is_cleanup {
2046                    span_mirbug!(self, block_data, "yield in cleanup block")
2047                }
2048                self.assert_iscleanup(block_data, resume, is_cleanup);
2049                if let Some(drop) = drop {
2050                    self.assert_iscleanup(block_data, drop, is_cleanup);
2051                }
2052            }
2053            TerminatorKind::Unreachable => {}
2054            TerminatorKind::Drop { target, unwind, drop, .. } => {
2055                self.assert_iscleanup(block_data, target, is_cleanup);
2056                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2057                if let Some(drop) = drop {
2058                    self.assert_iscleanup(block_data, drop, is_cleanup);
2059                }
2060            }
2061            TerminatorKind::Assert { target, unwind, .. } => {
2062                self.assert_iscleanup(block_data, target, is_cleanup);
2063                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2064            }
2065            TerminatorKind::Call { ref target, unwind, .. } => {
2066                if let &Some(target) = target {
2067                    self.assert_iscleanup(block_data, target, is_cleanup);
2068                }
2069                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2070            }
2071            TerminatorKind::FalseEdge { real_target, imaginary_target } => {
2072                self.assert_iscleanup(block_data, real_target, is_cleanup);
2073                self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
2074            }
2075            TerminatorKind::FalseUnwind { real_target, unwind } => {
2076                self.assert_iscleanup(block_data, real_target, is_cleanup);
2077                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2078            }
2079            TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
2080                for &target in targets {
2081                    self.assert_iscleanup(block_data, target, is_cleanup);
2082                }
2083                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2084            }
2085        }
2086    }
2087
2088    fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
2089        if self.body[bb].is_cleanup != iscleanuppad {
2090            span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
2091        }
2092    }
2093
2094    fn assert_iscleanup_unwind(
2095        &mut self,
2096        ctxt: &dyn fmt::Debug,
2097        unwind: UnwindAction,
2098        is_cleanup: bool,
2099    ) {
2100        match unwind {
2101            UnwindAction::Cleanup(unwind) => {
2102                if is_cleanup {
2103                    span_mirbug!(self, ctxt, "unwind on cleanup block")
2104                }
2105                self.assert_iscleanup(ctxt, unwind, true);
2106            }
2107            UnwindAction::Continue => {
2108                if is_cleanup {
2109                    span_mirbug!(self, ctxt, "unwind on cleanup block")
2110                }
2111            }
2112            UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
2113        }
2114    }
2115
2116    fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
2117        let tcx = self.tcx();
2118
2119        // Erase the regions from `ty` to get a global type. The
2120        // `Sized` bound in no way depends on precise regions, so this
2121        // shouldn't affect `is_sized`.
2122        let erased_ty = tcx.erase_regions(ty);
2123        // FIXME(#132279): Using `Ty::is_sized` causes us to incorrectly handle opaques here.
2124        if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
2125            // in current MIR construction, all non-control-flow rvalue
2126            // expressions evaluate through `as_temp` or `into` a return
2127            // slot or local, so to find all unsized rvalues it is enough
2128            // to check all temps, return slots and locals.
2129            if self.reported_errors.replace((ty, span)).is_none() {
2130                // While this is located in `nll::typeck` this error is not
2131                // an NLL error, it's a required check to prevent creation
2132                // of unsized rvalues in a call expression.
2133                self.tcx().dcx().emit_err(MoveUnsized { ty, span });
2134            }
2135        }
2136    }
2137
2138    fn aggregate_field_ty(
2139        &mut self,
2140        ak: &AggregateKind<'tcx>,
2141        field_index: FieldIdx,
2142        location: Location,
2143    ) -> Result<Ty<'tcx>, FieldAccessError> {
2144        let tcx = self.tcx();
2145
2146        match *ak {
2147            AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
2148                let def = tcx.adt_def(adt_did);
2149                let variant = &def.variant(variant_index);
2150                let adj_field_index = active_field_index.unwrap_or(field_index);
2151                if let Some(field) = variant.fields.get(adj_field_index) {
2152                    Ok(self.normalize(field.ty(tcx, args), location))
2153                } else {
2154                    Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
2155                }
2156            }
2157            AggregateKind::Closure(_, args) => {
2158                match args.as_closure().upvar_tys().get(field_index.as_usize()) {
2159                    Some(ty) => Ok(*ty),
2160                    None => Err(FieldAccessError::OutOfRange {
2161                        field_count: args.as_closure().upvar_tys().len(),
2162                    }),
2163                }
2164            }
2165            AggregateKind::Coroutine(_, args) => {
2166                // It doesn't make sense to look at a field beyond the prefix;
2167                // these require a variant index, and are not initialized in
2168                // aggregate rvalues.
2169                match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
2170                    Some(ty) => Ok(*ty),
2171                    None => Err(FieldAccessError::OutOfRange {
2172                        field_count: args.as_coroutine().prefix_tys().len(),
2173                    }),
2174                }
2175            }
2176            AggregateKind::CoroutineClosure(_, args) => {
2177                match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
2178                    Some(ty) => Ok(*ty),
2179                    None => Err(FieldAccessError::OutOfRange {
2180                        field_count: args.as_coroutine_closure().upvar_tys().len(),
2181                    }),
2182                }
2183            }
2184            AggregateKind::Array(ty) => Ok(ty),
2185            AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
2186                unreachable!("This should have been covered in check_rvalues");
2187            }
2188        }
2189    }
2190
2191    /// If this rvalue supports a user-given type annotation, then
2192    /// extract and return it. This represents the final type of the
2193    /// rvalue and will be unified with the inferred type.
2194    fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex> {
2195        match rvalue {
2196            Rvalue::Use(_)
2197            | Rvalue::ThreadLocalRef(_)
2198            | Rvalue::Repeat(..)
2199            | Rvalue::Ref(..)
2200            | Rvalue::RawPtr(..)
2201            | Rvalue::Len(..)
2202            | Rvalue::Cast(..)
2203            | Rvalue::ShallowInitBox(..)
2204            | Rvalue::BinaryOp(..)
2205            | Rvalue::NullaryOp(..)
2206            | Rvalue::CopyForDeref(..)
2207            | Rvalue::UnaryOp(..)
2208            | Rvalue::Discriminant(..)
2209            | Rvalue::WrapUnsafeBinder(..) => None,
2210
2211            Rvalue::Aggregate(aggregate, _) => match **aggregate {
2212                AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,
2213                AggregateKind::Array(_) => None,
2214                AggregateKind::Tuple => None,
2215                AggregateKind::Closure(_, _) => None,
2216                AggregateKind::Coroutine(_, _) => None,
2217                AggregateKind::CoroutineClosure(_, _) => None,
2218                AggregateKind::RawPtr(_, _) => None,
2219            },
2220        }
2221    }
2222
2223    fn check_aggregate_rvalue(
2224        &mut self,
2225        rvalue: &Rvalue<'tcx>,
2226        aggregate_kind: &AggregateKind<'tcx>,
2227        operands: &IndexSlice<FieldIdx, Operand<'tcx>>,
2228        location: Location,
2229    ) {
2230        let tcx = self.tcx();
2231
2232        self.prove_aggregate_predicates(aggregate_kind, location);
2233
2234        if *aggregate_kind == AggregateKind::Tuple {
2235            // tuple rvalue field type is always the type of the op. Nothing to check here.
2236            return;
2237        }
2238
2239        if let AggregateKind::RawPtr(..) = aggregate_kind {
2240            bug!("RawPtr should only be in runtime MIR");
2241        }
2242
2243        for (i, operand) in operands.iter_enumerated() {
2244            let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
2245                Ok(field_ty) => field_ty,
2246                Err(FieldAccessError::OutOfRange { field_count }) => {
2247                    span_mirbug!(
2248                        self,
2249                        rvalue,
2250                        "accessed field #{} but variant only has {}",
2251                        i.as_u32(),
2252                        field_count,
2253                    );
2254                    continue;
2255                }
2256            };
2257            let operand_ty = operand.ty(self.body, tcx);
2258            let operand_ty = self.normalize(operand_ty, location);
2259
2260            if let Err(terr) = self.sub_types(
2261                operand_ty,
2262                field_ty,
2263                location.to_locations(),
2264                ConstraintCategory::Boring,
2265            ) {
2266                span_mirbug!(
2267                    self,
2268                    rvalue,
2269                    "{:?} is not a subtype of {:?}: {:?}",
2270                    operand_ty,
2271                    field_ty,
2272                    terr
2273                );
2274            }
2275        }
2276    }
2277
2278    /// Adds the constraints that arise from a borrow expression `&'a P` at the location `L`.
2279    ///
2280    /// # Parameters
2281    ///
2282    /// - `location`: the location `L` where the borrow expression occurs
2283    /// - `borrow_region`: the region `'a` associated with the borrow
2284    /// - `borrowed_place`: the place `P` being borrowed
2285    fn add_reborrow_constraint(
2286        &mut self,
2287        location: Location,
2288        borrow_region: ty::Region<'tcx>,
2289        borrowed_place: &Place<'tcx>,
2290    ) {
2291        // These constraints are only meaningful during borrowck:
2292        let Self { borrow_set, location_table, polonius_facts, constraints, .. } = self;
2293
2294        // In Polonius mode, we also push a `loan_issued_at` fact
2295        // linking the loan to the region (in some cases, though,
2296        // there is no loan associated with this borrow expression --
2297        // that occurs when we are borrowing an unsafe place, for
2298        // example).
2299        if let Some(polonius_facts) = polonius_facts {
2300            let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
2301            if let Some(borrow_index) = borrow_set.get_index_of(&location) {
2302                let region_vid = borrow_region.as_var();
2303                polonius_facts.loan_issued_at.push((
2304                    region_vid.into(),
2305                    borrow_index,
2306                    location_table.mid_index(location),
2307                ));
2308            }
2309        }
2310
2311        // If we are reborrowing the referent of another reference, we
2312        // need to add outlives relationships. In a case like `&mut
2313        // *p`, where the `p` has type `&'b mut Foo`, for example, we
2314        // need to ensure that `'b: 'a`.
2315
2316        debug!(
2317            "add_reborrow_constraint({:?}, {:?}, {:?})",
2318            location, borrow_region, borrowed_place
2319        );
2320
2321        let tcx = self.infcx.tcx;
2322        let def = self.body.source.def_id().expect_local();
2323        let upvars = tcx.closure_captures(def);
2324        let field =
2325            path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), self.body);
2326        let category = if let Some(field) = field {
2327            ConstraintCategory::ClosureUpvar(field)
2328        } else {
2329            ConstraintCategory::Boring
2330        };
2331
2332        for (base, elem) in borrowed_place.as_ref().iter_projections().rev() {
2333            debug!("add_reborrow_constraint - iteration {:?}", elem);
2334
2335            match elem {
2336                ProjectionElem::Deref => {
2337                    let base_ty = base.ty(self.body, tcx).ty;
2338
2339                    debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
2340                    match base_ty.kind() {
2341                        ty::Ref(ref_region, _, mutbl) => {
2342                            constraints.outlives_constraints.push(OutlivesConstraint {
2343                                sup: ref_region.as_var(),
2344                                sub: borrow_region.as_var(),
2345                                locations: location.to_locations(),
2346                                span: location.to_locations().span(self.body),
2347                                category,
2348                                variance_info: ty::VarianceDiagInfo::default(),
2349                                from_closure: false,
2350                            });
2351
2352                            match mutbl {
2353                                hir::Mutability::Not => {
2354                                    // Immutable reference. We don't need the base
2355                                    // to be valid for the entire lifetime of
2356                                    // the borrow.
2357                                    break;
2358                                }
2359                                hir::Mutability::Mut => {
2360                                    // Mutable reference. We *do* need the base
2361                                    // to be valid, because after the base becomes
2362                                    // invalid, someone else can use our mutable deref.
2363
2364                                    // This is in order to make the following function
2365                                    // illegal:
2366                                    // ```
2367                                    // fn unsafe_deref<'a, 'b>(x: &'a &'b mut T) -> &'b mut T {
2368                                    //     &mut *x
2369                                    // }
2370                                    // ```
2371                                    //
2372                                    // As otherwise you could clone `&mut T` using the
2373                                    // following function:
2374                                    // ```
2375                                    // fn bad(x: &mut T) -> (&mut T, &mut T) {
2376                                    //     let my_clone = unsafe_deref(&'a x);
2377                                    //     ENDREGION 'a;
2378                                    //     (my_clone, x)
2379                                    // }
2380                                    // ```
2381                                }
2382                            }
2383                        }
2384                        ty::RawPtr(..) => {
2385                            // deref of raw pointer, guaranteed to be valid
2386                            break;
2387                        }
2388                        ty::Adt(def, _) if def.is_box() => {
2389                            // deref of `Box`, need the base to be valid - propagate
2390                        }
2391                        _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
2392                    }
2393                }
2394                ProjectionElem::Field(..)
2395                | ProjectionElem::Downcast(..)
2396                | ProjectionElem::OpaqueCast(..)
2397                | ProjectionElem::Index(..)
2398                | ProjectionElem::ConstantIndex { .. }
2399                | ProjectionElem::Subslice { .. }
2400                | ProjectionElem::UnwrapUnsafeBinder(_) => {
2401                    // other field access
2402                }
2403                ProjectionElem::Subtype(_) => {
2404                    bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
2405                }
2406            }
2407        }
2408    }
2409
2410    fn prove_aggregate_predicates(
2411        &mut self,
2412        aggregate_kind: &AggregateKind<'tcx>,
2413        location: Location,
2414    ) {
2415        let tcx = self.tcx();
2416
2417        debug!(
2418            "prove_aggregate_predicates(aggregate_kind={:?}, location={:?})",
2419            aggregate_kind, location
2420        );
2421
2422        let (def_id, instantiated_predicates) = match *aggregate_kind {
2423            AggregateKind::Adt(adt_did, _, args, _, _) => {
2424                (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, args))
2425            }
2426
2427            // For closures, we have some **extra requirements** we
2428            // have to check. In particular, in their upvars and
2429            // signatures, closures often reference various regions
2430            // from the surrounding function -- we call those the
2431            // closure's free regions. When we borrow-check (and hence
2432            // region-check) closures, we may find that the closure
2433            // requires certain relationships between those free
2434            // regions. However, because those free regions refer to
2435            // portions of the CFG of their caller, the closure is not
2436            // in a position to verify those relationships. In that
2437            // case, the requirements get "propagated" to us, and so
2438            // we have to solve them here where we instantiate the
2439            // closure.
2440            //
2441            // Despite the opacity of the previous paragraph, this is
2442            // actually relatively easy to understand in terms of the
2443            // desugaring. A closure gets desugared to a struct, and
2444            // these extra requirements are basically like where
2445            // clauses on the struct.
2446            AggregateKind::Closure(def_id, args)
2447            | AggregateKind::CoroutineClosure(def_id, args)
2448            | AggregateKind::Coroutine(def_id, args) => (
2449                def_id,
2450                self.prove_closure_bounds(
2451                    tcx,
2452                    def_id.expect_local(),
2453                    args,
2454                    location.to_locations(),
2455                ),
2456            ),
2457
2458            AggregateKind::Array(_) | AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
2459                (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
2460            }
2461        };
2462
2463        self.normalize_and_prove_instantiated_predicates(
2464            def_id,
2465            instantiated_predicates,
2466            location.to_locations(),
2467        );
2468    }
2469
2470    fn prove_closure_bounds(
2471        &mut self,
2472        tcx: TyCtxt<'tcx>,
2473        def_id: LocalDefId,
2474        args: GenericArgsRef<'tcx>,
2475        locations: Locations,
2476    ) -> ty::InstantiatedPredicates<'tcx> {
2477        if let Some(closure_requirements) = &self.root_cx.closure_requirements(def_id) {
2478            constraint_conversion::ConstraintConversion::new(
2479                self.infcx,
2480                self.universal_regions,
2481                self.region_bound_pairs,
2482                self.infcx.param_env,
2483                self.known_type_outlives_obligations,
2484                locations,
2485                self.body.span,             // irrelevant; will be overridden.
2486                ConstraintCategory::Boring, // same as above.
2487                self.constraints,
2488            )
2489            .apply_closure_requirements(closure_requirements, def_id, args);
2490        }
2491
2492        // Now equate closure args to regions inherited from `typeck_root_def_id`. Fixes #98589.
2493        let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
2494        let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
2495
2496        let parent_args = match tcx.def_kind(def_id) {
2497            // We don't want to dispatch on 3 different kind of closures here, so take
2498            // advantage of the fact that the `parent_args` is the same length as the
2499            // `typeck_root_args`.
2500            DefKind::Closure => {
2501                // FIXME(async_closures): It may be useful to add a debug assert here
2502                // to actually call `type_of` and check the `parent_args` are the same
2503                // length as the `typeck_root_args`.
2504                &args[..typeck_root_args.len()]
2505            }
2506            DefKind::InlineConst => args.as_inline_const().parent_args(),
2507            other => bug!("unexpected item {:?}", other),
2508        };
2509        let parent_args = tcx.mk_args(parent_args);
2510
2511        assert_eq!(typeck_root_args.len(), parent_args.len());
2512        if let Err(_) = self.eq_args(
2513            typeck_root_args,
2514            parent_args,
2515            locations,
2516            ConstraintCategory::BoringNoLocation,
2517        ) {
2518            span_mirbug!(
2519                self,
2520                def_id,
2521                "could not relate closure to parent {:?} != {:?}",
2522                typeck_root_args,
2523                parent_args
2524            );
2525        }
2526
2527        tcx.predicates_of(def_id).instantiate(tcx, args)
2528    }
2529}
2530
2531trait NormalizeLocation: fmt::Debug + Copy {
2532    fn to_locations(self) -> Locations;
2533}
2534
2535impl NormalizeLocation for Locations {
2536    fn to_locations(self) -> Locations {
2537        self
2538    }
2539}
2540
2541impl NormalizeLocation for Location {
2542    fn to_locations(self) -> Locations {
2543        Locations::Single(self)
2544    }
2545}
2546
2547/// Runs `infcx.instantiate_opaque_types`. Unlike other `TypeOp`s,
2548/// this is not canonicalized - it directly affects the main `InferCtxt`
2549/// that we use during MIR borrowchecking.
2550#[derive(Debug)]
2551pub(super) struct InstantiateOpaqueType<'tcx> {
2552    pub base_universe: Option<ty::UniverseIndex>,
2553    pub region_constraints: Option<RegionConstraintData<'tcx>>,
2554    pub obligations: PredicateObligations<'tcx>,
2555}
2556
2557impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
2558    type Output = ();
2559    /// We use this type itself to store the information used
2560    /// when reporting errors. Since this is not a query, we don't
2561    /// re-run anything during error reporting - we just use the information
2562    /// we saved to help extract an error from the already-existing region
2563    /// constraints in our `InferCtxt`
2564    type ErrorInfo = InstantiateOpaqueType<'tcx>;
2565
2566    fn fully_perform(
2567        mut self,
2568        infcx: &InferCtxt<'tcx>,
2569        span: Span,
2570    ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
2571        let (mut output, region_constraints) = scrape_region_constraints(
2572            infcx,
2573            |ocx| {
2574                ocx.register_obligations(self.obligations.clone());
2575                Ok(())
2576            },
2577            "InstantiateOpaqueType",
2578            span,
2579        )?;
2580        self.region_constraints = Some(region_constraints);
2581        output.error_info = Some(self);
2582        Ok(output)
2583    }
2584}