rustc_borrowck/type_check/
mod.rs

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