rustc_borrowck/type_check/
mod.rs

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