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