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