rustc_borrowck/type_check/
mod.rs

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