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