rustc_borrowck/type_check/
mod.rs

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