1use std::rc::Rc;
4use std::{fmt, iter, mem};
5
6use rustc_abi::FieldIdx;
7use rustc_data_structures::frozen::Frozen;
8use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
9use rustc_errors::ErrorGuaranteed;
10use rustc_hir as hir;
11use rustc_hir::def::DefKind;
12use rustc_hir::def_id::LocalDefId;
13use rustc_hir::lang_items::LangItem;
14use rustc_index::{IndexSlice, IndexVec};
15use rustc_infer::infer::canonical::QueryRegionConstraints;
16use rustc_infer::infer::outlives::env::RegionBoundPairs;
17use rustc_infer::infer::region_constraints::RegionConstraintData;
18use rustc_infer::infer::{
19 BoundRegionConversionTime, InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin,
20};
21use rustc_infer::traits::PredicateObligations;
22use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
23use rustc_middle::mir::*;
24use rustc_middle::traits::query::NoSolution;
25use rustc_middle::ty::adjustment::PointerCoercion;
26use rustc_middle::ty::cast::CastTy;
27use rustc_middle::ty::{
28 self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
29 GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions,
30};
31use rustc_middle::{bug, span_bug};
32use rustc_mir_dataflow::move_paths::MoveData;
33use rustc_mir_dataflow::points::DenseLocationMap;
34use rustc_span::def_id::CRATE_DEF_ID;
35use rustc_span::source_map::Spanned;
36use rustc_span::{Span, sym};
37use rustc_trait_selection::infer::InferCtxtExt;
38use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
39use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
40use tracing::{debug, instrument, trace};
41
42use crate::borrow_set::BorrowSet;
43use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
44use crate::diagnostics::UniverseInfo;
45use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
46use crate::polonius::{PoloniusContext, PoloniusLivenessContext};
47use crate::region_infer::TypeTest;
48use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices};
49use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
50use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations};
51use crate::universal_regions::{DefiningTy, UniversalRegions};
52use crate::{BorrowCheckRootCtxt, BorrowckInferCtxt, path_utils};
53
54macro_rules! span_mirbug {
55 ($context:expr, $elem:expr, $($message:tt)*) => ({
56 $crate::type_check::mirbug(
57 $context.tcx(),
58 $context.last_span,
59 format!(
60 "broken MIR in {:?} ({:?}): {}",
61 $context.body().source.def_id(),
62 $elem,
63 format_args!($($message)*),
64 ),
65 )
66 })
67}
68
69pub(crate) mod canonical;
70mod constraint_conversion;
71pub(crate) mod free_region_relations;
72mod input_output;
73pub(crate) mod liveness;
74mod relate_tys;
75
76pub(crate) fn type_check<'tcx>(
99 root_cx: &mut BorrowCheckRootCtxt<'tcx>,
100 infcx: &BorrowckInferCtxt<'tcx>,
101 body: &Body<'tcx>,
102 promoted: &IndexSlice<Promoted, Body<'tcx>>,
103 universal_regions: UniversalRegions<'tcx>,
104 location_table: &PoloniusLocationTable,
105 borrow_set: &BorrowSet<'tcx>,
106 polonius_facts: &mut Option<PoloniusFacts>,
107 move_data: &MoveData<'tcx>,
108 location_map: Rc<DenseLocationMap>,
109) -> MirTypeckResults<'tcx> {
110 let mut constraints = MirTypeckRegionConstraints {
111 placeholder_indices: PlaceholderIndices::default(),
112 placeholder_index_to_region: IndexVec::default(),
113 liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&location_map)),
114 outlives_constraints: OutlivesConstraintSet::default(),
115 type_tests: Vec::default(),
116 universe_causes: FxIndexMap::default(),
117 };
118
119 let CreateResult {
120 universal_region_relations,
121 region_bound_pairs,
122 normalized_inputs_and_output,
123 known_type_outlives_obligations,
124 } = free_region_relations::create(infcx, universal_regions, &mut constraints);
125
126 let pre_obligations = infcx.take_registered_region_obligations();
127 assert!(
128 pre_obligations.is_empty(),
129 "there should be no incoming region obligations = {pre_obligations:#?}",
130 );
131 let pre_assumptions = infcx.take_registered_region_assumptions();
132 assert!(
133 pre_assumptions.is_empty(),
134 "there should be no incoming region assumptions = {pre_assumptions:#?}",
135 );
136
137 debug!(?normalized_inputs_and_output);
138
139 let polonius_liveness = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
140 Some(PoloniusLivenessContext::default())
141 } else {
142 None
143 };
144
145 let mut typeck = TypeChecker {
146 root_cx,
147 infcx,
148 last_span: body.span,
149 body,
150 promoted,
151 user_type_annotations: &body.user_type_annotations,
152 region_bound_pairs: ®ion_bound_pairs,
153 known_type_outlives_obligations: &known_type_outlives_obligations,
154 reported_errors: Default::default(),
155 universal_regions: &universal_region_relations.universal_regions,
156 location_table,
157 polonius_facts,
158 borrow_set,
159 constraints: &mut constraints,
160 polonius_liveness,
161 };
162
163 typeck.check_user_type_annotations();
164 typeck.visit_body(body);
165 typeck.equate_inputs_and_outputs(&normalized_inputs_and_output);
166 typeck.check_signature_annotation();
167
168 liveness::generate(&mut typeck, &location_map, move_data);
169
170 let polonius_context = typeck.polonius_liveness.take().map(|liveness_context| {
172 PoloniusContext::create_from_liveness(
173 liveness_context,
174 infcx.num_region_vars(),
175 typeck.constraints.liveness_constraints.points(),
176 )
177 });
178
179 if let Some(guar) = universal_region_relations.universal_regions.encountered_re_error() {
182 debug!("encountered an error region; removing constraints!");
183 constraints.outlives_constraints = Default::default();
184 constraints.type_tests = Default::default();
185 root_cx.set_tainted_by_errors(guar);
186 infcx.set_tainted_by_errors(guar);
187 }
188
189 MirTypeckResults {
190 constraints,
191 universal_region_relations,
192 region_bound_pairs,
193 known_type_outlives_obligations,
194 polonius_context,
195 }
196}
197
198#[track_caller]
199fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
200 tcx.dcx().span_delayed_bug(span, msg);
204}
205
206enum FieldAccessError {
207 OutOfRange { field_count: usize },
208}
209
210struct TypeChecker<'a, 'tcx> {
215 root_cx: &'a mut BorrowCheckRootCtxt<'tcx>,
216 infcx: &'a BorrowckInferCtxt<'tcx>,
217 last_span: Span,
218 body: &'a Body<'tcx>,
219 promoted: &'a IndexSlice<Promoted, Body<'tcx>>,
222 user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
225 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
226 known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
227 reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
228 universal_regions: &'a UniversalRegions<'tcx>,
229 location_table: &'a PoloniusLocationTable,
230 polonius_facts: &'a mut Option<PoloniusFacts>,
231 borrow_set: &'a BorrowSet<'tcx>,
232 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
233 polonius_liveness: Option<PoloniusLivenessContext>,
235}
236
237pub(crate) struct MirTypeckResults<'tcx> {
240 pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
241 pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
242 pub(crate) region_bound_pairs: Frozen<RegionBoundPairs<'tcx>>,
243 pub(crate) known_type_outlives_obligations: Frozen<Vec<ty::PolyTypeOutlivesPredicate<'tcx>>>,
244 pub(crate) polonius_context: Option<PoloniusContext>,
245}
246
247pub(crate) struct MirTypeckRegionConstraints<'tcx> {
250 pub(crate) placeholder_indices: PlaceholderIndices,
256
257 pub(crate) placeholder_index_to_region: IndexVec<PlaceholderIndex, ty::Region<'tcx>>,
263
264 pub(crate) liveness_constraints: LivenessValues,
272
273 pub(crate) outlives_constraints: OutlivesConstraintSet<'tcx>,
274
275 pub(crate) universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
276
277 pub(crate) type_tests: Vec<TypeTest<'tcx>>,
278}
279
280impl<'tcx> MirTypeckRegionConstraints<'tcx> {
281 pub(crate) fn placeholder_region(
284 &mut self,
285 infcx: &InferCtxt<'tcx>,
286 placeholder: ty::PlaceholderRegion,
287 ) -> ty::Region<'tcx> {
288 let placeholder_index = self.placeholder_indices.insert(placeholder);
289 match self.placeholder_index_to_region.get(placeholder_index) {
290 Some(&v) => v,
291 None => {
292 let origin = NllRegionVariableOrigin::Placeholder(placeholder);
293 let region = infcx.next_nll_region_var_in_universe(origin, placeholder.universe);
294 self.placeholder_index_to_region.push(region);
295 region
296 }
297 }
298 }
299}
300
301#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
306pub enum Locations {
307 All(Span),
343
344 Single(Location),
348}
349
350impl Locations {
351 pub fn from_location(&self) -> Option<Location> {
352 match self {
353 Locations::All(_) => None,
354 Locations::Single(from_location) => Some(*from_location),
355 }
356 }
357
358 pub fn span(&self, body: &Body<'_>) -> Span {
360 match self {
361 Locations::All(span) => *span,
362 Locations::Single(l) => body.source_info(*l).span,
363 }
364 }
365}
366
367impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
368 fn tcx(&self) -> TyCtxt<'tcx> {
369 self.infcx.tcx
370 }
371
372 fn body(&self) -> &Body<'tcx> {
373 self.body
374 }
375
376 fn unsized_feature_enabled(&self) -> bool {
377 self.tcx().features().unsized_fn_params()
378 }
379
380 #[instrument(skip(self), level = "debug")]
382 fn check_user_type_annotations(&mut self) {
383 debug!(?self.user_type_annotations);
384 let tcx = self.tcx();
385 for user_annotation in self.user_type_annotations {
386 let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
387 let annotation = self.instantiate_canonical(span, user_ty);
388 if let ty::UserTypeKind::TypeOf(def, args) = annotation.kind
389 && let DefKind::InlineConst = tcx.def_kind(def)
390 {
391 assert!(annotation.bounds.is_empty());
392 self.check_inline_const(inferred_ty, def.expect_local(), args, span);
393 } else {
394 self.ascribe_user_type(inferred_ty, annotation, span);
395 }
396 }
397 }
398
399 #[instrument(skip(self, data), level = "debug")]
400 fn push_region_constraints(
401 &mut self,
402 locations: Locations,
403 category: ConstraintCategory<'tcx>,
404 data: &QueryRegionConstraints<'tcx>,
405 ) {
406 debug!("constraints generated: {:#?}", data);
407
408 constraint_conversion::ConstraintConversion::new(
409 self.infcx,
410 self.universal_regions,
411 self.region_bound_pairs,
412 self.known_type_outlives_obligations,
413 locations,
414 locations.span(self.body),
415 category,
416 self.constraints,
417 )
418 .convert_all(data);
419 }
420
421 fn sub_types(
423 &mut self,
424 sub: Ty<'tcx>,
425 sup: Ty<'tcx>,
426 locations: Locations,
427 category: ConstraintCategory<'tcx>,
428 ) -> Result<(), NoSolution> {
429 self.relate_types(sup, ty::Contravariant, sub, locations, category)
432 }
433
434 #[instrument(skip(self, category), level = "debug")]
435 fn eq_types(
436 &mut self,
437 expected: Ty<'tcx>,
438 found: Ty<'tcx>,
439 locations: Locations,
440 category: ConstraintCategory<'tcx>,
441 ) -> Result<(), NoSolution> {
442 self.relate_types(expected, ty::Invariant, found, locations, category)
443 }
444
445 #[instrument(skip(self), level = "debug")]
446 fn relate_type_and_user_type(
447 &mut self,
448 a: Ty<'tcx>,
449 v: ty::Variance,
450 user_ty: &UserTypeProjection,
451 locations: Locations,
452 category: ConstraintCategory<'tcx>,
453 ) -> Result<(), NoSolution> {
454 let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
455 trace!(?annotated_type);
456 let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
457
458 let tcx = self.infcx.tcx;
459
460 for proj in &user_ty.projs {
461 if !self.infcx.next_trait_solver()
462 && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind()
463 {
464 return Ok(());
468 }
469 let projected_ty = curr_projected_ty.projection_ty_core(
470 tcx,
471 proj,
472 |ty| self.structurally_resolve(ty, locations),
473 |ty, variant_index, field, ()| PlaceTy::field_ty(tcx, ty, variant_index, field),
474 |_| unreachable!(),
475 );
476 curr_projected_ty = projected_ty;
477 }
478 trace!(?curr_projected_ty);
479
480 let a = self.normalize(a, locations);
483 let ty = self.normalize(curr_projected_ty.ty, locations);
484 self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
485
486 Ok(())
487 }
488
489 fn check_promoted(&mut self, promoted_body: &'a Body<'tcx>, location: Location) {
490 let parent_body = mem::replace(&mut self.body, promoted_body);
495
496 let polonius_facts = &mut None;
499 let mut constraints = Default::default();
500 let mut liveness_constraints =
501 LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
502
503 let mut swap_constraints = |this: &mut Self| {
506 mem::swap(this.polonius_facts, polonius_facts);
507 mem::swap(&mut this.constraints.outlives_constraints, &mut constraints);
508 mem::swap(&mut this.constraints.liveness_constraints, &mut liveness_constraints);
509 };
510
511 swap_constraints(self);
512
513 self.visit_body(promoted_body);
514
515 self.body = parent_body;
516
517 swap_constraints(self);
519 let locations = location.to_locations();
520 for constraint in constraints.outlives().iter() {
521 let mut constraint = *constraint;
522 constraint.locations = locations;
523 if let ConstraintCategory::Return(_)
524 | ConstraintCategory::UseAsConst
525 | ConstraintCategory::UseAsStatic = constraint.category
526 {
527 constraint.category = ConstraintCategory::Boring;
530 }
531 self.constraints.outlives_constraints.push(constraint)
532 }
533 #[allow(rustc::potential_query_instability)]
540 for region in liveness_constraints.live_regions_unordered() {
541 self.constraints.liveness_constraints.add_location(region, location);
542 }
543 }
544
545 fn check_inline_const(
546 &mut self,
547 inferred_ty: Ty<'tcx>,
548 def_id: LocalDefId,
549 args: UserArgs<'tcx>,
550 span: Span,
551 ) {
552 assert!(args.user_self_ty.is_none());
553 let tcx = self.tcx();
554 let const_ty = tcx.type_of(def_id).instantiate(tcx, args.args);
555 if let Err(terr) =
556 self.eq_types(const_ty, inferred_ty, Locations::All(span), ConstraintCategory::Boring)
557 {
558 span_bug!(
559 span,
560 "bad inline const pattern: ({:?} = {:?}) {:?}",
561 const_ty,
562 inferred_ty,
563 terr
564 );
565 }
566 let args = self.infcx.resolve_vars_if_possible(args.args);
567 let predicates = self.prove_closure_bounds(tcx, def_id, args, Locations::All(span));
568 self.normalize_and_prove_instantiated_predicates(
569 def_id.to_def_id(),
570 predicates,
571 Locations::All(span),
572 );
573 }
574}
575
576impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
577 fn visit_span(&mut self, span: Span) {
578 if !span.is_dummy() {
579 debug!(?span);
580 self.last_span = span;
581 }
582 }
583
584 #[instrument(skip(self, body), level = "debug")]
585 fn visit_body(&mut self, body: &Body<'tcx>) {
586 debug_assert!(std::ptr::eq(self.body, body));
587
588 for (local, local_decl) in body.local_decls.iter_enumerated() {
589 self.visit_local_decl(local, local_decl);
590 }
591
592 for (block, block_data) in body.basic_blocks.iter_enumerated() {
593 let mut location = Location { block, statement_index: 0 };
594 for stmt in &block_data.statements {
595 self.visit_statement(stmt, location);
596 location.statement_index += 1;
597 }
598
599 self.visit_terminator(block_data.terminator(), location);
600 self.check_iscleanup(block_data);
601 }
602 }
603
604 #[instrument(skip(self), level = "debug")]
605 fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
606 self.super_statement(stmt, location);
607 let tcx = self.tcx();
608 match &stmt.kind {
609 StatementKind::Assign(box (place, rv)) => {
610 let category = match place.as_local() {
615 Some(RETURN_PLACE) => {
616 let defining_ty = &self.universal_regions.defining_ty;
617 if defining_ty.is_const() {
618 if tcx.is_static(defining_ty.def_id()) {
619 ConstraintCategory::UseAsStatic
620 } else {
621 ConstraintCategory::UseAsConst
622 }
623 } else {
624 ConstraintCategory::Return(ReturnConstraint::Normal)
625 }
626 }
627 Some(l)
628 if matches!(
629 self.body.local_decls[l].local_info(),
630 LocalInfo::AggregateTemp
631 ) =>
632 {
633 ConstraintCategory::Usage
634 }
635 Some(l) if !self.body.local_decls[l].is_user_variable() => {
636 ConstraintCategory::Boring
637 }
638 _ => ConstraintCategory::Assignment,
639 };
640 debug!(
641 "assignment category: {:?} {:?}",
642 category,
643 place.as_local().map(|l| &self.body.local_decls[l])
644 );
645
646 let place_ty = place.ty(self.body, tcx).ty;
647 debug!(?place_ty);
648 let place_ty = self.normalize(place_ty, location);
649 debug!("place_ty normalized: {:?}", place_ty);
650 let rv_ty = rv.ty(self.body, tcx);
651 debug!(?rv_ty);
652 let rv_ty = self.normalize(rv_ty, location);
653 debug!("normalized rv_ty: {:?}", rv_ty);
654 if let Err(terr) =
655 self.sub_types(rv_ty, place_ty, location.to_locations(), category)
656 {
657 span_mirbug!(
658 self,
659 stmt,
660 "bad assignment ({:?} = {:?}): {:?}",
661 place_ty,
662 rv_ty,
663 terr
664 );
665 }
666
667 if let Some(annotation_index) = self.rvalue_user_ty(rv)
668 && let Err(terr) = self.relate_type_and_user_type(
669 rv_ty,
670 ty::Invariant,
671 &UserTypeProjection { base: annotation_index, projs: vec![] },
672 location.to_locations(),
673 ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
674 )
675 {
676 let annotation = &self.user_type_annotations[annotation_index];
677 span_mirbug!(
678 self,
679 stmt,
680 "bad user type on rvalue ({:?} = {:?}): {:?}",
681 annotation,
682 rv_ty,
683 terr
684 );
685 }
686
687 if !self.unsized_feature_enabled() {
688 let trait_ref = ty::TraitRef::new(
689 tcx,
690 tcx.require_lang_item(LangItem::Sized, self.last_span),
691 [place_ty],
692 );
693 self.prove_trait_ref(
694 trait_ref,
695 location.to_locations(),
696 ConstraintCategory::SizedBound,
697 );
698 }
699 }
700 StatementKind::AscribeUserType(box (place, projection), variance) => {
701 let place_ty = place.ty(self.body, tcx).ty;
702 if let Err(terr) = self.relate_type_and_user_type(
703 place_ty,
704 *variance,
705 projection,
706 Locations::All(stmt.source_info.span),
707 ConstraintCategory::TypeAnnotation(AnnotationSource::Ascription),
708 ) {
709 let annotation = &self.user_type_annotations[projection.base];
710 span_mirbug!(
711 self,
712 stmt,
713 "bad type assert ({:?} <: {:?} with projections {:?}): {:?}",
714 place_ty,
715 annotation,
716 projection.projs,
717 terr
718 );
719 }
720 }
721 StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..))
722 | StatementKind::FakeRead(..)
723 | StatementKind::StorageLive(..)
724 | StatementKind::StorageDead(..)
725 | StatementKind::Retag { .. }
726 | StatementKind::Coverage(..)
727 | StatementKind::ConstEvalCounter
728 | StatementKind::PlaceMention(..)
729 | StatementKind::BackwardIncompatibleDropHint { .. }
730 | StatementKind::Nop => {}
731 StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..))
732 | StatementKind::Deinit(..)
733 | StatementKind::SetDiscriminant { .. } => {
734 bug!("Statement not allowed in this MIR phase")
735 }
736 }
737 }
738
739 #[instrument(skip(self), level = "debug")]
740 fn visit_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
741 self.super_terminator(term, term_location);
742 let tcx = self.tcx();
743 debug!("terminator kind: {:?}", term.kind);
744 match &term.kind {
745 TerminatorKind::Goto { .. }
746 | TerminatorKind::UnwindResume
747 | TerminatorKind::UnwindTerminate(_)
748 | TerminatorKind::Return
749 | TerminatorKind::CoroutineDrop
750 | TerminatorKind::Unreachable
751 | TerminatorKind::Drop { .. }
752 | TerminatorKind::FalseEdge { .. }
753 | TerminatorKind::FalseUnwind { .. }
754 | TerminatorKind::InlineAsm { .. } => {
755 }
757
758 TerminatorKind::SwitchInt { discr, .. } => {
759 let switch_ty = discr.ty(self.body, tcx);
760 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
761 span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
762 }
763 }
765 TerminatorKind::Call { func, args, .. }
766 | TerminatorKind::TailCall { func, args, .. } => {
767 let (call_source, destination, is_diverging) = match term.kind {
768 TerminatorKind::Call { call_source, destination, target, .. } => {
769 (call_source, destination, target.is_none())
770 }
771 TerminatorKind::TailCall { .. } => {
772 (CallSource::Normal, RETURN_PLACE.into(), false)
773 }
774 _ => unreachable!(),
775 };
776
777 let func_ty = func.ty(self.body, tcx);
778 debug!("func_ty.kind: {:?}", func_ty.kind());
779
780 let sig = match func_ty.kind() {
781 ty::FnDef(..) | ty::FnPtr(..) => func_ty.fn_sig(tcx),
782 _ => {
783 span_mirbug!(self, term, "call to non-function {:?}", func_ty);
784 return;
785 }
786 };
787 let (unnormalized_sig, map) = tcx.instantiate_bound_regions(sig, |br| {
788 use crate::renumber::RegionCtxt;
789
790 let region_ctxt_fn = || {
791 let reg_info = match br.kind {
792 ty::BoundRegionKind::Anon => sym::anon,
793 ty::BoundRegionKind::Named(def_id) => tcx.item_name(def_id),
794 ty::BoundRegionKind::ClosureEnv => sym::env,
795 ty::BoundRegionKind::NamedAnon(_) => {
796 bug!("only used for pretty printing")
797 }
798 };
799
800 RegionCtxt::LateBound(reg_info)
801 };
802
803 self.infcx.next_region_var(
804 RegionVariableOrigin::BoundRegion(
805 term.source_info.span,
806 br.kind,
807 BoundRegionConversionTime::FnCall,
808 ),
809 region_ctxt_fn,
810 )
811 });
812 debug!(?unnormalized_sig);
813 self.prove_predicates(
822 unnormalized_sig.inputs_and_output.iter().map(|ty| {
823 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
824 ty.into(),
825 )))
826 }),
827 term_location.to_locations(),
828 ConstraintCategory::Boring,
829 );
830
831 let sig = self.deeply_normalize(unnormalized_sig, term_location);
832 if sig != unnormalized_sig {
836 self.prove_predicates(
837 sig.inputs_and_output.iter().map(|ty| {
838 ty::Binder::dummy(ty::PredicateKind::Clause(
839 ty::ClauseKind::WellFormed(ty.into()),
840 ))
841 }),
842 term_location.to_locations(),
843 ConstraintCategory::Boring,
844 );
845 }
846
847 self.check_call_dest(term, &sig, destination, is_diverging, term_location);
848
849 for &late_bound_region in map.values() {
857 let region_vid = self.universal_regions.to_region_vid(late_bound_region);
858 self.constraints.liveness_constraints.add_location(region_vid, term_location);
859 }
860
861 self.check_call_inputs(term, func, &sig, args, term_location, call_source);
862 }
863 TerminatorKind::Assert { cond, msg, .. } => {
864 let cond_ty = cond.ty(self.body, tcx);
865 if cond_ty != tcx.types.bool {
866 span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
867 }
868
869 if let AssertKind::BoundsCheck { len, index } = &**msg {
870 if len.ty(self.body, tcx) != tcx.types.usize {
871 span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
872 }
873 if index.ty(self.body, tcx) != tcx.types.usize {
874 span_mirbug!(self, index, "bounds-check index non-usize {:?}", index)
875 }
876 }
877 }
878 TerminatorKind::Yield { value, resume_arg, .. } => {
879 match self.body.yield_ty() {
880 None => span_mirbug!(self, term, "yield in non-coroutine"),
881 Some(ty) => {
882 let value_ty = value.ty(self.body, tcx);
883 if let Err(terr) = self.sub_types(
884 value_ty,
885 ty,
886 term_location.to_locations(),
887 ConstraintCategory::Yield,
888 ) {
889 span_mirbug!(
890 self,
891 term,
892 "type of yield value is {:?}, but the yield type is {:?}: {:?}",
893 value_ty,
894 ty,
895 terr
896 );
897 }
898 }
899 }
900
901 match self.body.resume_ty() {
902 None => span_mirbug!(self, term, "yield in non-coroutine"),
903 Some(ty) => {
904 let resume_ty = resume_arg.ty(self.body, tcx);
905 if let Err(terr) = self.sub_types(
906 ty,
907 resume_ty.ty,
908 term_location.to_locations(),
909 ConstraintCategory::Yield,
910 ) {
911 span_mirbug!(
912 self,
913 term,
914 "type of resume place is {:?}, but the resume type is {:?}: {:?}",
915 resume_ty,
916 ty,
917 terr
918 );
919 }
920 }
921 }
922 }
923 }
924 }
925
926 fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
927 self.super_local_decl(local, local_decl);
928
929 for user_ty in
930 local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
931 {
932 let span = self.user_type_annotations[user_ty.base].span;
933
934 let ty = if local_decl.is_nonref_binding() {
935 local_decl.ty
936 } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
937 rty
941 } else {
942 bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
943 };
944
945 if let Err(terr) = self.relate_type_and_user_type(
946 ty,
947 ty::Invariant,
948 user_ty,
949 Locations::All(span),
950 ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
951 ) {
952 span_mirbug!(
953 self,
954 local,
955 "bad user type on variable {:?}: {:?} != {:?} ({:?})",
956 local,
957 local_decl.ty,
958 local_decl.user_ty,
959 terr,
960 );
961 }
962 }
963
964 if !self.unsized_feature_enabled() {
967 match self.body.local_kind(local) {
968 LocalKind::ReturnPointer | LocalKind::Arg => {
969 return;
976 }
977 LocalKind::Temp => {
978 let span = local_decl.source_info.span;
979 let ty = local_decl.ty;
980 self.ensure_place_sized(ty, span);
981 }
982 }
983 }
984 }
985
986 #[instrument(skip(self), level = "debug")]
987 fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
988 self.super_rvalue(rvalue, location);
989 let tcx = self.tcx();
990 let span = self.body.source_info(location).span;
991 match rvalue {
992 Rvalue::Aggregate(ak, ops) => self.check_aggregate_rvalue(rvalue, ak, ops, location),
993
994 Rvalue::Repeat(operand, len) => {
995 let array_ty = rvalue.ty(self.body.local_decls(), tcx);
996 self.prove_predicate(
997 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
998 Locations::Single(location),
999 ConstraintCategory::Boring,
1000 );
1001
1002 if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) {
1007 match operand {
1008 Operand::Copy(..) | Operand::Constant(..) => {
1009 }
1012 Operand::Move(place) => {
1013 let ty = place.ty(self.body, tcx).ty;
1015 let trait_ref = ty::TraitRef::new(
1016 tcx,
1017 tcx.require_lang_item(LangItem::Copy, span),
1018 [ty],
1019 );
1020
1021 self.prove_trait_ref(
1022 trait_ref,
1023 Locations::Single(location),
1024 ConstraintCategory::CopyBound,
1025 );
1026 }
1027 }
1028 }
1029 }
1030
1031 &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
1032 let trait_ref =
1033 ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [ty]);
1034
1035 self.prove_trait_ref(
1036 trait_ref,
1037 location.to_locations(),
1038 ConstraintCategory::SizedBound,
1039 );
1040 }
1041 &Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
1042 &Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
1043
1044 Rvalue::ShallowInitBox(_operand, ty) => {
1045 let trait_ref =
1046 ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [*ty]);
1047
1048 self.prove_trait_ref(
1049 trait_ref,
1050 location.to_locations(),
1051 ConstraintCategory::SizedBound,
1052 );
1053 }
1054
1055 Rvalue::Cast(cast_kind, op, ty) => {
1056 match *cast_kind {
1057 CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
1058 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1059 let src_ty = op.ty(self.body, tcx);
1060 let mut src_sig = src_ty.fn_sig(tcx);
1061 if let ty::FnDef(def_id, _) = src_ty.kind()
1062 && let ty::FnPtr(_, target_hdr) = *ty.kind()
1063 && tcx.codegen_fn_attrs(def_id).safe_target_features
1064 && target_hdr.safety.is_safe()
1065 && let Some(safe_sig) = tcx.adjust_target_feature_sig(
1066 *def_id,
1067 src_sig,
1068 self.body.source.def_id(),
1069 )
1070 {
1071 src_sig = safe_sig;
1072 }
1073
1074 if src_sig.has_bound_regions()
1089 && let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind()
1090 && let target_sig = target_fn_tys.with(target_hdr)
1091 && let Some(target_sig) = target_sig.no_bound_vars()
1092 {
1093 let src_sig = self.infcx.instantiate_binder_with_fresh_vars(
1094 span,
1095 BoundRegionConversionTime::HigherRankedType,
1096 src_sig,
1097 );
1098 let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
1099 self.prove_predicate(
1100 ty::ClauseKind::WellFormed(src_ty.into()),
1101 location.to_locations(),
1102 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1103 );
1104
1105 let src_ty = self.normalize(src_ty, location);
1106 if let Err(terr) = self.sub_types(
1107 src_ty,
1108 *ty,
1109 location.to_locations(),
1110 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1111 ) {
1112 span_mirbug!(
1113 self,
1114 rvalue,
1115 "equating {:?} with {:?} yields {:?}",
1116 target_sig,
1117 src_sig,
1118 terr
1119 );
1120 };
1121 }
1122
1123 let src_ty = Ty::new_fn_ptr(tcx, src_sig);
1124 self.prove_predicate(
1129 ty::ClauseKind::WellFormed(src_ty.into()),
1130 location.to_locations(),
1131 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1132 );
1133
1134 let src_ty = self.normalize(src_ty, location);
1140 if let Err(terr) = self.sub_types(
1141 src_ty,
1142 *ty,
1143 location.to_locations(),
1144 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1145 ) {
1146 span_mirbug!(
1147 self,
1148 rvalue,
1149 "equating {:?} with {:?} yields {:?}",
1150 src_ty,
1151 ty,
1152 terr
1153 );
1154 }
1155 }
1156
1157 CastKind::PointerCoercion(
1158 PointerCoercion::ClosureFnPointer(safety),
1159 coercion_source,
1160 ) => {
1161 let sig = match op.ty(self.body, tcx).kind() {
1162 ty::Closure(_, args) => args.as_closure().sig(),
1163 _ => bug!(),
1164 };
1165 let ty_fn_ptr_from =
1166 Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, safety));
1167
1168 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1169 if let Err(terr) = self.sub_types(
1170 ty_fn_ptr_from,
1171 *ty,
1172 location.to_locations(),
1173 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1174 ) {
1175 span_mirbug!(
1176 self,
1177 rvalue,
1178 "equating {:?} with {:?} yields {:?}",
1179 ty_fn_ptr_from,
1180 ty,
1181 terr
1182 );
1183 }
1184 }
1185
1186 CastKind::PointerCoercion(
1187 PointerCoercion::UnsafeFnPointer,
1188 coercion_source,
1189 ) => {
1190 let fn_sig = op.ty(self.body, tcx).fn_sig(tcx);
1191
1192 let fn_sig = self.normalize(fn_sig, location);
1198
1199 let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
1200
1201 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1202 if let Err(terr) = self.sub_types(
1203 ty_fn_ptr_from,
1204 *ty,
1205 location.to_locations(),
1206 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1207 ) {
1208 span_mirbug!(
1209 self,
1210 rvalue,
1211 "equating {:?} with {:?} yields {:?}",
1212 ty_fn_ptr_from,
1213 ty,
1214 terr
1215 );
1216 }
1217 }
1218
1219 CastKind::PointerCoercion(PointerCoercion::Unsize, coercion_source) => {
1220 let &ty = ty;
1221 let trait_ref = ty::TraitRef::new(
1222 tcx,
1223 tcx.require_lang_item(LangItem::CoerceUnsized, span),
1224 [op.ty(self.body, tcx), ty],
1225 );
1226
1227 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1228 let unsize_to = fold_regions(tcx, ty, |r, _| {
1229 if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
1230 });
1231 self.prove_trait_ref(
1232 trait_ref,
1233 location.to_locations(),
1234 ConstraintCategory::Cast {
1235 is_implicit_coercion,
1236 unsize_to: Some(unsize_to),
1237 },
1238 );
1239 }
1240
1241 CastKind::PointerCoercion(
1242 PointerCoercion::MutToConstPointer,
1243 coercion_source,
1244 ) => {
1245 let ty::RawPtr(ty_from, hir::Mutability::Mut) =
1246 op.ty(self.body, tcx).kind()
1247 else {
1248 span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
1249 return;
1250 };
1251 let ty::RawPtr(ty_to, hir::Mutability::Not) = ty.kind() else {
1252 span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
1253 return;
1254 };
1255 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1256 if let Err(terr) = self.sub_types(
1257 *ty_from,
1258 *ty_to,
1259 location.to_locations(),
1260 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1261 ) {
1262 span_mirbug!(
1263 self,
1264 rvalue,
1265 "relating {:?} with {:?} yields {:?}",
1266 ty_from,
1267 ty_to,
1268 terr
1269 );
1270 }
1271 }
1272
1273 CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
1274 let ty_from = op.ty(self.body, tcx);
1275
1276 let opt_ty_elem_mut = match ty_from.kind() {
1277 ty::RawPtr(array_ty, array_mut) => match array_ty.kind() {
1278 ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)),
1279 _ => None,
1280 },
1281 _ => None,
1282 };
1283
1284 let Some((ty_elem, ty_mut)) = opt_ty_elem_mut else {
1285 span_mirbug!(
1286 self,
1287 rvalue,
1288 "ArrayToPointer cast from unexpected type {:?}",
1289 ty_from,
1290 );
1291 return;
1292 };
1293
1294 let (ty_to, ty_to_mut) = match ty.kind() {
1295 ty::RawPtr(ty_to, ty_to_mut) => (ty_to, *ty_to_mut),
1296 _ => {
1297 span_mirbug!(
1298 self,
1299 rvalue,
1300 "ArrayToPointer cast to unexpected type {:?}",
1301 ty,
1302 );
1303 return;
1304 }
1305 };
1306
1307 if ty_to_mut.is_mut() && ty_mut.is_not() {
1308 span_mirbug!(
1309 self,
1310 rvalue,
1311 "ArrayToPointer cast from const {:?} to mut {:?}",
1312 ty,
1313 ty_to
1314 );
1315 return;
1316 }
1317
1318 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1319 if let Err(terr) = self.sub_types(
1320 *ty_elem,
1321 *ty_to,
1322 location.to_locations(),
1323 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1324 ) {
1325 span_mirbug!(
1326 self,
1327 rvalue,
1328 "relating {:?} with {:?} yields {:?}",
1329 ty_elem,
1330 ty_to,
1331 terr
1332 )
1333 }
1334 }
1335
1336 CastKind::PointerExposeProvenance => {
1337 let ty_from = op.ty(self.body, tcx);
1338 let cast_ty_from = CastTy::from_ty(ty_from);
1339 let cast_ty_to = CastTy::from_ty(*ty);
1340 match (cast_ty_from, cast_ty_to) {
1341 (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
1342 _ => {
1343 span_mirbug!(
1344 self,
1345 rvalue,
1346 "Invalid PointerExposeProvenance cast {:?} -> {:?}",
1347 ty_from,
1348 ty
1349 )
1350 }
1351 }
1352 }
1353
1354 CastKind::PointerWithExposedProvenance => {
1355 let ty_from = op.ty(self.body, tcx);
1356 let cast_ty_from = CastTy::from_ty(ty_from);
1357 let cast_ty_to = CastTy::from_ty(*ty);
1358 match (cast_ty_from, cast_ty_to) {
1359 (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
1360 _ => {
1361 span_mirbug!(
1362 self,
1363 rvalue,
1364 "Invalid PointerWithExposedProvenance cast {:?} -> {:?}",
1365 ty_from,
1366 ty
1367 )
1368 }
1369 }
1370 }
1371 CastKind::IntToInt => {
1372 let ty_from = op.ty(self.body, tcx);
1373 let cast_ty_from = CastTy::from_ty(ty_from);
1374 let cast_ty_to = CastTy::from_ty(*ty);
1375 match (cast_ty_from, cast_ty_to) {
1376 (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
1377 _ => {
1378 span_mirbug!(
1379 self,
1380 rvalue,
1381 "Invalid IntToInt cast {:?} -> {:?}",
1382 ty_from,
1383 ty
1384 )
1385 }
1386 }
1387 }
1388 CastKind::IntToFloat => {
1389 let ty_from = op.ty(self.body, tcx);
1390 let cast_ty_from = CastTy::from_ty(ty_from);
1391 let cast_ty_to = CastTy::from_ty(*ty);
1392 match (cast_ty_from, cast_ty_to) {
1393 (Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
1394 _ => {
1395 span_mirbug!(
1396 self,
1397 rvalue,
1398 "Invalid IntToFloat cast {:?} -> {:?}",
1399 ty_from,
1400 ty
1401 )
1402 }
1403 }
1404 }
1405 CastKind::FloatToInt => {
1406 let ty_from = op.ty(self.body, tcx);
1407 let cast_ty_from = CastTy::from_ty(ty_from);
1408 let cast_ty_to = CastTy::from_ty(*ty);
1409 match (cast_ty_from, cast_ty_to) {
1410 (Some(CastTy::Float), Some(CastTy::Int(_))) => (),
1411 _ => {
1412 span_mirbug!(
1413 self,
1414 rvalue,
1415 "Invalid FloatToInt cast {:?} -> {:?}",
1416 ty_from,
1417 ty
1418 )
1419 }
1420 }
1421 }
1422 CastKind::FloatToFloat => {
1423 let ty_from = op.ty(self.body, tcx);
1424 let cast_ty_from = CastTy::from_ty(ty_from);
1425 let cast_ty_to = CastTy::from_ty(*ty);
1426 match (cast_ty_from, cast_ty_to) {
1427 (Some(CastTy::Float), Some(CastTy::Float)) => (),
1428 _ => {
1429 span_mirbug!(
1430 self,
1431 rvalue,
1432 "Invalid FloatToFloat cast {:?} -> {:?}",
1433 ty_from,
1434 ty
1435 )
1436 }
1437 }
1438 }
1439 CastKind::FnPtrToPtr => {
1440 let ty_from = op.ty(self.body, tcx);
1441 let cast_ty_from = CastTy::from_ty(ty_from);
1442 let cast_ty_to = CastTy::from_ty(*ty);
1443 match (cast_ty_from, cast_ty_to) {
1444 (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
1445 _ => {
1446 span_mirbug!(
1447 self,
1448 rvalue,
1449 "Invalid FnPtrToPtr cast {:?} -> {:?}",
1450 ty_from,
1451 ty
1452 )
1453 }
1454 }
1455 }
1456 CastKind::PtrToPtr => {
1457 let ty_from = op.ty(self.body, tcx);
1458 let Some(CastTy::Ptr(src)) = CastTy::from_ty(ty_from) else {
1459 unreachable!();
1460 };
1461 let Some(CastTy::Ptr(dst)) = CastTy::from_ty(*ty) else {
1462 unreachable!();
1463 };
1464
1465 if self.infcx.type_is_sized_modulo_regions(self.infcx.param_env, dst.ty) {
1466 let trait_ref = ty::TraitRef::new(
1472 tcx,
1473 tcx.require_lang_item(LangItem::Sized, self.last_span),
1474 [dst.ty],
1475 );
1476 self.prove_trait_ref(
1477 trait_ref,
1478 location.to_locations(),
1479 ConstraintCategory::Cast {
1480 is_implicit_coercion: true,
1481 unsize_to: None,
1482 },
1483 );
1484 } else if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) =
1485 *self.struct_tail(src.ty, location).kind()
1486 && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) =
1487 *self.struct_tail(dst.ty, location).kind()
1488 && src_tty.principal().is_some()
1489 && dst_tty.principal().is_some()
1490 {
1491 let src_obj = Ty::new_dynamic(
1501 tcx,
1502 tcx.mk_poly_existential_predicates(
1503 &src_tty.without_auto_traits().collect::<Vec<_>>(),
1504 ),
1505 dst_lt,
1508 ty::Dyn,
1509 );
1510 let dst_obj = Ty::new_dynamic(
1511 tcx,
1512 tcx.mk_poly_existential_predicates(
1513 &dst_tty.without_auto_traits().collect::<Vec<_>>(),
1514 ),
1515 dst_lt,
1516 ty::Dyn,
1517 );
1518
1519 debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
1520
1521 self.sub_types(
1522 src_obj,
1523 dst_obj,
1524 location.to_locations(),
1525 ConstraintCategory::Cast {
1526 is_implicit_coercion: false,
1527 unsize_to: None,
1528 },
1529 )
1530 .unwrap();
1531 }
1532 }
1533 CastKind::Transmute => {
1534 let ty_from = op.ty(self.body, tcx);
1535 match ty_from.kind() {
1536 ty::Pat(base, _) if base == ty => {}
1537 _ => span_mirbug!(
1538 self,
1539 rvalue,
1540 "Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR",
1541 ),
1542 }
1543 }
1544 }
1545 }
1546
1547 Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
1548 self.add_reborrow_constraint(location, *region, borrowed_place);
1549 }
1550
1551 Rvalue::BinaryOp(
1552 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
1553 box (left, right),
1554 ) => {
1555 let ty_left = left.ty(self.body, tcx);
1556 match ty_left.kind() {
1557 ty::RawPtr(_, _) | ty::FnPtr(..) => {
1559 let ty_right = right.ty(self.body, tcx);
1560 let common_ty =
1561 self.infcx.next_ty_var(self.body.source_info(location).span);
1562 self.sub_types(
1563 ty_left,
1564 common_ty,
1565 location.to_locations(),
1566 ConstraintCategory::CallArgument(None),
1567 )
1568 .unwrap_or_else(|err| {
1569 bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
1570 });
1571 if let Err(terr) = self.sub_types(
1572 ty_right,
1573 common_ty,
1574 location.to_locations(),
1575 ConstraintCategory::CallArgument(None),
1576 ) {
1577 span_mirbug!(
1578 self,
1579 rvalue,
1580 "unexpected comparison types {:?} and {:?} yields {:?}",
1581 ty_left,
1582 ty_right,
1583 terr
1584 )
1585 }
1586 }
1587 ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_)
1590 if ty_left == right.ty(self.body, tcx) => {}
1591 _ => span_mirbug!(
1594 self,
1595 rvalue,
1596 "unexpected comparison types {:?} and {:?}",
1597 ty_left,
1598 right.ty(self.body, tcx)
1599 ),
1600 }
1601 }
1602
1603 Rvalue::WrapUnsafeBinder(op, ty) => {
1604 let operand_ty = op.ty(self.body, self.tcx());
1605 let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
1606 unreachable!();
1607 };
1608 let expected_ty = self.infcx.instantiate_binder_with_fresh_vars(
1609 self.body().source_info(location).span,
1610 BoundRegionConversionTime::HigherRankedType,
1611 binder_ty.into(),
1612 );
1613 self.sub_types(
1614 operand_ty,
1615 expected_ty,
1616 location.to_locations(),
1617 ConstraintCategory::Boring,
1618 )
1619 .unwrap();
1620 }
1621
1622 Rvalue::Use(_)
1623 | Rvalue::UnaryOp(_, _)
1624 | Rvalue::CopyForDeref(_)
1625 | Rvalue::BinaryOp(..)
1626 | Rvalue::RawPtr(..)
1627 | Rvalue::ThreadLocalRef(..)
1628 | Rvalue::Len(..)
1629 | Rvalue::Discriminant(..)
1630 | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
1631 }
1632 }
1633
1634 #[instrument(level = "debug", skip(self))]
1635 fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
1636 self.super_operand(op, location);
1637 if let Operand::Constant(constant) = op {
1638 let maybe_uneval = match constant.const_ {
1639 Const::Val(..) | Const::Ty(_, _) => None,
1640 Const::Unevaluated(uv, _) => Some(uv),
1641 };
1642
1643 if let Some(uv) = maybe_uneval {
1644 if uv.promoted.is_none() {
1645 let tcx = self.tcx();
1646 let def_id = uv.def;
1647 if tcx.def_kind(def_id) == DefKind::InlineConst {
1648 let def_id = def_id.expect_local();
1649 let predicates = self.prove_closure_bounds(
1650 tcx,
1651 def_id,
1652 uv.args,
1653 location.to_locations(),
1654 );
1655 self.normalize_and_prove_instantiated_predicates(
1656 def_id.to_def_id(),
1657 predicates,
1658 location.to_locations(),
1659 );
1660 }
1661 }
1662 }
1663 }
1664 }
1665
1666 #[instrument(level = "debug", skip(self))]
1667 fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
1668 self.super_const_operand(constant, location);
1669 let ty = constant.const_.ty();
1670
1671 self.infcx.tcx.for_each_free_region(&ty, |live_region| {
1672 let live_region_vid = self.universal_regions.to_region_vid(live_region);
1673 self.constraints.liveness_constraints.add_location(live_region_vid, location);
1674 });
1675
1676 let locations = location.to_locations();
1677 if let Some(annotation_index) = constant.user_ty {
1678 if let Err(terr) = self.relate_type_and_user_type(
1679 constant.const_.ty(),
1680 ty::Invariant,
1681 &UserTypeProjection { base: annotation_index, projs: vec![] },
1682 locations,
1683 ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
1684 ) {
1685 let annotation = &self.user_type_annotations[annotation_index];
1686 span_mirbug!(
1687 self,
1688 constant,
1689 "bad constant user type {:?} vs {:?}: {:?}",
1690 annotation,
1691 constant.const_.ty(),
1692 terr,
1693 );
1694 }
1695 } else {
1696 let tcx = self.tcx();
1697 let maybe_uneval = match constant.const_ {
1698 Const::Ty(_, ct) => match ct.kind() {
1699 ty::ConstKind::Unevaluated(uv) => {
1700 Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
1701 }
1702 _ => None,
1703 },
1704 Const::Unevaluated(uv, _) => Some(uv),
1705 _ => None,
1706 };
1707
1708 if let Some(uv) = maybe_uneval {
1709 if let Some(promoted) = uv.promoted {
1710 let promoted_body = &self.promoted[promoted];
1711 self.check_promoted(promoted_body, location);
1712 let promoted_ty = promoted_body.return_ty();
1713 if let Err(terr) =
1714 self.eq_types(ty, promoted_ty, locations, ConstraintCategory::Boring)
1715 {
1716 span_mirbug!(
1717 self,
1718 promoted,
1719 "bad promoted type ({:?}: {:?}): {:?}",
1720 ty,
1721 promoted_ty,
1722 terr
1723 );
1724 };
1725 } else {
1726 self.ascribe_user_type(
1727 constant.const_.ty(),
1728 ty::UserType::new(ty::UserTypeKind::TypeOf(
1729 uv.def,
1730 UserArgs { args: uv.args, user_self_ty: None },
1731 )),
1732 locations.span(self.body),
1733 );
1734 }
1735 } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
1736 let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
1737 let normalized_ty = self.normalize(unnormalized_ty, locations);
1738 let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
1739
1740 if let Err(terr) =
1741 self.eq_types(literal_ty, normalized_ty, locations, ConstraintCategory::Boring)
1742 {
1743 span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
1744 }
1745 } else if let Const::Ty(_, ct) = constant.const_
1746 && let ty::ConstKind::Param(p) = ct.kind()
1747 {
1748 let body_def_id = self.universal_regions.defining_ty.def_id();
1749 let const_param = tcx.generics_of(body_def_id).const_param(p, tcx);
1750 self.ascribe_user_type(
1751 constant.const_.ty(),
1752 ty::UserType::new(ty::UserTypeKind::TypeOf(
1753 const_param.def_id,
1754 UserArgs {
1755 args: self.universal_regions.defining_ty.args(),
1756 user_self_ty: None,
1757 },
1758 )),
1759 locations.span(self.body),
1760 );
1761 }
1762
1763 if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
1764 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
1765 self.normalize_and_prove_instantiated_predicates(
1766 def_id,
1767 instantiated_predicates,
1768 locations,
1769 );
1770
1771 assert_eq!(tcx.trait_impl_of_assoc(def_id), None);
1772 self.prove_predicates(
1773 args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
1774 locations,
1775 ConstraintCategory::Boring,
1776 );
1777 }
1778 }
1779 }
1780
1781 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
1782 self.super_place(place, context, location);
1783 let tcx = self.tcx();
1784 let place_ty = place.ty(self.body, tcx);
1785 if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
1786 let trait_ref = ty::TraitRef::new(
1787 tcx,
1788 tcx.require_lang_item(LangItem::Copy, self.last_span),
1789 [place_ty.ty],
1790 );
1791
1792 self.prove_trait_ref(trait_ref, location.to_locations(), ConstraintCategory::CopyBound);
1804 }
1805 }
1806
1807 fn visit_projection_elem(
1808 &mut self,
1809 place: PlaceRef<'tcx>,
1810 elem: PlaceElem<'tcx>,
1811 context: PlaceContext,
1812 location: Location,
1813 ) {
1814 let tcx = self.tcx();
1815 let base_ty = place.ty(self.body(), tcx);
1816 match elem {
1817 ProjectionElem::Deref
1820 | ProjectionElem::Index(_)
1821 | ProjectionElem::ConstantIndex { .. }
1822 | ProjectionElem::Subslice { .. }
1823 | ProjectionElem::Downcast(..) => {}
1824 ProjectionElem::Field(field, fty) => {
1825 let fty = self.normalize(fty, location);
1826 let ty = PlaceTy::field_ty(tcx, base_ty.ty, base_ty.variant_index, field);
1827 let ty = self.normalize(ty, location);
1828 debug!(?fty, ?ty);
1829
1830 if let Err(terr) = self.relate_types(
1831 ty,
1832 context.ambient_variance(),
1833 fty,
1834 location.to_locations(),
1835 ConstraintCategory::Boring,
1836 ) {
1837 span_mirbug!(self, place, "bad field access ({:?}: {:?}): {:?}", ty, fty, terr);
1838 }
1839 }
1840 ProjectionElem::OpaqueCast(ty) => {
1841 let ty = self.normalize(ty, location);
1842 self.relate_types(
1843 ty,
1844 context.ambient_variance(),
1845 base_ty.ty,
1846 location.to_locations(),
1847 ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
1848 )
1849 .unwrap();
1850 }
1851 ProjectionElem::UnwrapUnsafeBinder(ty) => {
1852 let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
1853 unreachable!();
1854 };
1855 let found_ty = self.infcx.instantiate_binder_with_fresh_vars(
1856 self.body.source_info(location).span,
1857 BoundRegionConversionTime::HigherRankedType,
1858 binder_ty.into(),
1859 );
1860 self.relate_types(
1861 ty,
1862 context.ambient_variance(),
1863 found_ty,
1864 location.to_locations(),
1865 ConstraintCategory::Boring,
1866 )
1867 .unwrap();
1868 }
1869 ProjectionElem::Subtype(_) => {
1870 bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
1871 }
1872 }
1873 }
1874}
1875
1876impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1877 fn check_call_dest(
1878 &mut self,
1879 term: &Terminator<'tcx>,
1880 sig: &ty::FnSig<'tcx>,
1881 destination: Place<'tcx>,
1882 is_diverging: bool,
1883 term_location: Location,
1884 ) {
1885 let tcx = self.tcx();
1886 if is_diverging {
1887 let output_ty = self.tcx().erase_regions(sig.output());
1890 if !output_ty
1891 .is_privately_uninhabited(self.tcx(), self.infcx.typing_env(self.infcx.param_env))
1892 {
1893 span_mirbug!(self, term, "call to non-diverging function {:?} w/o dest", sig);
1894 }
1895 } else {
1896 let dest_ty = destination.ty(self.body, tcx).ty;
1897 let dest_ty = self.normalize(dest_ty, term_location);
1898 let category = match destination.as_local() {
1899 Some(RETURN_PLACE) => {
1900 if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
1901 self.universal_regions.defining_ty
1902 {
1903 if tcx.is_static(def_id) {
1904 ConstraintCategory::UseAsStatic
1905 } else {
1906 ConstraintCategory::UseAsConst
1907 }
1908 } else {
1909 ConstraintCategory::Return(ReturnConstraint::Normal)
1910 }
1911 }
1912 Some(l) if !self.body.local_decls[l].is_user_variable() => {
1913 ConstraintCategory::Boring
1914 }
1915 _ => ConstraintCategory::Assignment,
1917 };
1918
1919 let locations = term_location.to_locations();
1920
1921 if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
1922 span_mirbug!(
1923 self,
1924 term,
1925 "call dest mismatch ({:?} <- {:?}): {:?}",
1926 dest_ty,
1927 sig.output(),
1928 terr
1929 );
1930 }
1931
1932 if self.unsized_feature_enabled() {
1935 let span = term.source_info.span;
1936 self.ensure_place_sized(dest_ty, span);
1937 }
1938 }
1939 }
1940
1941 #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
1942 fn check_call_inputs(
1943 &mut self,
1944 term: &Terminator<'tcx>,
1945 func: &Operand<'tcx>,
1946 sig: &ty::FnSig<'tcx>,
1947 args: &[Spanned<Operand<'tcx>>],
1948 term_location: Location,
1949 call_source: CallSource,
1950 ) {
1951 if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
1952 span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
1953 }
1954
1955 let func_ty = func.ty(self.body, self.infcx.tcx);
1956 if let ty::FnDef(def_id, _) = *func_ty.kind() {
1957 if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
1961 self.tcx().intrinsic(def_id).map(|i| i.name)
1962 {
1963 let idx = match name {
1964 sym::simd_shuffle => 2,
1965 _ => 1,
1966 };
1967 if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) {
1968 self.tcx().dcx().emit_err(SimdIntrinsicArgConst {
1969 span: term.source_info.span,
1970 arg: idx + 1,
1971 intrinsic: name.to_string(),
1972 });
1973 }
1974 }
1975 }
1976 debug!(?func_ty);
1977
1978 for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
1979 let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
1980
1981 let op_arg_ty = self.normalize(op_arg_ty, term_location);
1982 let category = if call_source.from_hir_call() {
1983 ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
1984 } else {
1985 ConstraintCategory::Boring
1986 };
1987 if let Err(terr) =
1988 self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
1989 {
1990 span_mirbug!(
1991 self,
1992 term,
1993 "bad arg #{:?} ({:?} <- {:?}): {:?}",
1994 n,
1995 fn_arg,
1996 op_arg_ty,
1997 terr
1998 );
1999 }
2000 }
2001 }
2002
2003 fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
2004 let is_cleanup = block_data.is_cleanup;
2005 match block_data.terminator().kind {
2006 TerminatorKind::Goto { target } => {
2007 self.assert_iscleanup(block_data, target, is_cleanup)
2008 }
2009 TerminatorKind::SwitchInt { ref targets, .. } => {
2010 for target in targets.all_targets() {
2011 self.assert_iscleanup(block_data, *target, is_cleanup);
2012 }
2013 }
2014 TerminatorKind::UnwindResume => {
2015 if !is_cleanup {
2016 span_mirbug!(self, block_data, "resume on non-cleanup block!")
2017 }
2018 }
2019 TerminatorKind::UnwindTerminate(_) => {
2020 if !is_cleanup {
2021 span_mirbug!(self, block_data, "terminate on non-cleanup block!")
2022 }
2023 }
2024 TerminatorKind::Return => {
2025 if is_cleanup {
2026 span_mirbug!(self, block_data, "return on cleanup block")
2027 }
2028 }
2029 TerminatorKind::TailCall { .. } => {
2030 if is_cleanup {
2031 span_mirbug!(self, block_data, "tailcall on cleanup block")
2032 }
2033 }
2034 TerminatorKind::CoroutineDrop { .. } => {
2035 if is_cleanup {
2036 span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
2037 }
2038 }
2039 TerminatorKind::Yield { resume, drop, .. } => {
2040 if is_cleanup {
2041 span_mirbug!(self, block_data, "yield in cleanup block")
2042 }
2043 self.assert_iscleanup(block_data, resume, is_cleanup);
2044 if let Some(drop) = drop {
2045 self.assert_iscleanup(block_data, drop, is_cleanup);
2046 }
2047 }
2048 TerminatorKind::Unreachable => {}
2049 TerminatorKind::Drop { target, unwind, drop, .. } => {
2050 self.assert_iscleanup(block_data, target, is_cleanup);
2051 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2052 if let Some(drop) = drop {
2053 self.assert_iscleanup(block_data, drop, is_cleanup);
2054 }
2055 }
2056 TerminatorKind::Assert { target, unwind, .. } => {
2057 self.assert_iscleanup(block_data, target, is_cleanup);
2058 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2059 }
2060 TerminatorKind::Call { ref target, unwind, .. } => {
2061 if let &Some(target) = target {
2062 self.assert_iscleanup(block_data, target, is_cleanup);
2063 }
2064 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2065 }
2066 TerminatorKind::FalseEdge { real_target, imaginary_target } => {
2067 self.assert_iscleanup(block_data, real_target, is_cleanup);
2068 self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
2069 }
2070 TerminatorKind::FalseUnwind { real_target, unwind } => {
2071 self.assert_iscleanup(block_data, real_target, is_cleanup);
2072 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2073 }
2074 TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
2075 for &target in targets {
2076 self.assert_iscleanup(block_data, target, is_cleanup);
2077 }
2078 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2079 }
2080 }
2081 }
2082
2083 fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
2084 if self.body[bb].is_cleanup != iscleanuppad {
2085 span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
2086 }
2087 }
2088
2089 fn assert_iscleanup_unwind(
2090 &mut self,
2091 ctxt: &dyn fmt::Debug,
2092 unwind: UnwindAction,
2093 is_cleanup: bool,
2094 ) {
2095 match unwind {
2096 UnwindAction::Cleanup(unwind) => {
2097 if is_cleanup {
2098 span_mirbug!(self, ctxt, "unwind on cleanup block")
2099 }
2100 self.assert_iscleanup(ctxt, unwind, true);
2101 }
2102 UnwindAction::Continue => {
2103 if is_cleanup {
2104 span_mirbug!(self, ctxt, "unwind on cleanup block")
2105 }
2106 }
2107 UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
2108 }
2109 }
2110
2111 fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
2112 let tcx = self.tcx();
2113
2114 let erased_ty = tcx.erase_regions(ty);
2118 if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
2120 if self.reported_errors.replace((ty, span)).is_none() {
2125 self.tcx().dcx().emit_err(MoveUnsized { ty, span });
2129 }
2130 }
2131 }
2132
2133 fn aggregate_field_ty(
2134 &mut self,
2135 ak: &AggregateKind<'tcx>,
2136 field_index: FieldIdx,
2137 location: Location,
2138 ) -> Result<Ty<'tcx>, FieldAccessError> {
2139 let tcx = self.tcx();
2140
2141 match *ak {
2142 AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
2143 let def = tcx.adt_def(adt_did);
2144 let variant = &def.variant(variant_index);
2145 let adj_field_index = active_field_index.unwrap_or(field_index);
2146 if let Some(field) = variant.fields.get(adj_field_index) {
2147 Ok(self.normalize(field.ty(tcx, args), location))
2148 } else {
2149 Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
2150 }
2151 }
2152 AggregateKind::Closure(_, args) => {
2153 match args.as_closure().upvar_tys().get(field_index.as_usize()) {
2154 Some(ty) => Ok(*ty),
2155 None => Err(FieldAccessError::OutOfRange {
2156 field_count: args.as_closure().upvar_tys().len(),
2157 }),
2158 }
2159 }
2160 AggregateKind::Coroutine(_, args) => {
2161 match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
2165 Some(ty) => Ok(*ty),
2166 None => Err(FieldAccessError::OutOfRange {
2167 field_count: args.as_coroutine().prefix_tys().len(),
2168 }),
2169 }
2170 }
2171 AggregateKind::CoroutineClosure(_, args) => {
2172 match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
2173 Some(ty) => Ok(*ty),
2174 None => Err(FieldAccessError::OutOfRange {
2175 field_count: args.as_coroutine_closure().upvar_tys().len(),
2176 }),
2177 }
2178 }
2179 AggregateKind::Array(ty) => Ok(ty),
2180 AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
2181 unreachable!("This should have been covered in check_rvalues");
2182 }
2183 }
2184 }
2185
2186 fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex> {
2190 match rvalue {
2191 Rvalue::Use(_)
2192 | Rvalue::ThreadLocalRef(_)
2193 | Rvalue::Repeat(..)
2194 | Rvalue::Ref(..)
2195 | Rvalue::RawPtr(..)
2196 | Rvalue::Len(..)
2197 | Rvalue::Cast(..)
2198 | Rvalue::ShallowInitBox(..)
2199 | Rvalue::BinaryOp(..)
2200 | Rvalue::NullaryOp(..)
2201 | Rvalue::CopyForDeref(..)
2202 | Rvalue::UnaryOp(..)
2203 | Rvalue::Discriminant(..)
2204 | Rvalue::WrapUnsafeBinder(..) => None,
2205
2206 Rvalue::Aggregate(aggregate, _) => match **aggregate {
2207 AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,
2208 AggregateKind::Array(_) => None,
2209 AggregateKind::Tuple => None,
2210 AggregateKind::Closure(_, _) => None,
2211 AggregateKind::Coroutine(_, _) => None,
2212 AggregateKind::CoroutineClosure(_, _) => None,
2213 AggregateKind::RawPtr(_, _) => None,
2214 },
2215 }
2216 }
2217
2218 fn check_aggregate_rvalue(
2219 &mut self,
2220 rvalue: &Rvalue<'tcx>,
2221 aggregate_kind: &AggregateKind<'tcx>,
2222 operands: &IndexSlice<FieldIdx, Operand<'tcx>>,
2223 location: Location,
2224 ) {
2225 let tcx = self.tcx();
2226
2227 self.prove_aggregate_predicates(aggregate_kind, location);
2228
2229 if *aggregate_kind == AggregateKind::Tuple {
2230 return;
2232 }
2233
2234 if let AggregateKind::RawPtr(..) = aggregate_kind {
2235 bug!("RawPtr should only be in runtime MIR");
2236 }
2237
2238 for (i, operand) in operands.iter_enumerated() {
2239 let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
2240 Ok(field_ty) => field_ty,
2241 Err(FieldAccessError::OutOfRange { field_count }) => {
2242 span_mirbug!(
2243 self,
2244 rvalue,
2245 "accessed field #{} but variant only has {}",
2246 i.as_u32(),
2247 field_count,
2248 );
2249 continue;
2250 }
2251 };
2252 let operand_ty = operand.ty(self.body, tcx);
2253 let operand_ty = self.normalize(operand_ty, location);
2254
2255 if let Err(terr) = self.sub_types(
2256 operand_ty,
2257 field_ty,
2258 location.to_locations(),
2259 ConstraintCategory::Boring,
2260 ) {
2261 span_mirbug!(
2262 self,
2263 rvalue,
2264 "{:?} is not a subtype of {:?}: {:?}",
2265 operand_ty,
2266 field_ty,
2267 terr
2268 );
2269 }
2270 }
2271 }
2272
2273 fn add_reborrow_constraint(
2281 &mut self,
2282 location: Location,
2283 borrow_region: ty::Region<'tcx>,
2284 borrowed_place: &Place<'tcx>,
2285 ) {
2286 let Self { borrow_set, location_table, polonius_facts, constraints, .. } = self;
2288
2289 if let Some(polonius_facts) = polonius_facts {
2295 let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
2296 if let Some(borrow_index) = borrow_set.get_index_of(&location) {
2297 let region_vid = borrow_region.as_var();
2298 polonius_facts.loan_issued_at.push((
2299 region_vid.into(),
2300 borrow_index,
2301 location_table.mid_index(location),
2302 ));
2303 }
2304 }
2305
2306 debug!(
2312 "add_reborrow_constraint({:?}, {:?}, {:?})",
2313 location, borrow_region, borrowed_place
2314 );
2315
2316 let tcx = self.infcx.tcx;
2317 let def = self.body.source.def_id().expect_local();
2318 let upvars = tcx.closure_captures(def);
2319 let field =
2320 path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), self.body);
2321 let category = if let Some(field) = field {
2322 ConstraintCategory::ClosureUpvar(field)
2323 } else {
2324 ConstraintCategory::Boring
2325 };
2326
2327 for (base, elem) in borrowed_place.as_ref().iter_projections().rev() {
2328 debug!("add_reborrow_constraint - iteration {:?}", elem);
2329
2330 match elem {
2331 ProjectionElem::Deref => {
2332 let base_ty = base.ty(self.body, tcx).ty;
2333
2334 debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
2335 match base_ty.kind() {
2336 ty::Ref(ref_region, _, mutbl) => {
2337 constraints.outlives_constraints.push(OutlivesConstraint {
2338 sup: ref_region.as_var(),
2339 sub: borrow_region.as_var(),
2340 locations: location.to_locations(),
2341 span: location.to_locations().span(self.body),
2342 category,
2343 variance_info: ty::VarianceDiagInfo::default(),
2344 from_closure: false,
2345 });
2346
2347 match mutbl {
2348 hir::Mutability::Not => {
2349 break;
2353 }
2354 hir::Mutability::Mut => {
2355 }
2377 }
2378 }
2379 ty::RawPtr(..) => {
2380 break;
2382 }
2383 ty::Adt(def, _) if def.is_box() => {
2384 }
2386 _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
2387 }
2388 }
2389 ProjectionElem::Field(..)
2390 | ProjectionElem::Downcast(..)
2391 | ProjectionElem::OpaqueCast(..)
2392 | ProjectionElem::Index(..)
2393 | ProjectionElem::ConstantIndex { .. }
2394 | ProjectionElem::Subslice { .. }
2395 | ProjectionElem::UnwrapUnsafeBinder(_) => {
2396 }
2398 ProjectionElem::Subtype(_) => {
2399 bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
2400 }
2401 }
2402 }
2403 }
2404
2405 fn prove_aggregate_predicates(
2406 &mut self,
2407 aggregate_kind: &AggregateKind<'tcx>,
2408 location: Location,
2409 ) {
2410 let tcx = self.tcx();
2411
2412 debug!(
2413 "prove_aggregate_predicates(aggregate_kind={:?}, location={:?})",
2414 aggregate_kind, location
2415 );
2416
2417 let (def_id, instantiated_predicates) = match *aggregate_kind {
2418 AggregateKind::Adt(adt_did, _, args, _, _) => {
2419 (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, args))
2420 }
2421
2422 AggregateKind::Closure(def_id, args)
2442 | AggregateKind::CoroutineClosure(def_id, args)
2443 | AggregateKind::Coroutine(def_id, args) => (
2444 def_id,
2445 self.prove_closure_bounds(
2446 tcx,
2447 def_id.expect_local(),
2448 args,
2449 location.to_locations(),
2450 ),
2451 ),
2452
2453 AggregateKind::Array(_) | AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
2454 (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
2455 }
2456 };
2457
2458 self.normalize_and_prove_instantiated_predicates(
2459 def_id,
2460 instantiated_predicates,
2461 location.to_locations(),
2462 );
2463 }
2464
2465 fn prove_closure_bounds(
2466 &mut self,
2467 tcx: TyCtxt<'tcx>,
2468 def_id: LocalDefId,
2469 args: GenericArgsRef<'tcx>,
2470 locations: Locations,
2471 ) -> ty::InstantiatedPredicates<'tcx> {
2472 let root_def_id = self.root_cx.root_def_id();
2473 if let Some(closure_requirements) = &self.root_cx.closure_requirements(def_id) {
2474 constraint_conversion::ConstraintConversion::new(
2475 self.infcx,
2476 self.universal_regions,
2477 self.region_bound_pairs,
2478 self.known_type_outlives_obligations,
2479 locations,
2480 self.body.span, ConstraintCategory::Boring, self.constraints,
2483 )
2484 .apply_closure_requirements(closure_requirements, def_id, args);
2485 }
2486
2487 let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, root_def_id);
2489
2490 let parent_args = match tcx.def_kind(def_id) {
2491 DefKind::Closure => {
2495 &args[..typeck_root_args.len()]
2499 }
2500 DefKind::InlineConst => args.as_inline_const().parent_args(),
2501 other => bug!("unexpected item {:?}", other),
2502 };
2503 let parent_args = tcx.mk_args(parent_args);
2504
2505 assert_eq!(typeck_root_args.len(), parent_args.len());
2506 if let Err(_) = self.eq_args(
2507 typeck_root_args,
2508 parent_args,
2509 locations,
2510 ConstraintCategory::BoringNoLocation,
2511 ) {
2512 span_mirbug!(
2513 self,
2514 def_id,
2515 "could not relate closure to parent {:?} != {:?}",
2516 typeck_root_args,
2517 parent_args
2518 );
2519 }
2520
2521 tcx.predicates_of(def_id).instantiate(tcx, args)
2522 }
2523}
2524
2525trait NormalizeLocation: fmt::Debug + Copy {
2526 fn to_locations(self) -> Locations;
2527}
2528
2529impl NormalizeLocation for Locations {
2530 fn to_locations(self) -> Locations {
2531 self
2532 }
2533}
2534
2535impl NormalizeLocation for Location {
2536 fn to_locations(self) -> Locations {
2537 Locations::Single(self)
2538 }
2539}
2540
2541#[derive(Debug)]
2545pub(super) struct InstantiateOpaqueType<'tcx> {
2546 pub base_universe: Option<ty::UniverseIndex>,
2547 pub region_constraints: Option<RegionConstraintData<'tcx>>,
2548 pub obligations: PredicateObligations<'tcx>,
2549}
2550
2551impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
2552 type Output = ();
2553 type ErrorInfo = InstantiateOpaqueType<'tcx>;
2559
2560 fn fully_perform(
2561 mut self,
2562 infcx: &InferCtxt<'tcx>,
2563 root_def_id: LocalDefId,
2564 span: Span,
2565 ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
2566 let (mut output, region_constraints) =
2567 scrape_region_constraints(infcx, root_def_id, "InstantiateOpaqueType", span, |ocx| {
2568 ocx.register_obligations(self.obligations.clone());
2569 Ok(())
2570 })?;
2571 self.region_constraints = Some(region_constraints);
2572 output.error_info = Some(self);
2573 Ok(output)
2574 }
2575}