rustc_borrowck/type_check/
mod.rs

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