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