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