rustc_borrowck/type_check/
mod.rs

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