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