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