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 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.infcx.param_env,
412 self.known_type_outlives_obligations,
413 locations,
414 locations.span(self.body),
415 category,
416 self.constraints,
417 )
418 .convert_all(data);
419 }
420
421 fn sub_types(
423 &mut self,
424 sub: Ty<'tcx>,
425 sup: Ty<'tcx>,
426 locations: Locations,
427 category: ConstraintCategory<'tcx>,
428 ) -> Result<(), NoSolution> {
429 self.relate_types(sup, ty::Contravariant, sub, locations, category)
432 }
433
434 #[instrument(skip(self, category), level = "debug")]
435 fn eq_types(
436 &mut self,
437 expected: Ty<'tcx>,
438 found: Ty<'tcx>,
439 locations: Locations,
440 category: ConstraintCategory<'tcx>,
441 ) -> Result<(), NoSolution> {
442 self.relate_types(expected, ty::Invariant, found, locations, category)
443 }
444
445 #[instrument(skip(self), level = "debug")]
446 fn relate_type_and_user_type(
447 &mut self,
448 a: Ty<'tcx>,
449 v: ty::Variance,
450 user_ty: &UserTypeProjection,
451 locations: Locations,
452 category: ConstraintCategory<'tcx>,
453 ) -> Result<(), NoSolution> {
454 let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
455 trace!(?annotated_type);
456 let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
457
458 let tcx = self.infcx.tcx;
459
460 for proj in &user_ty.projs {
461 if !self.infcx.next_trait_solver()
462 && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind()
463 {
464 return Ok(());
468 }
469 let projected_ty = curr_projected_ty.projection_ty_core(
470 tcx,
471 proj,
472 |ty| self.structurally_resolve(ty, locations),
473 |ty, variant_index, field, ()| PlaceTy::field_ty(tcx, ty, variant_index, field),
474 |_| unreachable!(),
475 );
476 curr_projected_ty = projected_ty;
477 }
478 trace!(?curr_projected_ty);
479
480 let a = self.normalize(a, locations);
483 let ty = self.normalize(curr_projected_ty.ty, locations);
484 self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
485
486 Ok(())
487 }
488
489 fn check_promoted(&mut self, promoted_body: &'a Body<'tcx>, location: Location) {
490 let parent_body = mem::replace(&mut self.body, promoted_body);
495
496 let polonius_facts = &mut None;
499 let mut constraints = Default::default();
500 let mut liveness_constraints =
501 LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
502
503 let mut swap_constraints = |this: &mut Self| {
506 mem::swap(this.polonius_facts, polonius_facts);
507 mem::swap(&mut this.constraints.outlives_constraints, &mut constraints);
508 mem::swap(&mut this.constraints.liveness_constraints, &mut liveness_constraints);
509 };
510
511 swap_constraints(self);
512
513 self.visit_body(promoted_body);
514
515 self.body = parent_body;
516
517 swap_constraints(self);
519 let locations = location.to_locations();
520 for constraint in constraints.outlives().iter() {
521 let mut constraint = *constraint;
522 constraint.locations = locations;
523 if let ConstraintCategory::Return(_)
524 | ConstraintCategory::UseAsConst
525 | ConstraintCategory::UseAsStatic = constraint.category
526 {
527 constraint.category = ConstraintCategory::Boring;
530 }
531 self.constraints.outlives_constraints.push(constraint)
532 }
533 #[allow(rustc::potential_query_instability)]
540 for region in liveness_constraints.live_regions_unordered() {
541 self.constraints.liveness_constraints.add_location(region, location);
542 }
543 }
544
545 fn check_inline_const(
546 &mut self,
547 inferred_ty: Ty<'tcx>,
548 def_id: LocalDefId,
549 args: UserArgs<'tcx>,
550 span: Span,
551 ) {
552 assert!(args.user_self_ty.is_none());
553 let tcx = self.tcx();
554 let const_ty = tcx.type_of(def_id).instantiate(tcx, args.args);
555 if let Err(terr) =
556 self.eq_types(const_ty, inferred_ty, Locations::All(span), ConstraintCategory::Boring)
557 {
558 span_bug!(
559 span,
560 "bad inline const pattern: ({:?} = {:?}) {:?}",
561 const_ty,
562 inferred_ty,
563 terr
564 );
565 }
566 let args = self.infcx.resolve_vars_if_possible(args.args);
567 let predicates = self.prove_closure_bounds(tcx, def_id, args, Locations::All(span));
568 self.normalize_and_prove_instantiated_predicates(
569 def_id.to_def_id(),
570 predicates,
571 Locations::All(span),
572 );
573 }
574}
575
576impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
577 fn visit_span(&mut self, span: Span) {
578 if !span.is_dummy() {
579 debug!(?span);
580 self.last_span = span;
581 }
582 }
583
584 #[instrument(skip(self, body), level = "debug")]
585 fn visit_body(&mut self, body: &Body<'tcx>) {
586 debug_assert!(std::ptr::eq(self.body, body));
587
588 for (local, local_decl) in body.local_decls.iter_enumerated() {
589 self.visit_local_decl(local, local_decl);
590 }
591
592 for (block, block_data) in body.basic_blocks.iter_enumerated() {
593 let mut location = Location { block, statement_index: 0 };
594 for stmt in &block_data.statements {
595 self.visit_statement(stmt, location);
596 location.statement_index += 1;
597 }
598
599 self.visit_terminator(block_data.terminator(), location);
600 self.check_iscleanup(block_data);
601 }
602 }
603
604 #[instrument(skip(self), level = "debug")]
605 fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) {
606 self.super_statement(stmt, location);
607 let tcx = self.tcx();
608 match &stmt.kind {
609 StatementKind::Assign(box (place, rv)) => {
610 let category = match place.as_local() {
615 Some(RETURN_PLACE) => {
616 let defining_ty = &self.universal_regions.defining_ty;
617 if defining_ty.is_const() {
618 if tcx.is_static(defining_ty.def_id()) {
619 ConstraintCategory::UseAsStatic
620 } else {
621 ConstraintCategory::UseAsConst
622 }
623 } else {
624 ConstraintCategory::Return(ReturnConstraint::Normal)
625 }
626 }
627 Some(l)
628 if matches!(
629 self.body.local_decls[l].local_info(),
630 LocalInfo::AggregateTemp
631 ) =>
632 {
633 ConstraintCategory::Usage
634 }
635 Some(l) if !self.body.local_decls[l].is_user_variable() => {
636 ConstraintCategory::Boring
637 }
638 _ => ConstraintCategory::Assignment,
639 };
640 debug!(
641 "assignment category: {:?} {:?}",
642 category,
643 place.as_local().map(|l| &self.body.local_decls[l])
644 );
645
646 let place_ty = place.ty(self.body, tcx).ty;
647 debug!(?place_ty);
648 let place_ty = self.normalize(place_ty, location);
649 debug!("place_ty normalized: {:?}", place_ty);
650 let rv_ty = rv.ty(self.body, tcx);
651 debug!(?rv_ty);
652 let rv_ty = self.normalize(rv_ty, location);
653 debug!("normalized rv_ty: {:?}", rv_ty);
654 if let Err(terr) =
655 self.sub_types(rv_ty, place_ty, location.to_locations(), category)
656 {
657 span_mirbug!(
658 self,
659 stmt,
660 "bad assignment ({:?} = {:?}): {:?}",
661 place_ty,
662 rv_ty,
663 terr
664 );
665 }
666
667 if let Some(annotation_index) = self.rvalue_user_ty(rv) {
668 if let Err(terr) = self.relate_type_and_user_type(
669 rv_ty,
670 ty::Invariant,
671 &UserTypeProjection { base: annotation_index, projs: vec![] },
672 location.to_locations(),
673 ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
674 ) {
675 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
687 if !self.unsized_feature_enabled() {
688 let trait_ref = ty::TraitRef::new(
689 tcx,
690 tcx.require_lang_item(LangItem::Sized, self.last_span),
691 [place_ty],
692 );
693 self.prove_trait_ref(
694 trait_ref,
695 location.to_locations(),
696 ConstraintCategory::SizedBound,
697 );
698 }
699 }
700 StatementKind::AscribeUserType(box (place, projection), variance) => {
701 let place_ty = place.ty(self.body, tcx).ty;
702 if let Err(terr) = self.relate_type_and_user_type(
703 place_ty,
704 *variance,
705 projection,
706 Locations::All(stmt.source_info.span),
707 ConstraintCategory::TypeAnnotation(AnnotationSource::Ascription),
708 ) {
709 let annotation = &self.user_type_annotations[projection.base];
710 span_mirbug!(
711 self,
712 stmt,
713 "bad type assert ({:?} <: {:?} with projections {:?}): {:?}",
714 place_ty,
715 annotation,
716 projection.projs,
717 terr
718 );
719 }
720 }
721 StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(..))
722 | StatementKind::FakeRead(..)
723 | StatementKind::StorageLive(..)
724 | StatementKind::StorageDead(..)
725 | StatementKind::Retag { .. }
726 | StatementKind::Coverage(..)
727 | StatementKind::ConstEvalCounter
728 | StatementKind::PlaceMention(..)
729 | StatementKind::BackwardIncompatibleDropHint { .. }
730 | StatementKind::Nop => {}
731 StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(..))
732 | StatementKind::Deinit(..)
733 | StatementKind::SetDiscriminant { .. } => {
734 bug!("Statement not allowed in this MIR phase")
735 }
736 }
737 }
738
739 #[instrument(skip(self), level = "debug")]
740 fn visit_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
741 self.super_terminator(term, term_location);
742 let tcx = self.tcx();
743 debug!("terminator kind: {:?}", term.kind);
744 match &term.kind {
745 TerminatorKind::Goto { .. }
746 | TerminatorKind::UnwindResume
747 | TerminatorKind::UnwindTerminate(_)
748 | TerminatorKind::Return
749 | TerminatorKind::CoroutineDrop
750 | TerminatorKind::Unreachable
751 | TerminatorKind::Drop { .. }
752 | TerminatorKind::FalseEdge { .. }
753 | TerminatorKind::FalseUnwind { .. }
754 | TerminatorKind::InlineAsm { .. } => {
755 }
757
758 TerminatorKind::SwitchInt { discr, .. } => {
759 let switch_ty = discr.ty(self.body, tcx);
760 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
761 span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
762 }
763 }
765 TerminatorKind::Call { func, args, .. }
766 | TerminatorKind::TailCall { func, args, .. } => {
767 let call_source = match term.kind {
768 TerminatorKind::Call { call_source, .. } => call_source,
769 TerminatorKind::TailCall { .. } => CallSource::Normal,
770 _ => unreachable!(),
771 };
772
773 let func_ty = func.ty(self.body, tcx);
774 debug!("func_ty.kind: {:?}", func_ty.kind());
775
776 let sig = match func_ty.kind() {
777 ty::FnDef(..) | ty::FnPtr(..) => func_ty.fn_sig(tcx),
778 _ => {
779 span_mirbug!(self, term, "call to non-function {:?}", func_ty);
780 return;
781 }
782 };
783 let (unnormalized_sig, map) = tcx.instantiate_bound_regions(sig, |br| {
784 use crate::renumber::RegionCtxt;
785
786 let region_ctxt_fn = || {
787 let reg_info = match br.kind {
788 ty::BoundRegionKind::Anon => sym::anon,
789 ty::BoundRegionKind::Named(_, name) => name,
790 ty::BoundRegionKind::ClosureEnv => sym::env,
791 };
792
793 RegionCtxt::LateBound(reg_info)
794 };
795
796 self.infcx.next_region_var(
797 BoundRegion(
798 term.source_info.span,
799 br.kind,
800 BoundRegionConversionTime::FnCall,
801 ),
802 region_ctxt_fn,
803 )
804 });
805 debug!(?unnormalized_sig);
806 self.prove_predicates(
815 unnormalized_sig.inputs_and_output.iter().map(|ty| {
816 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
817 ty.into(),
818 )))
819 }),
820 term_location.to_locations(),
821 ConstraintCategory::Boring,
822 );
823
824 let sig = self.deeply_normalize(unnormalized_sig, term_location);
825 if sig != unnormalized_sig {
829 self.prove_predicates(
830 sig.inputs_and_output.iter().map(|ty| {
831 ty::Binder::dummy(ty::PredicateKind::Clause(
832 ty::ClauseKind::WellFormed(ty.into()),
833 ))
834 }),
835 term_location.to_locations(),
836 ConstraintCategory::Boring,
837 );
838 }
839
840 if let TerminatorKind::Call { destination, target, .. } = term.kind {
841 self.check_call_dest(term, &sig, destination, target, term_location);
842 }
843
844 for &late_bound_region in map.values() {
852 let region_vid = self.universal_regions.to_region_vid(late_bound_region);
853 self.constraints.liveness_constraints.add_location(region_vid, term_location);
854 }
855
856 self.check_call_inputs(term, func, &sig, args, term_location, call_source);
857 }
858 TerminatorKind::Assert { cond, msg, .. } => {
859 let cond_ty = cond.ty(self.body, tcx);
860 if cond_ty != tcx.types.bool {
861 span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
862 }
863
864 if let AssertKind::BoundsCheck { len, index } = &**msg {
865 if len.ty(self.body, tcx) != tcx.types.usize {
866 span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
867 }
868 if index.ty(self.body, tcx) != tcx.types.usize {
869 span_mirbug!(self, index, "bounds-check index non-usize {:?}", index)
870 }
871 }
872 }
873 TerminatorKind::Yield { value, resume_arg, .. } => {
874 match self.body.yield_ty() {
875 None => span_mirbug!(self, term, "yield in non-coroutine"),
876 Some(ty) => {
877 let value_ty = value.ty(self.body, tcx);
878 if let Err(terr) = self.sub_types(
879 value_ty,
880 ty,
881 term_location.to_locations(),
882 ConstraintCategory::Yield,
883 ) {
884 span_mirbug!(
885 self,
886 term,
887 "type of yield value is {:?}, but the yield type is {:?}: {:?}",
888 value_ty,
889 ty,
890 terr
891 );
892 }
893 }
894 }
895
896 match self.body.resume_ty() {
897 None => span_mirbug!(self, term, "yield in non-coroutine"),
898 Some(ty) => {
899 let resume_ty = resume_arg.ty(self.body, tcx);
900 if let Err(terr) = self.sub_types(
901 ty,
902 resume_ty.ty,
903 term_location.to_locations(),
904 ConstraintCategory::Yield,
905 ) {
906 span_mirbug!(
907 self,
908 term,
909 "type of resume place is {:?}, but the resume type is {:?}: {:?}",
910 resume_ty,
911 ty,
912 terr
913 );
914 }
915 }
916 }
917 }
918 }
919 }
920
921 fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
922 self.super_local_decl(local, local_decl);
923
924 for user_ty in
925 local_decl.user_ty.as_deref().into_iter().flat_map(UserTypeProjections::projections)
926 {
927 let span = self.user_type_annotations[user_ty.base].span;
928
929 let ty = if local_decl.is_nonref_binding() {
930 local_decl.ty
931 } else if let &ty::Ref(_, rty, _) = local_decl.ty.kind() {
932 rty
936 } else {
937 bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
938 };
939
940 if let Err(terr) = self.relate_type_and_user_type(
941 ty,
942 ty::Invariant,
943 user_ty,
944 Locations::All(span),
945 ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
946 ) {
947 span_mirbug!(
948 self,
949 local,
950 "bad user type on variable {:?}: {:?} != {:?} ({:?})",
951 local,
952 local_decl.ty,
953 local_decl.user_ty,
954 terr,
955 );
956 }
957 }
958
959 if !self.unsized_feature_enabled() {
962 match self.body.local_kind(local) {
963 LocalKind::ReturnPointer | LocalKind::Arg => {
964 return;
971 }
972 LocalKind::Temp => {
973 let span = local_decl.source_info.span;
974 let ty = local_decl.ty;
975 self.ensure_place_sized(ty, span);
976 }
977 }
978 }
979 }
980
981 #[instrument(skip(self), level = "debug")]
982 fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
983 self.super_rvalue(rvalue, location);
984 let tcx = self.tcx();
985 let span = self.body.source_info(location).span;
986 match rvalue {
987 Rvalue::Aggregate(ak, ops) => self.check_aggregate_rvalue(rvalue, ak, ops, location),
988
989 Rvalue::Repeat(operand, len) => {
990 let array_ty = rvalue.ty(self.body.local_decls(), tcx);
991 self.prove_predicate(
992 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
993 Locations::Single(location),
994 ConstraintCategory::Boring,
995 );
996
997 if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) {
1002 match operand {
1003 Operand::Copy(..) | Operand::Constant(..) => {
1004 }
1007 Operand::Move(place) => {
1008 let ty = place.ty(self.body, tcx).ty;
1010 let trait_ref = ty::TraitRef::new(
1011 tcx,
1012 tcx.require_lang_item(LangItem::Copy, span),
1013 [ty],
1014 );
1015
1016 self.prove_trait_ref(
1017 trait_ref,
1018 Locations::Single(location),
1019 ConstraintCategory::CopyBound,
1020 );
1021 }
1022 }
1023 }
1024 }
1025
1026 &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
1027 let trait_ref =
1028 ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [ty]);
1029
1030 self.prove_trait_ref(
1031 trait_ref,
1032 location.to_locations(),
1033 ConstraintCategory::SizedBound,
1034 );
1035 }
1036 &Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
1037 &Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
1038
1039 Rvalue::ShallowInitBox(_operand, ty) => {
1040 let trait_ref =
1041 ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Sized, span), [*ty]);
1042
1043 self.prove_trait_ref(
1044 trait_ref,
1045 location.to_locations(),
1046 ConstraintCategory::SizedBound,
1047 );
1048 }
1049
1050 Rvalue::Cast(cast_kind, op, ty) => {
1051 match *cast_kind {
1052 CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
1053 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1054 let src_ty = op.ty(self.body, tcx);
1055 let mut src_sig = src_ty.fn_sig(tcx);
1056 if let ty::FnDef(def_id, _) = src_ty.kind()
1057 && let ty::FnPtr(_, target_hdr) = *ty.kind()
1058 && tcx.codegen_fn_attrs(def_id).safe_target_features
1059 && target_hdr.safety.is_safe()
1060 && let Some(safe_sig) = tcx.adjust_target_feature_sig(
1061 *def_id,
1062 src_sig,
1063 self.body.source.def_id(),
1064 )
1065 {
1066 src_sig = safe_sig;
1067 }
1068
1069 if src_sig.has_bound_regions()
1084 && let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind()
1085 && let target_sig = target_fn_tys.with(target_hdr)
1086 && let Some(target_sig) = target_sig.no_bound_vars()
1087 {
1088 let src_sig = self.infcx.instantiate_binder_with_fresh_vars(
1089 span,
1090 BoundRegionConversionTime::HigherRankedType,
1091 src_sig,
1092 );
1093 let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
1094 self.prove_predicate(
1095 ty::ClauseKind::WellFormed(src_ty.into()),
1096 location.to_locations(),
1097 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1098 );
1099
1100 let src_ty = self.normalize(src_ty, location);
1101 if let Err(terr) = self.sub_types(
1102 src_ty,
1103 *ty,
1104 location.to_locations(),
1105 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1106 ) {
1107 span_mirbug!(
1108 self,
1109 rvalue,
1110 "equating {:?} with {:?} yields {:?}",
1111 target_sig,
1112 src_sig,
1113 terr
1114 );
1115 };
1116 }
1117
1118 let src_ty = Ty::new_fn_ptr(tcx, src_sig);
1119 self.prove_predicate(
1124 ty::ClauseKind::WellFormed(src_ty.into()),
1125 location.to_locations(),
1126 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1127 );
1128
1129 let src_ty = self.normalize(src_ty, location);
1135 if let Err(terr) = self.sub_types(
1136 src_ty,
1137 *ty,
1138 location.to_locations(),
1139 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1140 ) {
1141 span_mirbug!(
1142 self,
1143 rvalue,
1144 "equating {:?} with {:?} yields {:?}",
1145 src_ty,
1146 ty,
1147 terr
1148 );
1149 }
1150 }
1151
1152 CastKind::PointerCoercion(
1153 PointerCoercion::ClosureFnPointer(safety),
1154 coercion_source,
1155 ) => {
1156 let sig = match op.ty(self.body, tcx).kind() {
1157 ty::Closure(_, args) => args.as_closure().sig(),
1158 _ => bug!(),
1159 };
1160 let ty_fn_ptr_from =
1161 Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, safety));
1162
1163 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1164 if let Err(terr) = self.sub_types(
1165 ty_fn_ptr_from,
1166 *ty,
1167 location.to_locations(),
1168 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1169 ) {
1170 span_mirbug!(
1171 self,
1172 rvalue,
1173 "equating {:?} with {:?} yields {:?}",
1174 ty_fn_ptr_from,
1175 ty,
1176 terr
1177 );
1178 }
1179 }
1180
1181 CastKind::PointerCoercion(
1182 PointerCoercion::UnsafeFnPointer,
1183 coercion_source,
1184 ) => {
1185 let fn_sig = op.ty(self.body, tcx).fn_sig(tcx);
1186
1187 let fn_sig = self.normalize(fn_sig, location);
1193
1194 let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
1195
1196 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1197 if let Err(terr) = self.sub_types(
1198 ty_fn_ptr_from,
1199 *ty,
1200 location.to_locations(),
1201 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1202 ) {
1203 span_mirbug!(
1204 self,
1205 rvalue,
1206 "equating {:?} with {:?} yields {:?}",
1207 ty_fn_ptr_from,
1208 ty,
1209 terr
1210 );
1211 }
1212 }
1213
1214 CastKind::PointerCoercion(PointerCoercion::Unsize, coercion_source) => {
1215 let &ty = ty;
1216 let trait_ref = ty::TraitRef::new(
1217 tcx,
1218 tcx.require_lang_item(LangItem::CoerceUnsized, span),
1219 [op.ty(self.body, tcx), ty],
1220 );
1221
1222 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1223 let unsize_to = fold_regions(tcx, ty, |r, _| {
1224 if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
1225 });
1226 self.prove_trait_ref(
1227 trait_ref,
1228 location.to_locations(),
1229 ConstraintCategory::Cast {
1230 is_implicit_coercion,
1231 unsize_to: Some(unsize_to),
1232 },
1233 );
1234 }
1235
1236 CastKind::PointerCoercion(PointerCoercion::DynStar, coercion_source) => {
1237 let (existential_predicates, region) = match ty.kind() {
1241 Dynamic(predicates, region, ty::DynStar) => (predicates, region),
1242 _ => panic!("Invalid dyn* cast_ty"),
1243 };
1244
1245 let self_ty = op.ty(self.body, tcx);
1246
1247 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1248 self.prove_predicates(
1249 existential_predicates
1250 .iter()
1251 .map(|predicate| predicate.with_self_ty(tcx, self_ty)),
1252 location.to_locations(),
1253 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1254 );
1255
1256 let outlives_predicate = tcx.mk_predicate(Binder::dummy(
1257 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
1258 ty::OutlivesPredicate(self_ty, *region),
1259 )),
1260 ));
1261 self.prove_predicate(
1262 outlives_predicate,
1263 location.to_locations(),
1264 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1265 );
1266 }
1267
1268 CastKind::PointerCoercion(
1269 PointerCoercion::MutToConstPointer,
1270 coercion_source,
1271 ) => {
1272 let ty::RawPtr(ty_from, hir::Mutability::Mut) =
1273 op.ty(self.body, tcx).kind()
1274 else {
1275 span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
1276 return;
1277 };
1278 let ty::RawPtr(ty_to, hir::Mutability::Not) = ty.kind() else {
1279 span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
1280 return;
1281 };
1282 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1283 if let Err(terr) = self.sub_types(
1284 *ty_from,
1285 *ty_to,
1286 location.to_locations(),
1287 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1288 ) {
1289 span_mirbug!(
1290 self,
1291 rvalue,
1292 "relating {:?} with {:?} yields {:?}",
1293 ty_from,
1294 ty_to,
1295 terr
1296 );
1297 }
1298 }
1299
1300 CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
1301 let ty_from = op.ty(self.body, tcx);
1302
1303 let opt_ty_elem_mut = match ty_from.kind() {
1304 ty::RawPtr(array_ty, array_mut) => match array_ty.kind() {
1305 ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)),
1306 _ => None,
1307 },
1308 _ => None,
1309 };
1310
1311 let Some((ty_elem, ty_mut)) = opt_ty_elem_mut else {
1312 span_mirbug!(
1313 self,
1314 rvalue,
1315 "ArrayToPointer cast from unexpected type {:?}",
1316 ty_from,
1317 );
1318 return;
1319 };
1320
1321 let (ty_to, ty_to_mut) = match ty.kind() {
1322 ty::RawPtr(ty_to, ty_to_mut) => (ty_to, *ty_to_mut),
1323 _ => {
1324 span_mirbug!(
1325 self,
1326 rvalue,
1327 "ArrayToPointer cast to unexpected type {:?}",
1328 ty,
1329 );
1330 return;
1331 }
1332 };
1333
1334 if ty_to_mut.is_mut() && ty_mut.is_not() {
1335 span_mirbug!(
1336 self,
1337 rvalue,
1338 "ArrayToPointer cast from const {:?} to mut {:?}",
1339 ty,
1340 ty_to
1341 );
1342 return;
1343 }
1344
1345 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1346 if let Err(terr) = self.sub_types(
1347 *ty_elem,
1348 *ty_to,
1349 location.to_locations(),
1350 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1351 ) {
1352 span_mirbug!(
1353 self,
1354 rvalue,
1355 "relating {:?} with {:?} yields {:?}",
1356 ty_elem,
1357 ty_to,
1358 terr
1359 )
1360 }
1361 }
1362
1363 CastKind::PointerExposeProvenance => {
1364 let ty_from = op.ty(self.body, tcx);
1365 let cast_ty_from = CastTy::from_ty(ty_from);
1366 let cast_ty_to = CastTy::from_ty(*ty);
1367 match (cast_ty_from, cast_ty_to) {
1368 (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
1369 _ => {
1370 span_mirbug!(
1371 self,
1372 rvalue,
1373 "Invalid PointerExposeProvenance cast {:?} -> {:?}",
1374 ty_from,
1375 ty
1376 )
1377 }
1378 }
1379 }
1380
1381 CastKind::PointerWithExposedProvenance => {
1382 let ty_from = op.ty(self.body, tcx);
1383 let cast_ty_from = CastTy::from_ty(ty_from);
1384 let cast_ty_to = CastTy::from_ty(*ty);
1385 match (cast_ty_from, cast_ty_to) {
1386 (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
1387 _ => {
1388 span_mirbug!(
1389 self,
1390 rvalue,
1391 "Invalid PointerWithExposedProvenance cast {:?} -> {:?}",
1392 ty_from,
1393 ty
1394 )
1395 }
1396 }
1397 }
1398 CastKind::IntToInt => {
1399 let ty_from = op.ty(self.body, tcx);
1400 let cast_ty_from = CastTy::from_ty(ty_from);
1401 let cast_ty_to = CastTy::from_ty(*ty);
1402 match (cast_ty_from, cast_ty_to) {
1403 (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
1404 _ => {
1405 span_mirbug!(
1406 self,
1407 rvalue,
1408 "Invalid IntToInt cast {:?} -> {:?}",
1409 ty_from,
1410 ty
1411 )
1412 }
1413 }
1414 }
1415 CastKind::IntToFloat => {
1416 let ty_from = op.ty(self.body, tcx);
1417 let cast_ty_from = CastTy::from_ty(ty_from);
1418 let cast_ty_to = CastTy::from_ty(*ty);
1419 match (cast_ty_from, cast_ty_to) {
1420 (Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
1421 _ => {
1422 span_mirbug!(
1423 self,
1424 rvalue,
1425 "Invalid IntToFloat cast {:?} -> {:?}",
1426 ty_from,
1427 ty
1428 )
1429 }
1430 }
1431 }
1432 CastKind::FloatToInt => {
1433 let ty_from = op.ty(self.body, tcx);
1434 let cast_ty_from = CastTy::from_ty(ty_from);
1435 let cast_ty_to = CastTy::from_ty(*ty);
1436 match (cast_ty_from, cast_ty_to) {
1437 (Some(CastTy::Float), Some(CastTy::Int(_))) => (),
1438 _ => {
1439 span_mirbug!(
1440 self,
1441 rvalue,
1442 "Invalid FloatToInt cast {:?} -> {:?}",
1443 ty_from,
1444 ty
1445 )
1446 }
1447 }
1448 }
1449 CastKind::FloatToFloat => {
1450 let ty_from = op.ty(self.body, tcx);
1451 let cast_ty_from = CastTy::from_ty(ty_from);
1452 let cast_ty_to = CastTy::from_ty(*ty);
1453 match (cast_ty_from, cast_ty_to) {
1454 (Some(CastTy::Float), Some(CastTy::Float)) => (),
1455 _ => {
1456 span_mirbug!(
1457 self,
1458 rvalue,
1459 "Invalid FloatToFloat cast {:?} -> {:?}",
1460 ty_from,
1461 ty
1462 )
1463 }
1464 }
1465 }
1466 CastKind::FnPtrToPtr => {
1467 let ty_from = op.ty(self.body, tcx);
1468 let cast_ty_from = CastTy::from_ty(ty_from);
1469 let cast_ty_to = CastTy::from_ty(*ty);
1470 match (cast_ty_from, cast_ty_to) {
1471 (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
1472 _ => {
1473 span_mirbug!(
1474 self,
1475 rvalue,
1476 "Invalid FnPtrToPtr cast {:?} -> {:?}",
1477 ty_from,
1478 ty
1479 )
1480 }
1481 }
1482 }
1483 CastKind::PtrToPtr => {
1484 let ty_from = op.ty(self.body, tcx);
1485 let cast_ty_from = CastTy::from_ty(ty_from);
1486 let cast_ty_to = CastTy::from_ty(*ty);
1487 match (cast_ty_from, cast_ty_to) {
1488 (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
1489 let src_tail = self.struct_tail(src.ty, location);
1490 let dst_tail = self.struct_tail(dst.ty, location);
1491
1492 if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) = *src_tail.kind()
1499 && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) = *dst_tail.kind()
1500 && src_tty.principal().is_some()
1501 && dst_tty.principal().is_some()
1502 {
1503 let src_obj = Ty::new_dynamic(
1506 tcx,
1507 tcx.mk_poly_existential_predicates(
1508 &src_tty.without_auto_traits().collect::<Vec<_>>(),
1509 ),
1510 dst_lt,
1513 ty::Dyn,
1514 );
1515 let dst_obj = Ty::new_dynamic(
1516 tcx,
1517 tcx.mk_poly_existential_predicates(
1518 &dst_tty.without_auto_traits().collect::<Vec<_>>(),
1519 ),
1520 dst_lt,
1521 ty::Dyn,
1522 );
1523
1524 debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
1525
1526 self.sub_types(
1527 src_obj,
1528 dst_obj,
1529 location.to_locations(),
1530 ConstraintCategory::Cast {
1531 is_implicit_coercion: false,
1532 unsize_to: None,
1533 },
1534 )
1535 .unwrap();
1536 }
1537 }
1538 _ => {
1539 span_mirbug!(
1540 self,
1541 rvalue,
1542 "Invalid PtrToPtr cast {:?} -> {:?}",
1543 ty_from,
1544 ty
1545 )
1546 }
1547 }
1548 }
1549 CastKind::Transmute => {
1550 let ty_from = op.ty(self.body, tcx);
1551 match ty_from.kind() {
1552 ty::Pat(base, _) if base == ty => {}
1553 _ => span_mirbug!(
1554 self,
1555 rvalue,
1556 "Unexpected CastKind::Transmute {ty_from:?} -> {ty:?}, which is not permitted in Analysis MIR",
1557 ),
1558 }
1559 }
1560 }
1561 }
1562
1563 Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
1564 self.add_reborrow_constraint(location, *region, borrowed_place);
1565 }
1566
1567 Rvalue::BinaryOp(
1568 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
1569 box (left, right),
1570 ) => {
1571 let ty_left = left.ty(self.body, tcx);
1572 match ty_left.kind() {
1573 ty::RawPtr(_, _) | ty::FnPtr(..) => {
1575 let ty_right = right.ty(self.body, tcx);
1576 let common_ty =
1577 self.infcx.next_ty_var(self.body.source_info(location).span);
1578 self.sub_types(
1579 ty_left,
1580 common_ty,
1581 location.to_locations(),
1582 ConstraintCategory::CallArgument(None),
1583 )
1584 .unwrap_or_else(|err| {
1585 bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
1586 });
1587 if let Err(terr) = self.sub_types(
1588 ty_right,
1589 common_ty,
1590 location.to_locations(),
1591 ConstraintCategory::CallArgument(None),
1592 ) {
1593 span_mirbug!(
1594 self,
1595 rvalue,
1596 "unexpected comparison types {:?} and {:?} yields {:?}",
1597 ty_left,
1598 ty_right,
1599 terr
1600 )
1601 }
1602 }
1603 ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_)
1606 if ty_left == right.ty(self.body, tcx) => {}
1607 _ => span_mirbug!(
1610 self,
1611 rvalue,
1612 "unexpected comparison types {:?} and {:?}",
1613 ty_left,
1614 right.ty(self.body, tcx)
1615 ),
1616 }
1617 }
1618
1619 Rvalue::WrapUnsafeBinder(op, ty) => {
1620 let operand_ty = op.ty(self.body, self.tcx());
1621 let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
1622 unreachable!();
1623 };
1624 let expected_ty = self.infcx.instantiate_binder_with_fresh_vars(
1625 self.body().source_info(location).span,
1626 BoundRegionConversionTime::HigherRankedType,
1627 binder_ty.into(),
1628 );
1629 self.sub_types(
1630 operand_ty,
1631 expected_ty,
1632 location.to_locations(),
1633 ConstraintCategory::Boring,
1634 )
1635 .unwrap();
1636 }
1637
1638 Rvalue::Use(_)
1639 | Rvalue::UnaryOp(_, _)
1640 | Rvalue::CopyForDeref(_)
1641 | Rvalue::BinaryOp(..)
1642 | Rvalue::RawPtr(..)
1643 | Rvalue::ThreadLocalRef(..)
1644 | Rvalue::Len(..)
1645 | Rvalue::Discriminant(..)
1646 | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
1647 }
1648 }
1649
1650 #[instrument(level = "debug", skip(self))]
1651 fn visit_operand(&mut self, op: &Operand<'tcx>, location: Location) {
1652 self.super_operand(op, location);
1653 if let Operand::Constant(constant) = op {
1654 let maybe_uneval = match constant.const_ {
1655 Const::Val(..) | Const::Ty(_, _) => None,
1656 Const::Unevaluated(uv, _) => Some(uv),
1657 };
1658
1659 if let Some(uv) = maybe_uneval {
1660 if uv.promoted.is_none() {
1661 let tcx = self.tcx();
1662 let def_id = uv.def;
1663 if tcx.def_kind(def_id) == DefKind::InlineConst {
1664 let def_id = def_id.expect_local();
1665 let predicates = self.prove_closure_bounds(
1666 tcx,
1667 def_id,
1668 uv.args,
1669 location.to_locations(),
1670 );
1671 self.normalize_and_prove_instantiated_predicates(
1672 def_id.to_def_id(),
1673 predicates,
1674 location.to_locations(),
1675 );
1676 }
1677 }
1678 }
1679 }
1680 }
1681
1682 #[instrument(level = "debug", skip(self))]
1683 fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
1684 self.super_const_operand(constant, location);
1685 let ty = constant.const_.ty();
1686
1687 self.infcx.tcx.for_each_free_region(&ty, |live_region| {
1688 let live_region_vid = self.universal_regions.to_region_vid(live_region);
1689 self.constraints.liveness_constraints.add_location(live_region_vid, location);
1690 });
1691
1692 let locations = location.to_locations();
1693 if let Some(annotation_index) = constant.user_ty {
1694 if let Err(terr) = self.relate_type_and_user_type(
1695 constant.const_.ty(),
1696 ty::Invariant,
1697 &UserTypeProjection { base: annotation_index, projs: vec![] },
1698 locations,
1699 ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
1700 ) {
1701 let annotation = &self.user_type_annotations[annotation_index];
1702 span_mirbug!(
1703 self,
1704 constant,
1705 "bad constant user type {:?} vs {:?}: {:?}",
1706 annotation,
1707 constant.const_.ty(),
1708 terr,
1709 );
1710 }
1711 } else {
1712 let tcx = self.tcx();
1713 let maybe_uneval = match constant.const_ {
1714 Const::Ty(_, ct) => match ct.kind() {
1715 ty::ConstKind::Unevaluated(uv) => {
1716 Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
1717 }
1718 _ => None,
1719 },
1720 Const::Unevaluated(uv, _) => Some(uv),
1721 _ => None,
1722 };
1723
1724 if let Some(uv) = maybe_uneval {
1725 if let Some(promoted) = uv.promoted {
1726 let promoted_body = &self.promoted[promoted];
1727 self.check_promoted(promoted_body, location);
1728 let promoted_ty = promoted_body.return_ty();
1729 if let Err(terr) =
1730 self.eq_types(ty, promoted_ty, locations, ConstraintCategory::Boring)
1731 {
1732 span_mirbug!(
1733 self,
1734 promoted,
1735 "bad promoted type ({:?}: {:?}): {:?}",
1736 ty,
1737 promoted_ty,
1738 terr
1739 );
1740 };
1741 } else {
1742 self.ascribe_user_type(
1743 constant.const_.ty(),
1744 ty::UserType::new(ty::UserTypeKind::TypeOf(
1745 uv.def,
1746 UserArgs { args: uv.args, user_self_ty: None },
1747 )),
1748 locations.span(self.body),
1749 );
1750 }
1751 } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
1752 let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
1753 let normalized_ty = self.normalize(unnormalized_ty, locations);
1754 let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
1755
1756 if let Err(terr) =
1757 self.eq_types(literal_ty, normalized_ty, locations, ConstraintCategory::Boring)
1758 {
1759 span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
1760 }
1761 } else if let Const::Ty(_, ct) = constant.const_
1762 && let ty::ConstKind::Param(p) = ct.kind()
1763 {
1764 let body_def_id = self.universal_regions.defining_ty.def_id();
1765 let const_param = tcx.generics_of(body_def_id).const_param(p, tcx);
1766 self.ascribe_user_type(
1767 constant.const_.ty(),
1768 ty::UserType::new(ty::UserTypeKind::TypeOf(
1769 const_param.def_id,
1770 UserArgs {
1771 args: self.universal_regions.defining_ty.args(),
1772 user_self_ty: None,
1773 },
1774 )),
1775 locations.span(self.body),
1776 );
1777 }
1778
1779 if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
1780 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
1781 self.normalize_and_prove_instantiated_predicates(
1782 def_id,
1783 instantiated_predicates,
1784 locations,
1785 );
1786
1787 assert!(!matches!(
1788 tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
1789 Some(DefKind::Impl { of_trait: true })
1790 ));
1791 self.prove_predicates(
1792 args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
1793 locations,
1794 ConstraintCategory::Boring,
1795 );
1796 }
1797 }
1798 }
1799
1800 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
1801 self.super_place(place, context, location);
1802 let tcx = self.tcx();
1803 let place_ty = place.ty(self.body, tcx);
1804 if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
1805 let trait_ref = ty::TraitRef::new(
1806 tcx,
1807 tcx.require_lang_item(LangItem::Copy, self.last_span),
1808 [place_ty.ty],
1809 );
1810
1811 self.prove_trait_ref(trait_ref, location.to_locations(), ConstraintCategory::CopyBound);
1823 }
1824 }
1825
1826 fn visit_projection_elem(
1827 &mut self,
1828 place: PlaceRef<'tcx>,
1829 elem: PlaceElem<'tcx>,
1830 context: PlaceContext,
1831 location: Location,
1832 ) {
1833 let tcx = self.tcx();
1834 let base_ty = place.ty(self.body(), tcx);
1835 match elem {
1836 ProjectionElem::Deref
1839 | ProjectionElem::Index(_)
1840 | ProjectionElem::ConstantIndex { .. }
1841 | ProjectionElem::Subslice { .. }
1842 | ProjectionElem::Downcast(..) => {}
1843 ProjectionElem::Field(field, fty) => {
1844 let fty = self.normalize(fty, location);
1845 let ty = PlaceTy::field_ty(tcx, base_ty.ty, base_ty.variant_index, field);
1846 let ty = self.normalize(ty, location);
1847 debug!(?fty, ?ty);
1848
1849 if let Err(terr) = self.relate_types(
1850 ty,
1851 context.ambient_variance(),
1852 fty,
1853 location.to_locations(),
1854 ConstraintCategory::Boring,
1855 ) {
1856 span_mirbug!(self, place, "bad field access ({:?}: {:?}): {:?}", ty, fty, terr);
1857 }
1858 }
1859 ProjectionElem::OpaqueCast(ty) => {
1860 let ty = self.normalize(ty, location);
1861 self.relate_types(
1862 ty,
1863 context.ambient_variance(),
1864 base_ty.ty,
1865 location.to_locations(),
1866 ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
1867 )
1868 .unwrap();
1869 }
1870 ProjectionElem::UnwrapUnsafeBinder(ty) => {
1871 let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
1872 unreachable!();
1873 };
1874 let found_ty = self.infcx.instantiate_binder_with_fresh_vars(
1875 self.body.source_info(location).span,
1876 BoundRegionConversionTime::HigherRankedType,
1877 binder_ty.into(),
1878 );
1879 self.relate_types(
1880 ty,
1881 context.ambient_variance(),
1882 found_ty,
1883 location.to_locations(),
1884 ConstraintCategory::Boring,
1885 )
1886 .unwrap();
1887 }
1888 ProjectionElem::Subtype(_) => {
1889 bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
1890 }
1891 }
1892 }
1893}
1894
1895impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
1896 fn check_call_dest(
1897 &mut self,
1898 term: &Terminator<'tcx>,
1899 sig: &ty::FnSig<'tcx>,
1900 destination: Place<'tcx>,
1901 target: Option<BasicBlock>,
1902 term_location: Location,
1903 ) {
1904 let tcx = self.tcx();
1905 match target {
1906 Some(_) => {
1907 let dest_ty = destination.ty(self.body, tcx).ty;
1908 let dest_ty = self.normalize(dest_ty, term_location);
1909 let category = match destination.as_local() {
1910 Some(RETURN_PLACE) => {
1911 if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
1912 self.universal_regions.defining_ty
1913 {
1914 if tcx.is_static(def_id) {
1915 ConstraintCategory::UseAsStatic
1916 } else {
1917 ConstraintCategory::UseAsConst
1918 }
1919 } else {
1920 ConstraintCategory::Return(ReturnConstraint::Normal)
1921 }
1922 }
1923 Some(l) if !self.body.local_decls[l].is_user_variable() => {
1924 ConstraintCategory::Boring
1925 }
1926 _ => ConstraintCategory::Assignment,
1928 };
1929
1930 let locations = term_location.to_locations();
1931
1932 if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
1933 span_mirbug!(
1934 self,
1935 term,
1936 "call dest mismatch ({:?} <- {:?}): {:?}",
1937 dest_ty,
1938 sig.output(),
1939 terr
1940 );
1941 }
1942
1943 if self.unsized_feature_enabled() {
1946 let span = term.source_info.span;
1947 self.ensure_place_sized(dest_ty, span);
1948 }
1949 }
1950 None => {
1951 let output_ty = self.tcx().erase_regions(sig.output());
1954 if !output_ty.is_privately_uninhabited(
1955 self.tcx(),
1956 self.infcx.typing_env(self.infcx.param_env),
1957 ) {
1958 span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
1959 }
1960 }
1961 }
1962 }
1963
1964 #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
1965 fn check_call_inputs(
1966 &mut self,
1967 term: &Terminator<'tcx>,
1968 func: &Operand<'tcx>,
1969 sig: &ty::FnSig<'tcx>,
1970 args: &[Spanned<Operand<'tcx>>],
1971 term_location: Location,
1972 call_source: CallSource,
1973 ) {
1974 if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
1975 span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
1976 }
1977
1978 let func_ty = func.ty(self.body, self.infcx.tcx);
1979 if let ty::FnDef(def_id, _) = *func_ty.kind() {
1980 if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
1984 self.tcx().intrinsic(def_id).map(|i| i.name)
1985 {
1986 let idx = match name {
1987 sym::simd_shuffle => 2,
1988 _ => 1,
1989 };
1990 if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) {
1991 self.tcx().dcx().emit_err(SimdIntrinsicArgConst {
1992 span: term.source_info.span,
1993 arg: idx + 1,
1994 intrinsic: name.to_string(),
1995 });
1996 }
1997 }
1998 }
1999 debug!(?func_ty);
2000
2001 for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
2002 let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
2003
2004 let op_arg_ty = self.normalize(op_arg_ty, term_location);
2005 let category = if call_source.from_hir_call() {
2006 ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
2007 } else {
2008 ConstraintCategory::Boring
2009 };
2010 if let Err(terr) =
2011 self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
2012 {
2013 span_mirbug!(
2014 self,
2015 term,
2016 "bad arg #{:?} ({:?} <- {:?}): {:?}",
2017 n,
2018 fn_arg,
2019 op_arg_ty,
2020 terr
2021 );
2022 }
2023 }
2024 }
2025
2026 fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
2027 let is_cleanup = block_data.is_cleanup;
2028 match block_data.terminator().kind {
2029 TerminatorKind::Goto { target } => {
2030 self.assert_iscleanup(block_data, target, is_cleanup)
2031 }
2032 TerminatorKind::SwitchInt { ref targets, .. } => {
2033 for target in targets.all_targets() {
2034 self.assert_iscleanup(block_data, *target, is_cleanup);
2035 }
2036 }
2037 TerminatorKind::UnwindResume => {
2038 if !is_cleanup {
2039 span_mirbug!(self, block_data, "resume on non-cleanup block!")
2040 }
2041 }
2042 TerminatorKind::UnwindTerminate(_) => {
2043 if !is_cleanup {
2044 span_mirbug!(self, block_data, "terminate on non-cleanup block!")
2045 }
2046 }
2047 TerminatorKind::Return => {
2048 if is_cleanup {
2049 span_mirbug!(self, block_data, "return on cleanup block")
2050 }
2051 }
2052 TerminatorKind::TailCall { .. } => {
2053 if is_cleanup {
2054 span_mirbug!(self, block_data, "tailcall on cleanup block")
2055 }
2056 }
2057 TerminatorKind::CoroutineDrop { .. } => {
2058 if is_cleanup {
2059 span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
2060 }
2061 }
2062 TerminatorKind::Yield { resume, drop, .. } => {
2063 if is_cleanup {
2064 span_mirbug!(self, block_data, "yield in cleanup block")
2065 }
2066 self.assert_iscleanup(block_data, resume, is_cleanup);
2067 if let Some(drop) = drop {
2068 self.assert_iscleanup(block_data, drop, is_cleanup);
2069 }
2070 }
2071 TerminatorKind::Unreachable => {}
2072 TerminatorKind::Drop { target, unwind, drop, .. } => {
2073 self.assert_iscleanup(block_data, target, is_cleanup);
2074 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2075 if let Some(drop) = drop {
2076 self.assert_iscleanup(block_data, drop, is_cleanup);
2077 }
2078 }
2079 TerminatorKind::Assert { target, unwind, .. } => {
2080 self.assert_iscleanup(block_data, target, is_cleanup);
2081 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2082 }
2083 TerminatorKind::Call { ref target, unwind, .. } => {
2084 if let &Some(target) = target {
2085 self.assert_iscleanup(block_data, target, is_cleanup);
2086 }
2087 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2088 }
2089 TerminatorKind::FalseEdge { real_target, imaginary_target } => {
2090 self.assert_iscleanup(block_data, real_target, is_cleanup);
2091 self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
2092 }
2093 TerminatorKind::FalseUnwind { real_target, unwind } => {
2094 self.assert_iscleanup(block_data, real_target, is_cleanup);
2095 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2096 }
2097 TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
2098 for &target in targets {
2099 self.assert_iscleanup(block_data, target, is_cleanup);
2100 }
2101 self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2102 }
2103 }
2104 }
2105
2106 fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
2107 if self.body[bb].is_cleanup != iscleanuppad {
2108 span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
2109 }
2110 }
2111
2112 fn assert_iscleanup_unwind(
2113 &mut self,
2114 ctxt: &dyn fmt::Debug,
2115 unwind: UnwindAction,
2116 is_cleanup: bool,
2117 ) {
2118 match unwind {
2119 UnwindAction::Cleanup(unwind) => {
2120 if is_cleanup {
2121 span_mirbug!(self, ctxt, "unwind on cleanup block")
2122 }
2123 self.assert_iscleanup(ctxt, unwind, true);
2124 }
2125 UnwindAction::Continue => {
2126 if is_cleanup {
2127 span_mirbug!(self, ctxt, "unwind on cleanup block")
2128 }
2129 }
2130 UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
2131 }
2132 }
2133
2134 fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
2135 let tcx = self.tcx();
2136
2137 let erased_ty = tcx.erase_regions(ty);
2141 if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
2143 if self.reported_errors.replace((ty, span)).is_none() {
2148 self.tcx().dcx().emit_err(MoveUnsized { ty, span });
2152 }
2153 }
2154 }
2155
2156 fn aggregate_field_ty(
2157 &mut self,
2158 ak: &AggregateKind<'tcx>,
2159 field_index: FieldIdx,
2160 location: Location,
2161 ) -> Result<Ty<'tcx>, FieldAccessError> {
2162 let tcx = self.tcx();
2163
2164 match *ak {
2165 AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
2166 let def = tcx.adt_def(adt_did);
2167 let variant = &def.variant(variant_index);
2168 let adj_field_index = active_field_index.unwrap_or(field_index);
2169 if let Some(field) = variant.fields.get(adj_field_index) {
2170 Ok(self.normalize(field.ty(tcx, args), location))
2171 } else {
2172 Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
2173 }
2174 }
2175 AggregateKind::Closure(_, args) => {
2176 match args.as_closure().upvar_tys().get(field_index.as_usize()) {
2177 Some(ty) => Ok(*ty),
2178 None => Err(FieldAccessError::OutOfRange {
2179 field_count: args.as_closure().upvar_tys().len(),
2180 }),
2181 }
2182 }
2183 AggregateKind::Coroutine(_, args) => {
2184 match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
2188 Some(ty) => Ok(*ty),
2189 None => Err(FieldAccessError::OutOfRange {
2190 field_count: args.as_coroutine().prefix_tys().len(),
2191 }),
2192 }
2193 }
2194 AggregateKind::CoroutineClosure(_, args) => {
2195 match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
2196 Some(ty) => Ok(*ty),
2197 None => Err(FieldAccessError::OutOfRange {
2198 field_count: args.as_coroutine_closure().upvar_tys().len(),
2199 }),
2200 }
2201 }
2202 AggregateKind::Array(ty) => Ok(ty),
2203 AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
2204 unreachable!("This should have been covered in check_rvalues");
2205 }
2206 }
2207 }
2208
2209 fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex> {
2213 match rvalue {
2214 Rvalue::Use(_)
2215 | Rvalue::ThreadLocalRef(_)
2216 | Rvalue::Repeat(..)
2217 | Rvalue::Ref(..)
2218 | Rvalue::RawPtr(..)
2219 | Rvalue::Len(..)
2220 | Rvalue::Cast(..)
2221 | Rvalue::ShallowInitBox(..)
2222 | Rvalue::BinaryOp(..)
2223 | Rvalue::NullaryOp(..)
2224 | Rvalue::CopyForDeref(..)
2225 | Rvalue::UnaryOp(..)
2226 | Rvalue::Discriminant(..)
2227 | Rvalue::WrapUnsafeBinder(..) => None,
2228
2229 Rvalue::Aggregate(aggregate, _) => match **aggregate {
2230 AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,
2231 AggregateKind::Array(_) => None,
2232 AggregateKind::Tuple => None,
2233 AggregateKind::Closure(_, _) => None,
2234 AggregateKind::Coroutine(_, _) => None,
2235 AggregateKind::CoroutineClosure(_, _) => None,
2236 AggregateKind::RawPtr(_, _) => None,
2237 },
2238 }
2239 }
2240
2241 fn check_aggregate_rvalue(
2242 &mut self,
2243 rvalue: &Rvalue<'tcx>,
2244 aggregate_kind: &AggregateKind<'tcx>,
2245 operands: &IndexSlice<FieldIdx, Operand<'tcx>>,
2246 location: Location,
2247 ) {
2248 let tcx = self.tcx();
2249
2250 self.prove_aggregate_predicates(aggregate_kind, location);
2251
2252 if *aggregate_kind == AggregateKind::Tuple {
2253 return;
2255 }
2256
2257 if let AggregateKind::RawPtr(..) = aggregate_kind {
2258 bug!("RawPtr should only be in runtime MIR");
2259 }
2260
2261 for (i, operand) in operands.iter_enumerated() {
2262 let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
2263 Ok(field_ty) => field_ty,
2264 Err(FieldAccessError::OutOfRange { field_count }) => {
2265 span_mirbug!(
2266 self,
2267 rvalue,
2268 "accessed field #{} but variant only has {}",
2269 i.as_u32(),
2270 field_count,
2271 );
2272 continue;
2273 }
2274 };
2275 let operand_ty = operand.ty(self.body, tcx);
2276 let operand_ty = self.normalize(operand_ty, location);
2277
2278 if let Err(terr) = self.sub_types(
2279 operand_ty,
2280 field_ty,
2281 location.to_locations(),
2282 ConstraintCategory::Boring,
2283 ) {
2284 span_mirbug!(
2285 self,
2286 rvalue,
2287 "{:?} is not a subtype of {:?}: {:?}",
2288 operand_ty,
2289 field_ty,
2290 terr
2291 );
2292 }
2293 }
2294 }
2295
2296 fn add_reborrow_constraint(
2304 &mut self,
2305 location: Location,
2306 borrow_region: ty::Region<'tcx>,
2307 borrowed_place: &Place<'tcx>,
2308 ) {
2309 let Self { borrow_set, location_table, polonius_facts, constraints, .. } = self;
2311
2312 if let Some(polonius_facts) = polonius_facts {
2318 let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
2319 if let Some(borrow_index) = borrow_set.get_index_of(&location) {
2320 let region_vid = borrow_region.as_var();
2321 polonius_facts.loan_issued_at.push((
2322 region_vid.into(),
2323 borrow_index,
2324 location_table.mid_index(location),
2325 ));
2326 }
2327 }
2328
2329 debug!(
2335 "add_reborrow_constraint({:?}, {:?}, {:?})",
2336 location, borrow_region, borrowed_place
2337 );
2338
2339 let tcx = self.infcx.tcx;
2340 let def = self.body.source.def_id().expect_local();
2341 let upvars = tcx.closure_captures(def);
2342 let field =
2343 path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), self.body);
2344 let category = if let Some(field) = field {
2345 ConstraintCategory::ClosureUpvar(field)
2346 } else {
2347 ConstraintCategory::Boring
2348 };
2349
2350 for (base, elem) in borrowed_place.as_ref().iter_projections().rev() {
2351 debug!("add_reborrow_constraint - iteration {:?}", elem);
2352
2353 match elem {
2354 ProjectionElem::Deref => {
2355 let base_ty = base.ty(self.body, tcx).ty;
2356
2357 debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
2358 match base_ty.kind() {
2359 ty::Ref(ref_region, _, mutbl) => {
2360 constraints.outlives_constraints.push(OutlivesConstraint {
2361 sup: ref_region.as_var(),
2362 sub: borrow_region.as_var(),
2363 locations: location.to_locations(),
2364 span: location.to_locations().span(self.body),
2365 category,
2366 variance_info: ty::VarianceDiagInfo::default(),
2367 from_closure: false,
2368 });
2369
2370 match mutbl {
2371 hir::Mutability::Not => {
2372 break;
2376 }
2377 hir::Mutability::Mut => {
2378 }
2400 }
2401 }
2402 ty::RawPtr(..) => {
2403 break;
2405 }
2406 ty::Adt(def, _) if def.is_box() => {
2407 }
2409 _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
2410 }
2411 }
2412 ProjectionElem::Field(..)
2413 | ProjectionElem::Downcast(..)
2414 | ProjectionElem::OpaqueCast(..)
2415 | ProjectionElem::Index(..)
2416 | ProjectionElem::ConstantIndex { .. }
2417 | ProjectionElem::Subslice { .. }
2418 | ProjectionElem::UnwrapUnsafeBinder(_) => {
2419 }
2421 ProjectionElem::Subtype(_) => {
2422 bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
2423 }
2424 }
2425 }
2426 }
2427
2428 fn prove_aggregate_predicates(
2429 &mut self,
2430 aggregate_kind: &AggregateKind<'tcx>,
2431 location: Location,
2432 ) {
2433 let tcx = self.tcx();
2434
2435 debug!(
2436 "prove_aggregate_predicates(aggregate_kind={:?}, location={:?})",
2437 aggregate_kind, location
2438 );
2439
2440 let (def_id, instantiated_predicates) = match *aggregate_kind {
2441 AggregateKind::Adt(adt_did, _, args, _, _) => {
2442 (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, args))
2443 }
2444
2445 AggregateKind::Closure(def_id, args)
2465 | AggregateKind::CoroutineClosure(def_id, args)
2466 | AggregateKind::Coroutine(def_id, args) => (
2467 def_id,
2468 self.prove_closure_bounds(
2469 tcx,
2470 def_id.expect_local(),
2471 args,
2472 location.to_locations(),
2473 ),
2474 ),
2475
2476 AggregateKind::Array(_) | AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
2477 (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
2478 }
2479 };
2480
2481 self.normalize_and_prove_instantiated_predicates(
2482 def_id,
2483 instantiated_predicates,
2484 location.to_locations(),
2485 );
2486 }
2487
2488 fn prove_closure_bounds(
2489 &mut self,
2490 tcx: TyCtxt<'tcx>,
2491 def_id: LocalDefId,
2492 args: GenericArgsRef<'tcx>,
2493 locations: Locations,
2494 ) -> ty::InstantiatedPredicates<'tcx> {
2495 if let Some(closure_requirements) = &self.root_cx.closure_requirements(def_id) {
2496 constraint_conversion::ConstraintConversion::new(
2497 self.infcx,
2498 self.universal_regions,
2499 self.region_bound_pairs,
2500 self.infcx.param_env,
2501 self.known_type_outlives_obligations,
2502 locations,
2503 self.body.span, ConstraintCategory::Boring, self.constraints,
2506 )
2507 .apply_closure_requirements(closure_requirements, def_id, args);
2508 }
2509
2510 let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
2512 let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
2513
2514 let parent_args = match tcx.def_kind(def_id) {
2515 DefKind::Closure => {
2519 &args[..typeck_root_args.len()]
2523 }
2524 DefKind::InlineConst => args.as_inline_const().parent_args(),
2525 other => bug!("unexpected item {:?}", other),
2526 };
2527 let parent_args = tcx.mk_args(parent_args);
2528
2529 assert_eq!(typeck_root_args.len(), parent_args.len());
2530 if let Err(_) = self.eq_args(
2531 typeck_root_args,
2532 parent_args,
2533 locations,
2534 ConstraintCategory::BoringNoLocation,
2535 ) {
2536 span_mirbug!(
2537 self,
2538 def_id,
2539 "could not relate closure to parent {:?} != {:?}",
2540 typeck_root_args,
2541 parent_args
2542 );
2543 }
2544
2545 tcx.predicates_of(def_id).instantiate(tcx, args)
2546 }
2547}
2548
2549trait NormalizeLocation: fmt::Debug + Copy {
2550 fn to_locations(self) -> Locations;
2551}
2552
2553impl NormalizeLocation for Locations {
2554 fn to_locations(self) -> Locations {
2555 self
2556 }
2557}
2558
2559impl NormalizeLocation for Location {
2560 fn to_locations(self) -> Locations {
2561 Locations::Single(self)
2562 }
2563}
2564
2565#[derive(Debug)]
2569pub(super) struct InstantiateOpaqueType<'tcx> {
2570 pub base_universe: Option<ty::UniverseIndex>,
2571 pub region_constraints: Option<RegionConstraintData<'tcx>>,
2572 pub obligations: PredicateObligations<'tcx>,
2573}
2574
2575impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
2576 type Output = ();
2577 type ErrorInfo = InstantiateOpaqueType<'tcx>;
2583
2584 fn fully_perform(
2585 mut self,
2586 infcx: &InferCtxt<'tcx>,
2587 span: Span,
2588 ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
2589 let (mut output, region_constraints) = scrape_region_constraints(
2590 infcx,
2591 |ocx| {
2592 ocx.register_obligations(self.obligations.clone());
2593 Ok(())
2594 },
2595 "InstantiateOpaqueType",
2596 span,
2597 )?;
2598 self.region_constraints = Some(region_constraints);
2599 output.error_info = Some(self);
2600 Ok(output)
2601 }
2602}