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::tcx::PlaceTy;
23use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
24use rustc_middle::mir::*;
25use rustc_middle::traits::query::NoSolution;
26use rustc_middle::ty::adjustment::PointerCoercion;
27use rustc_middle::ty::cast::CastTy;
28use rustc_middle::ty::fold::fold_regions;
29use rustc_middle::ty::visit::TypeVisitableExt;
30use rustc_middle::ty::{
31 self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
32 Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserArgs,
33 UserTypeAnnotationIndex,
34};
35use rustc_middle::{bug, span_bug};
36use rustc_mir_dataflow::ResultsCursor;
37use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
38use rustc_mir_dataflow::move_paths::MoveData;
39use rustc_mir_dataflow::points::DenseLocationMap;
40use rustc_span::def_id::CRATE_DEF_ID;
41use rustc_span::source_map::Spanned;
42use rustc_span::{DUMMY_SP, Span, sym};
43use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
44use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
45use tracing::{debug, instrument, trace};
46
47use crate::borrow_set::BorrowSet;
48use crate::constraints::{OutlivesConstraint, OutlivesConstraintSet};
49use crate::diagnostics::UniverseInfo;
50use crate::member_constraints::MemberConstraintSet;
51use crate::polonius::legacy::{PoloniusFacts, PoloniusLocationTable};
52use crate::polonius::{PoloniusContext, PoloniusLivenessContext};
53use crate::region_infer::TypeTest;
54use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderIndices};
55use crate::renumber::RegionCtxt;
56use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst};
57use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations};
58use crate::universal_regions::{DefiningTy, UniversalRegions};
59use crate::{BorrowckInferCtxt, path_utils};
60
61macro_rules! span_mirbug {
62 ($context:expr, $elem:expr, $($message:tt)*) => ({
63 $crate::type_check::mirbug(
64 $context.tcx(),
65 $context.last_span,
66 format!(
67 "broken MIR in {:?} ({:?}): {}",
68 $context.body().source.def_id(),
69 $elem,
70 format_args!($($message)*),
71 ),
72 )
73 })
74}
75
76mod canonical;
77mod constraint_conversion;
78pub(crate) mod free_region_relations;
79mod input_output;
80pub(crate) mod liveness;
81mod opaque_types;
82mod relate_tys;
83
84pub(crate) fn type_check<'a, 'tcx>(
108 infcx: &BorrowckInferCtxt<'tcx>,
109 body: &Body<'tcx>,
110 promoted: &IndexSlice<Promoted, Body<'tcx>>,
111 universal_regions: UniversalRegions<'tcx>,
112 location_table: &PoloniusLocationTable,
113 borrow_set: &BorrowSet<'tcx>,
114 polonius_facts: &mut Option<PoloniusFacts>,
115 flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
116 move_data: &MoveData<'tcx>,
117 location_map: Rc<DenseLocationMap>,
118) -> MirTypeckResults<'tcx> {
119 let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
120 let mut constraints = MirTypeckRegionConstraints {
121 placeholder_indices: PlaceholderIndices::default(),
122 placeholder_index_to_region: IndexVec::default(),
123 liveness_constraints: LivenessValues::with_specific_points(Rc::clone(&location_map)),
124 outlives_constraints: OutlivesConstraintSet::default(),
125 member_constraints: MemberConstraintSet::default(),
126 type_tests: Vec::default(),
127 universe_causes: FxIndexMap::default(),
128 };
129
130 let CreateResult {
131 universal_region_relations,
132 region_bound_pairs,
133 normalized_inputs_and_output,
134 known_type_outlives_obligations,
135 } = free_region_relations::create(
136 infcx,
137 infcx.param_env,
138 implicit_region_bound,
139 universal_regions,
140 &mut constraints,
141 );
142
143 let pre_obligations = infcx.take_registered_region_obligations();
144 assert!(
145 pre_obligations.is_empty(),
146 "there should be no incoming region obligations = {pre_obligations:#?}",
147 );
148
149 debug!(?normalized_inputs_and_output);
150
151 let polonius_liveness = if infcx.tcx.sess.opts.unstable_opts.polonius.is_next_enabled() {
152 Some(PoloniusLivenessContext::default())
153 } else {
154 None
155 };
156
157 let mut typeck = TypeChecker {
158 infcx,
159 last_span: body.span,
160 body,
161 user_type_annotations: &body.user_type_annotations,
162 region_bound_pairs,
163 known_type_outlives_obligations,
164 implicit_region_bound,
165 reported_errors: Default::default(),
166 universal_regions: &universal_region_relations.universal_regions,
167 location_table,
168 polonius_facts,
169 borrow_set,
170 constraints: &mut constraints,
171 polonius_liveness,
172 };
173
174 typeck.check_user_type_annotations();
175
176 let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span };
177 verifier.visit_body(body);
178
179 typeck.typeck_mir(body);
180 typeck.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
181 typeck.check_signature_annotation(body);
182
183 liveness::generate(&mut typeck, body, &location_map, flow_inits, move_data);
184
185 let opaque_type_values =
186 opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
187
188 let polonius_context = typeck.polonius_liveness.take().map(|liveness_context| {
190 PoloniusContext::create_from_liveness(
191 liveness_context,
192 infcx.num_region_vars(),
193 typeck.constraints.liveness_constraints.points(),
194 )
195 });
196
197 MirTypeckResults {
198 constraints,
199 universal_region_relations,
200 opaque_type_values,
201 polonius_context,
202 }
203}
204
205#[track_caller]
206fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
207 tcx.dcx().span_delayed_bug(span, msg);
211}
212
213enum FieldAccessError {
214 OutOfRange { field_count: usize },
215}
216
217struct TypeVerifier<'a, 'b, 'tcx> {
221 typeck: &'a mut TypeChecker<'b, 'tcx>,
222 promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
223 last_span: Span,
224}
225
226impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
227 fn visit_span(&mut self, span: Span) {
228 if !span.is_dummy() {
229 self.last_span = span;
230 }
231 }
232
233 fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
234 self.super_place(place, context, location);
235 let tcx = self.tcx();
236 let place_ty = place.ty(self.body(), tcx);
237 if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
238 let trait_ref = ty::TraitRef::new(
239 tcx,
240 tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
241 [place_ty.ty],
242 );
243
244 self.typeck.prove_trait_ref(
256 trait_ref,
257 location.to_locations(),
258 ConstraintCategory::CopyBound,
259 );
260 }
261 }
262
263 fn visit_projection_elem(
264 &mut self,
265 place: PlaceRef<'tcx>,
266 elem: PlaceElem<'tcx>,
267 context: PlaceContext,
268 location: Location,
269 ) {
270 let tcx = self.tcx();
271 let base_ty = place.ty(self.body(), tcx);
272 match elem {
273 ProjectionElem::Deref
276 | ProjectionElem::Index(_)
277 | ProjectionElem::ConstantIndex { .. }
278 | ProjectionElem::Subslice { .. }
279 | ProjectionElem::Downcast(..) => {}
280 ProjectionElem::Field(field, fty) => {
281 let fty = self.typeck.normalize(fty, location);
282 let ty = base_ty.field_ty(tcx, field);
283 let ty = self.typeck.normalize(ty, location);
284 debug!(?fty, ?ty);
285
286 if let Err(terr) = self.typeck.relate_types(
287 ty,
288 context.ambient_variance(),
289 fty,
290 location.to_locations(),
291 ConstraintCategory::Boring,
292 ) {
293 span_mirbug!(self, place, "bad field access ({:?}: {:?}): {:?}", ty, fty, terr);
294 }
295 }
296 ProjectionElem::OpaqueCast(ty) => {
297 let ty = self.typeck.normalize(ty, location);
298 self.typeck
299 .relate_types(
300 ty,
301 context.ambient_variance(),
302 base_ty.ty,
303 location.to_locations(),
304 ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
305 )
306 .unwrap();
307 }
308 ProjectionElem::UnwrapUnsafeBinder(ty) => {
309 let ty::UnsafeBinder(binder_ty) = *base_ty.ty.kind() else {
310 unreachable!();
311 };
312 let found_ty = self.typeck.infcx.instantiate_binder_with_fresh_vars(
313 self.body().source_info(location).span,
314 BoundRegionConversionTime::HigherRankedType,
315 binder_ty.into(),
316 );
317 self.typeck
318 .relate_types(
319 ty,
320 context.ambient_variance(),
321 found_ty,
322 location.to_locations(),
323 ConstraintCategory::Boring,
324 )
325 .unwrap();
326 }
327 ProjectionElem::Subtype(_) => {
328 bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
329 }
330 }
331 }
332
333 fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>, location: Location) {
334 debug!(?constant, ?location, "visit_const_operand");
335
336 self.super_const_operand(constant, location);
337 let ty = constant.const_.ty();
338
339 self.typeck.infcx.tcx.for_each_free_region(&ty, |live_region| {
340 let live_region_vid = self.typeck.universal_regions.to_region_vid(live_region);
341 self.typeck.constraints.liveness_constraints.add_location(live_region_vid, location);
342 });
343
344 let locations = if location != Location::START {
347 location.to_locations()
348 } else {
349 Locations::All(constant.span)
350 };
351
352 if let Some(annotation_index) = constant.user_ty {
353 if let Err(terr) = self.typeck.relate_type_and_user_type(
354 constant.const_.ty(),
355 ty::Invariant,
356 &UserTypeProjection { base: annotation_index, projs: vec![] },
357 locations,
358 ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
359 ) {
360 let annotation = &self.typeck.user_type_annotations[annotation_index];
361 span_mirbug!(
362 self,
363 constant,
364 "bad constant user type {:?} vs {:?}: {:?}",
365 annotation,
366 constant.const_.ty(),
367 terr,
368 );
369 }
370 } else {
371 let tcx = self.tcx();
372 let maybe_uneval = match constant.const_ {
373 Const::Ty(_, ct) => match ct.kind() {
374 ty::ConstKind::Unevaluated(uv) => {
375 Some(UnevaluatedConst { def: uv.def, args: uv.args, promoted: None })
376 }
377 _ => None,
378 },
379 Const::Unevaluated(uv, _) => Some(uv),
380 _ => None,
381 };
382
383 if let Some(uv) = maybe_uneval {
384 if let Some(promoted) = uv.promoted {
385 let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
386 promoted: &Body<'tcx>,
387 ty,
388 san_ty| {
389 if let Err(terr) = verifier.typeck.eq_types(
390 ty,
391 san_ty,
392 locations,
393 ConstraintCategory::Boring,
394 ) {
395 span_mirbug!(
396 verifier,
397 promoted,
398 "bad promoted type ({:?}: {:?}): {:?}",
399 ty,
400 san_ty,
401 terr
402 );
403 };
404 };
405
406 let promoted_body = &self.promoted[promoted];
407 self.verify_promoted(promoted_body, location);
408
409 let promoted_ty = promoted_body.return_ty();
410 check_err(self, promoted_body, ty, promoted_ty);
411 } else {
412 self.typeck.ascribe_user_type(
413 constant.const_.ty(),
414 ty::UserType::new(ty::UserTypeKind::TypeOf(
415 uv.def,
416 UserArgs { args: uv.args, user_self_ty: None },
417 )),
418 locations.span(self.typeck.body),
419 );
420 }
421 } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
422 let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity();
423 let normalized_ty = self.typeck.normalize(unnormalized_ty, locations);
424 let literal_ty = constant.const_.ty().builtin_deref(true).unwrap();
425
426 if let Err(terr) = self.typeck.eq_types(
427 literal_ty,
428 normalized_ty,
429 locations,
430 ConstraintCategory::Boring,
431 ) {
432 span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
433 }
434 }
435
436 if let ty::FnDef(def_id, args) = *constant.const_.ty().kind() {
437 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args);
438 self.typeck.normalize_and_prove_instantiated_predicates(
439 def_id,
440 instantiated_predicates,
441 locations,
442 );
443
444 assert!(!matches!(
445 tcx.impl_of_method(def_id).map(|imp| tcx.def_kind(imp)),
446 Some(DefKind::Impl { of_trait: true })
447 ));
448 self.typeck.prove_predicates(
449 args.types().map(|ty| ty::ClauseKind::WellFormed(ty.into())),
450 locations,
451 ConstraintCategory::Boring,
452 );
453 }
454 }
455 }
456
457 fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
458 self.super_local_decl(local, local_decl);
459
460 if let Some(user_ty) = &local_decl.user_ty {
461 for (user_ty, span) in user_ty.projections_and_spans() {
462 let ty = if !local_decl.is_nonref_binding() {
463 if let ty::Ref(_, rty, _) = local_decl.ty.kind() {
467 *rty
468 } else {
469 bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
470 }
471 } else {
472 local_decl.ty
473 };
474
475 if let Err(terr) = self.typeck.relate_type_and_user_type(
476 ty,
477 ty::Invariant,
478 user_ty,
479 Locations::All(*span),
480 ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
481 ) {
482 span_mirbug!(
483 self,
484 local,
485 "bad user type on variable {:?}: {:?} != {:?} ({:?})",
486 local,
487 local_decl.ty,
488 local_decl.user_ty,
489 terr,
490 );
491 }
492 }
493 }
494 }
495
496 fn visit_body(&mut self, body: &Body<'tcx>) {
497 self.super_body(body);
499 }
500}
501
502impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
503 fn body(&self) -> &Body<'tcx> {
504 self.typeck.body
505 }
506
507 fn tcx(&self) -> TyCtxt<'tcx> {
508 self.typeck.infcx.tcx
509 }
510
511 fn verify_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) {
512 let parent_body = mem::replace(&mut self.typeck.body, promoted_body);
517
518 let polonius_facts = &mut None;
521 let mut constraints = Default::default();
522 let mut liveness_constraints =
523 LivenessValues::without_specific_points(Rc::new(DenseLocationMap::new(promoted_body)));
524 let mut swap_constraints = |this: &mut Self| {
527 mem::swap(this.typeck.polonius_facts, polonius_facts);
528 mem::swap(&mut this.typeck.constraints.outlives_constraints, &mut constraints);
529 mem::swap(&mut this.typeck.constraints.liveness_constraints, &mut liveness_constraints);
530 };
531
532 swap_constraints(self);
533
534 self.visit_body(promoted_body);
535
536 self.typeck.typeck_mir(promoted_body);
537
538 self.typeck.body = parent_body;
539 swap_constraints(self);
541
542 let locations = location.to_locations();
543 for constraint in constraints.outlives().iter() {
544 let mut constraint = *constraint;
545 constraint.locations = locations;
546 if let ConstraintCategory::Return(_)
547 | ConstraintCategory::UseAsConst
548 | ConstraintCategory::UseAsStatic = constraint.category
549 {
550 constraint.category = ConstraintCategory::Boring;
553 }
554 self.typeck.constraints.outlives_constraints.push(constraint)
555 }
556 #[allow(rustc::potential_query_instability)]
563 for region in liveness_constraints.live_regions_unordered() {
564 self.typeck.constraints.liveness_constraints.add_location(region, location);
565 }
566 }
567}
568
569struct TypeChecker<'a, 'tcx> {
574 infcx: &'a BorrowckInferCtxt<'tcx>,
575 last_span: Span,
576 body: &'a Body<'tcx>,
577 user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
580 region_bound_pairs: RegionBoundPairs<'tcx>,
581 known_type_outlives_obligations: Vec<ty::PolyTypeOutlivesPredicate<'tcx>>,
582 implicit_region_bound: ty::Region<'tcx>,
583 reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
584 universal_regions: &'a UniversalRegions<'tcx>,
585 location_table: &'a PoloniusLocationTable,
586 polonius_facts: &'a mut Option<PoloniusFacts>,
587 borrow_set: &'a BorrowSet<'tcx>,
588 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
589 polonius_liveness: Option<PoloniusLivenessContext>,
591}
592
593pub(crate) struct MirTypeckResults<'tcx> {
596 pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
597 pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
598 pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
599 pub(crate) polonius_context: Option<PoloniusContext>,
600}
601
602pub(crate) struct MirTypeckRegionConstraints<'tcx> {
605 pub(crate) placeholder_indices: PlaceholderIndices,
611
612 pub(crate) placeholder_index_to_region: IndexVec<PlaceholderIndex, ty::Region<'tcx>>,
618
619 pub(crate) liveness_constraints: LivenessValues,
627
628 pub(crate) outlives_constraints: OutlivesConstraintSet<'tcx>,
629
630 pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
631
632 pub(crate) universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
633
634 pub(crate) type_tests: Vec<TypeTest<'tcx>>,
635}
636
637impl<'tcx> MirTypeckRegionConstraints<'tcx> {
638 fn placeholder_region(
641 &mut self,
642 infcx: &InferCtxt<'tcx>,
643 placeholder: ty::PlaceholderRegion,
644 ) -> ty::Region<'tcx> {
645 let placeholder_index = self.placeholder_indices.insert(placeholder);
646 match self.placeholder_index_to_region.get(placeholder_index) {
647 Some(&v) => v,
648 None => {
649 let origin = NllRegionVariableOrigin::Placeholder(placeholder);
650 let region = infcx.next_nll_region_var_in_universe(origin, placeholder.universe);
651 self.placeholder_index_to_region.push(region);
652 region
653 }
654 }
655 }
656}
657
658#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
663pub enum Locations {
664 All(Span),
700
701 Single(Location),
705}
706
707impl Locations {
708 pub fn from_location(&self) -> Option<Location> {
709 match self {
710 Locations::All(_) => None,
711 Locations::Single(from_location) => Some(*from_location),
712 }
713 }
714
715 pub fn span(&self, body: &Body<'_>) -> Span {
717 match self {
718 Locations::All(span) => *span,
719 Locations::Single(l) => body.source_info(*l).span,
720 }
721 }
722}
723
724impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
725 fn body(&self) -> &Body<'tcx> {
726 self.body
727 }
728
729 fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> RegionVid {
730 if let ty::RePlaceholder(placeholder) = r.kind() {
731 self.constraints.placeholder_region(self.infcx, placeholder).as_var()
732 } else {
733 self.universal_regions.to_region_vid(r)
734 }
735 }
736
737 fn unsized_feature_enabled(&self) -> bool {
738 let features = self.tcx().features();
739 features.unsized_locals() || features.unsized_fn_params()
740 }
741
742 #[instrument(skip(self), level = "debug")]
744 fn check_user_type_annotations(&mut self) {
745 debug!(?self.user_type_annotations);
746 let tcx = self.tcx();
747 for user_annotation in self.user_type_annotations {
748 let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
749 let annotation = self.instantiate_canonical(span, user_ty);
750 if let ty::UserTypeKind::TypeOf(def, args) = annotation.kind
751 && let DefKind::InlineConst = tcx.def_kind(def)
752 {
753 assert!(annotation.bounds.is_empty());
754 self.check_inline_const(inferred_ty, def.expect_local(), args, span);
755 } else {
756 self.ascribe_user_type(inferred_ty, annotation, span);
757 }
758 }
759 }
760
761 #[instrument(skip(self, data), level = "debug")]
762 fn push_region_constraints(
763 &mut self,
764 locations: Locations,
765 category: ConstraintCategory<'tcx>,
766 data: &QueryRegionConstraints<'tcx>,
767 ) {
768 debug!("constraints generated: {:#?}", data);
769
770 constraint_conversion::ConstraintConversion::new(
771 self.infcx,
772 self.universal_regions,
773 &self.region_bound_pairs,
774 self.implicit_region_bound,
775 self.infcx.param_env,
776 &self.known_type_outlives_obligations,
777 locations,
778 locations.span(self.body),
779 category,
780 self.constraints,
781 )
782 .convert_all(data);
783 }
784
785 fn sub_types(
787 &mut self,
788 sub: Ty<'tcx>,
789 sup: Ty<'tcx>,
790 locations: Locations,
791 category: ConstraintCategory<'tcx>,
792 ) -> Result<(), NoSolution> {
793 self.relate_types(sup, ty::Contravariant, sub, locations, category)
796 }
797
798 #[instrument(skip(self, category), level = "debug")]
799 fn eq_types(
800 &mut self,
801 expected: Ty<'tcx>,
802 found: Ty<'tcx>,
803 locations: Locations,
804 category: ConstraintCategory<'tcx>,
805 ) -> Result<(), NoSolution> {
806 self.relate_types(expected, ty::Invariant, found, locations, category)
807 }
808
809 #[instrument(skip(self), level = "debug")]
810 fn relate_type_and_user_type(
811 &mut self,
812 a: Ty<'tcx>,
813 v: ty::Variance,
814 user_ty: &UserTypeProjection,
815 locations: Locations,
816 category: ConstraintCategory<'tcx>,
817 ) -> Result<(), NoSolution> {
818 let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
819 trace!(?annotated_type);
820 let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
821
822 let tcx = self.infcx.tcx;
823
824 for proj in &user_ty.projs {
825 if !self.infcx.next_trait_solver()
826 && let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind()
827 {
828 return Ok(());
832 }
833 let projected_ty = curr_projected_ty.projection_ty_core(
834 tcx,
835 proj,
836 |this, field, ()| {
837 let ty = this.field_ty(tcx, field);
838 self.structurally_resolve(ty, locations)
839 },
840 |_, _| unreachable!(),
841 );
842 curr_projected_ty = projected_ty;
843 }
844 trace!(?curr_projected_ty);
845
846 let ty = curr_projected_ty.ty;
847 self.relate_types(ty, v.xform(ty::Contravariant), a, locations, category)?;
848
849 Ok(())
850 }
851
852 fn check_inline_const(
853 &mut self,
854 inferred_ty: Ty<'tcx>,
855 def_id: LocalDefId,
856 args: UserArgs<'tcx>,
857 span: Span,
858 ) {
859 assert!(args.user_self_ty.is_none());
860 let tcx = self.tcx();
861 let const_ty = tcx.type_of(def_id).instantiate(tcx, args.args);
862 if let Err(terr) =
863 self.eq_types(const_ty, inferred_ty, Locations::All(span), ConstraintCategory::Boring)
864 {
865 span_bug!(
866 span,
867 "bad inline const pattern: ({:?} = {:?}) {:?}",
868 const_ty,
869 inferred_ty,
870 terr
871 );
872 }
873 let args = self.infcx.resolve_vars_if_possible(args.args);
874 let predicates = self.prove_closure_bounds(tcx, def_id, args, Locations::All(span));
875 self.normalize_and_prove_instantiated_predicates(
876 def_id.to_def_id(),
877 predicates,
878 Locations::All(span),
879 );
880 }
881
882 fn tcx(&self) -> TyCtxt<'tcx> {
883 self.infcx.tcx
884 }
885
886 #[instrument(skip(self, body), level = "debug")]
887 fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
888 let tcx = self.tcx();
889 debug!("stmt kind: {:?}", stmt.kind);
890 match &stmt.kind {
891 StatementKind::Assign(box (place, rv)) => {
892 let category = match place.as_local() {
897 Some(RETURN_PLACE) => {
898 let defining_ty = &self.universal_regions.defining_ty;
899 if defining_ty.is_const() {
900 if tcx.is_static(defining_ty.def_id()) {
901 ConstraintCategory::UseAsStatic
902 } else {
903 ConstraintCategory::UseAsConst
904 }
905 } else {
906 ConstraintCategory::Return(ReturnConstraint::Normal)
907 }
908 }
909 Some(l)
910 if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) =>
911 {
912 ConstraintCategory::Usage
913 }
914 Some(l) if !body.local_decls[l].is_user_variable() => {
915 ConstraintCategory::Boring
916 }
917 _ => ConstraintCategory::Assignment,
918 };
919 debug!(
920 "assignment category: {:?} {:?}",
921 category,
922 place.as_local().map(|l| &body.local_decls[l])
923 );
924
925 let place_ty = place.ty(body, tcx).ty;
926 debug!(?place_ty);
927 let place_ty = self.normalize(place_ty, location);
928 debug!("place_ty normalized: {:?}", place_ty);
929 let rv_ty = rv.ty(body, tcx);
930 debug!(?rv_ty);
931 let rv_ty = self.normalize(rv_ty, location);
932 debug!("normalized rv_ty: {:?}", rv_ty);
933 if let Err(terr) =
934 self.sub_types(rv_ty, place_ty, location.to_locations(), category)
935 {
936 span_mirbug!(
937 self,
938 stmt,
939 "bad assignment ({:?} = {:?}): {:?}",
940 place_ty,
941 rv_ty,
942 terr
943 );
944 }
945
946 if let Some(annotation_index) = self.rvalue_user_ty(rv) {
947 if let Err(terr) = self.relate_type_and_user_type(
948 rv_ty,
949 ty::Invariant,
950 &UserTypeProjection { base: annotation_index, projs: vec![] },
951 location.to_locations(),
952 ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
953 ) {
954 let annotation = &self.user_type_annotations[annotation_index];
955 span_mirbug!(
956 self,
957 stmt,
958 "bad user type on rvalue ({:?} = {:?}): {:?}",
959 annotation,
960 rv_ty,
961 terr
962 );
963 }
964 }
965
966 self.check_rvalue(body, rv, location);
967 if !self.unsized_feature_enabled() {
968 let trait_ref = ty::TraitRef::new(
969 tcx,
970 tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
971 [place_ty],
972 );
973 self.prove_trait_ref(
974 trait_ref,
975 location.to_locations(),
976 ConstraintCategory::SizedBound,
977 );
978 }
979 }
980 StatementKind::AscribeUserType(box (place, projection), variance) => {
981 let place_ty = place.ty(body, tcx).ty;
982 if let Err(terr) = self.relate_type_and_user_type(
983 place_ty,
984 *variance,
985 projection,
986 Locations::All(stmt.source_info.span),
987 ConstraintCategory::TypeAnnotation(AnnotationSource::Ascription),
988 ) {
989 let annotation = &self.user_type_annotations[projection.base];
990 span_mirbug!(
991 self,
992 stmt,
993 "bad type assert ({:?} <: {:?} with projections {:?}): {:?}",
994 place_ty,
995 annotation,
996 projection.projs,
997 terr
998 );
999 }
1000 }
1001 StatementKind::Intrinsic(box kind) => match kind {
1002 NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
1003 NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
1004 stmt.source_info.span,
1005 "Unexpected NonDivergingIntrinsic::CopyNonOverlapping, should only appear after lowering_intrinsics",
1006 ),
1007 },
1008 StatementKind::FakeRead(..)
1009 | StatementKind::StorageLive(..)
1010 | StatementKind::StorageDead(..)
1011 | StatementKind::Retag { .. }
1012 | StatementKind::Coverage(..)
1013 | StatementKind::ConstEvalCounter
1014 | StatementKind::PlaceMention(..)
1015 | StatementKind::BackwardIncompatibleDropHint { .. }
1016 | StatementKind::Nop => {}
1017 StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
1018 bug!("Statement not allowed in this MIR phase")
1019 }
1020 }
1021 }
1022
1023 #[instrument(skip(self, body, term_location), level = "debug")]
1024 fn check_terminator(
1025 &mut self,
1026 body: &Body<'tcx>,
1027 term: &Terminator<'tcx>,
1028 term_location: Location,
1029 ) {
1030 let tcx = self.tcx();
1031 debug!("terminator kind: {:?}", term.kind);
1032 match &term.kind {
1033 TerminatorKind::Goto { .. }
1034 | TerminatorKind::UnwindResume
1035 | TerminatorKind::UnwindTerminate(_)
1036 | TerminatorKind::Return
1037 | TerminatorKind::CoroutineDrop
1038 | TerminatorKind::Unreachable
1039 | TerminatorKind::Drop { .. }
1040 | TerminatorKind::FalseEdge { .. }
1041 | TerminatorKind::FalseUnwind { .. }
1042 | TerminatorKind::InlineAsm { .. } => {
1043 }
1045
1046 TerminatorKind::SwitchInt { discr, .. } => {
1047 self.check_operand(discr, term_location);
1048
1049 let switch_ty = discr.ty(body, tcx);
1050 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
1051 span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
1052 }
1053 }
1055 TerminatorKind::Call { func, args, .. }
1056 | TerminatorKind::TailCall { func, args, .. } => {
1057 let call_source = match term.kind {
1058 TerminatorKind::Call { call_source, .. } => call_source,
1059 TerminatorKind::TailCall { .. } => CallSource::Normal,
1060 _ => unreachable!(),
1061 };
1062
1063 self.check_operand(func, term_location);
1064 for arg in args {
1065 self.check_operand(&arg.node, term_location);
1066 }
1067
1068 let func_ty = func.ty(body, tcx);
1069 debug!("func_ty.kind: {:?}", func_ty.kind());
1070
1071 let sig = match func_ty.kind() {
1072 ty::FnDef(..) | ty::FnPtr(..) => func_ty.fn_sig(tcx),
1073 _ => {
1074 span_mirbug!(self, term, "call to non-function {:?}", func_ty);
1075 return;
1076 }
1077 };
1078 let (unnormalized_sig, map) = tcx.instantiate_bound_regions(sig, |br| {
1079 use crate::renumber::RegionCtxt;
1080
1081 let region_ctxt_fn = || {
1082 let reg_info = match br.kind {
1083 ty::BoundRegionKind::Anon => sym::anon,
1084 ty::BoundRegionKind::Named(_, name) => name,
1085 ty::BoundRegionKind::ClosureEnv => sym::env,
1086 };
1087
1088 RegionCtxt::LateBound(reg_info)
1089 };
1090
1091 self.infcx.next_region_var(
1092 BoundRegion(
1093 term.source_info.span,
1094 br.kind,
1095 BoundRegionConversionTime::FnCall,
1096 ),
1097 region_ctxt_fn,
1098 )
1099 });
1100 debug!(?unnormalized_sig);
1101 self.prove_predicates(
1110 unnormalized_sig.inputs_and_output.iter().map(|ty| {
1111 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
1112 ty.into(),
1113 )))
1114 }),
1115 term_location.to_locations(),
1116 ConstraintCategory::Boring,
1117 );
1118
1119 let sig = self.deeply_normalize(unnormalized_sig, term_location);
1120 if sig != unnormalized_sig {
1124 self.prove_predicates(
1125 sig.inputs_and_output.iter().map(|ty| {
1126 ty::Binder::dummy(ty::PredicateKind::Clause(
1127 ty::ClauseKind::WellFormed(ty.into()),
1128 ))
1129 }),
1130 term_location.to_locations(),
1131 ConstraintCategory::Boring,
1132 );
1133 }
1134
1135 if let TerminatorKind::Call { destination, target, .. } = term.kind {
1136 self.check_call_dest(body, term, &sig, destination, target, term_location);
1137 }
1138
1139 for &late_bound_region in map.values() {
1147 let region_vid = self.universal_regions.to_region_vid(late_bound_region);
1148 self.constraints.liveness_constraints.add_location(region_vid, term_location);
1149 }
1150
1151 self.check_call_inputs(body, term, func, &sig, args, term_location, call_source);
1152 }
1153 TerminatorKind::Assert { cond, msg, .. } => {
1154 self.check_operand(cond, term_location);
1155
1156 let cond_ty = cond.ty(body, tcx);
1157 if cond_ty != tcx.types.bool {
1158 span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
1159 }
1160
1161 if let AssertKind::BoundsCheck { len, index } = &**msg {
1162 if len.ty(body, tcx) != tcx.types.usize {
1163 span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
1164 }
1165 if index.ty(body, tcx) != tcx.types.usize {
1166 span_mirbug!(self, index, "bounds-check index non-usize {:?}", index)
1167 }
1168 }
1169 }
1170 TerminatorKind::Yield { value, resume_arg, .. } => {
1171 self.check_operand(value, term_location);
1172
1173 match body.yield_ty() {
1174 None => span_mirbug!(self, term, "yield in non-coroutine"),
1175 Some(ty) => {
1176 let value_ty = value.ty(body, tcx);
1177 if let Err(terr) = self.sub_types(
1178 value_ty,
1179 ty,
1180 term_location.to_locations(),
1181 ConstraintCategory::Yield,
1182 ) {
1183 span_mirbug!(
1184 self,
1185 term,
1186 "type of yield value is {:?}, but the yield type is {:?}: {:?}",
1187 value_ty,
1188 ty,
1189 terr
1190 );
1191 }
1192 }
1193 }
1194
1195 match body.resume_ty() {
1196 None => span_mirbug!(self, term, "yield in non-coroutine"),
1197 Some(ty) => {
1198 let resume_ty = resume_arg.ty(body, tcx);
1199 if let Err(terr) = self.sub_types(
1200 ty,
1201 resume_ty.ty,
1202 term_location.to_locations(),
1203 ConstraintCategory::Yield,
1204 ) {
1205 span_mirbug!(
1206 self,
1207 term,
1208 "type of resume place is {:?}, but the resume type is {:?}: {:?}",
1209 resume_ty,
1210 ty,
1211 terr
1212 );
1213 }
1214 }
1215 }
1216 }
1217 }
1218 }
1219
1220 fn check_call_dest(
1221 &mut self,
1222 body: &Body<'tcx>,
1223 term: &Terminator<'tcx>,
1224 sig: &ty::FnSig<'tcx>,
1225 destination: Place<'tcx>,
1226 target: Option<BasicBlock>,
1227 term_location: Location,
1228 ) {
1229 let tcx = self.tcx();
1230 match target {
1231 Some(_) => {
1232 let dest_ty = destination.ty(body, tcx).ty;
1233 let dest_ty = self.normalize(dest_ty, term_location);
1234 let category = match destination.as_local() {
1235 Some(RETURN_PLACE) => {
1236 if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
1237 self.universal_regions.defining_ty
1238 {
1239 if tcx.is_static(def_id) {
1240 ConstraintCategory::UseAsStatic
1241 } else {
1242 ConstraintCategory::UseAsConst
1243 }
1244 } else {
1245 ConstraintCategory::Return(ReturnConstraint::Normal)
1246 }
1247 }
1248 Some(l) if !body.local_decls[l].is_user_variable() => {
1249 ConstraintCategory::Boring
1250 }
1251 _ => ConstraintCategory::Assignment,
1253 };
1254
1255 let locations = term_location.to_locations();
1256
1257 if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
1258 span_mirbug!(
1259 self,
1260 term,
1261 "call dest mismatch ({:?} <- {:?}): {:?}",
1262 dest_ty,
1263 sig.output(),
1264 terr
1265 );
1266 }
1267
1268 if self.unsized_feature_enabled() {
1271 let span = term.source_info.span;
1272 self.ensure_place_sized(dest_ty, span);
1273 }
1274 }
1275 None => {
1276 let output_ty = self.tcx().erase_regions(sig.output());
1279 if !output_ty.is_privately_uninhabited(
1280 self.tcx(),
1281 self.infcx.typing_env(self.infcx.param_env),
1282 ) {
1283 span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
1284 }
1285 }
1286 }
1287 }
1288
1289 #[instrument(level = "debug", skip(self, body, term, func, term_location, call_source))]
1290 fn check_call_inputs(
1291 &mut self,
1292 body: &Body<'tcx>,
1293 term: &Terminator<'tcx>,
1294 func: &Operand<'tcx>,
1295 sig: &ty::FnSig<'tcx>,
1296 args: &[Spanned<Operand<'tcx>>],
1297 term_location: Location,
1298 call_source: CallSource,
1299 ) {
1300 if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
1301 span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
1302 }
1303
1304 let func_ty = func.ty(body, self.infcx.tcx);
1305 if let ty::FnDef(def_id, _) = *func_ty.kind() {
1306 if let Some(name @ (sym::simd_shuffle | sym::simd_insert | sym::simd_extract)) =
1310 self.tcx().intrinsic(def_id).map(|i| i.name)
1311 {
1312 let idx = match name {
1313 sym::simd_shuffle => 2,
1314 _ => 1,
1315 };
1316 if !matches!(args[idx], Spanned { node: Operand::Constant(_), .. }) {
1317 self.tcx().dcx().emit_err(SimdIntrinsicArgConst {
1318 span: term.source_info.span,
1319 arg: idx + 1,
1320 intrinsic: name.to_string(),
1321 });
1322 }
1323 }
1324 }
1325 debug!(?func_ty);
1326
1327 for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
1328 let op_arg_ty = op_arg.node.ty(body, self.tcx());
1329
1330 let op_arg_ty = self.normalize(op_arg_ty, term_location);
1331 let category = if call_source.from_hir_call() {
1332 ConstraintCategory::CallArgument(Some(self.infcx.tcx.erase_regions(func_ty)))
1333 } else {
1334 ConstraintCategory::Boring
1335 };
1336 if let Err(terr) =
1337 self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
1338 {
1339 span_mirbug!(
1340 self,
1341 term,
1342 "bad arg #{:?} ({:?} <- {:?}): {:?}",
1343 n,
1344 fn_arg,
1345 op_arg_ty,
1346 terr
1347 );
1348 }
1349 }
1350 }
1351
1352 fn check_iscleanup(&mut self, body: &Body<'tcx>, block_data: &BasicBlockData<'tcx>) {
1353 let is_cleanup = block_data.is_cleanup;
1354 self.last_span = block_data.terminator().source_info.span;
1355 match block_data.terminator().kind {
1356 TerminatorKind::Goto { target } => {
1357 self.assert_iscleanup(body, block_data, target, is_cleanup)
1358 }
1359 TerminatorKind::SwitchInt { ref targets, .. } => {
1360 for target in targets.all_targets() {
1361 self.assert_iscleanup(body, block_data, *target, is_cleanup);
1362 }
1363 }
1364 TerminatorKind::UnwindResume => {
1365 if !is_cleanup {
1366 span_mirbug!(self, block_data, "resume on non-cleanup block!")
1367 }
1368 }
1369 TerminatorKind::UnwindTerminate(_) => {
1370 if !is_cleanup {
1371 span_mirbug!(self, block_data, "terminate on non-cleanup block!")
1372 }
1373 }
1374 TerminatorKind::Return => {
1375 if is_cleanup {
1376 span_mirbug!(self, block_data, "return on cleanup block")
1377 }
1378 }
1379 TerminatorKind::TailCall { .. } => {
1380 if is_cleanup {
1381 span_mirbug!(self, block_data, "tailcall on cleanup block")
1382 }
1383 }
1384 TerminatorKind::CoroutineDrop { .. } => {
1385 if is_cleanup {
1386 span_mirbug!(self, block_data, "coroutine_drop in cleanup block")
1387 }
1388 }
1389 TerminatorKind::Yield { resume, drop, .. } => {
1390 if is_cleanup {
1391 span_mirbug!(self, block_data, "yield in cleanup block")
1392 }
1393 self.assert_iscleanup(body, block_data, resume, is_cleanup);
1394 if let Some(drop) = drop {
1395 self.assert_iscleanup(body, block_data, drop, is_cleanup);
1396 }
1397 }
1398 TerminatorKind::Unreachable => {}
1399 TerminatorKind::Drop { target, unwind, .. }
1400 | TerminatorKind::Assert { target, unwind, .. } => {
1401 self.assert_iscleanup(body, block_data, target, is_cleanup);
1402 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1403 }
1404 TerminatorKind::Call { ref target, unwind, .. } => {
1405 if let &Some(target) = target {
1406 self.assert_iscleanup(body, block_data, target, is_cleanup);
1407 }
1408 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1409 }
1410 TerminatorKind::FalseEdge { real_target, imaginary_target } => {
1411 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
1412 self.assert_iscleanup(body, block_data, imaginary_target, is_cleanup);
1413 }
1414 TerminatorKind::FalseUnwind { real_target, unwind } => {
1415 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
1416 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1417 }
1418 TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
1419 for &target in targets {
1420 self.assert_iscleanup(body, block_data, target, is_cleanup);
1421 }
1422 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1423 }
1424 }
1425 }
1426
1427 fn assert_iscleanup(
1428 &mut self,
1429 body: &Body<'tcx>,
1430 ctxt: &dyn fmt::Debug,
1431 bb: BasicBlock,
1432 iscleanuppad: bool,
1433 ) {
1434 if body[bb].is_cleanup != iscleanuppad {
1435 span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
1436 }
1437 }
1438
1439 fn assert_iscleanup_unwind(
1440 &mut self,
1441 body: &Body<'tcx>,
1442 ctxt: &dyn fmt::Debug,
1443 unwind: UnwindAction,
1444 is_cleanup: bool,
1445 ) {
1446 match unwind {
1447 UnwindAction::Cleanup(unwind) => {
1448 if is_cleanup {
1449 span_mirbug!(self, ctxt, "unwind on cleanup block")
1450 }
1451 self.assert_iscleanup(body, ctxt, unwind, true);
1452 }
1453 UnwindAction::Continue => {
1454 if is_cleanup {
1455 span_mirbug!(self, ctxt, "unwind on cleanup block")
1456 }
1457 }
1458 UnwindAction::Unreachable | UnwindAction::Terminate(_) => (),
1459 }
1460 }
1461
1462 fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
1463 match body.local_kind(local) {
1464 LocalKind::ReturnPointer | LocalKind::Arg => {
1465 return;
1472 }
1473 LocalKind::Temp => {}
1474 }
1475
1476 if !self.unsized_feature_enabled() {
1479 let span = local_decl.source_info.span;
1480 let ty = local_decl.ty;
1481 self.ensure_place_sized(ty, span);
1482 }
1483 }
1484
1485 fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
1486 let tcx = self.tcx();
1487
1488 let erased_ty = tcx.erase_regions(ty);
1492 if !erased_ty.is_sized(tcx, self.infcx.typing_env(self.infcx.param_env)) {
1494 if self.reported_errors.replace((ty, span)).is_none() {
1499 self.tcx().dcx().emit_err(MoveUnsized { ty, span });
1503 }
1504 }
1505 }
1506
1507 fn aggregate_field_ty(
1508 &mut self,
1509 ak: &AggregateKind<'tcx>,
1510 field_index: FieldIdx,
1511 location: Location,
1512 ) -> Result<Ty<'tcx>, FieldAccessError> {
1513 let tcx = self.tcx();
1514
1515 match *ak {
1516 AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => {
1517 let def = tcx.adt_def(adt_did);
1518 let variant = &def.variant(variant_index);
1519 let adj_field_index = active_field_index.unwrap_or(field_index);
1520 if let Some(field) = variant.fields.get(adj_field_index) {
1521 Ok(self.normalize(field.ty(tcx, args), location))
1522 } else {
1523 Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
1524 }
1525 }
1526 AggregateKind::Closure(_, args) => {
1527 match args.as_closure().upvar_tys().get(field_index.as_usize()) {
1528 Some(ty) => Ok(*ty),
1529 None => Err(FieldAccessError::OutOfRange {
1530 field_count: args.as_closure().upvar_tys().len(),
1531 }),
1532 }
1533 }
1534 AggregateKind::Coroutine(_, args) => {
1535 match args.as_coroutine().prefix_tys().get(field_index.as_usize()) {
1539 Some(ty) => Ok(*ty),
1540 None => Err(FieldAccessError::OutOfRange {
1541 field_count: args.as_coroutine().prefix_tys().len(),
1542 }),
1543 }
1544 }
1545 AggregateKind::CoroutineClosure(_, args) => {
1546 match args.as_coroutine_closure().upvar_tys().get(field_index.as_usize()) {
1547 Some(ty) => Ok(*ty),
1548 None => Err(FieldAccessError::OutOfRange {
1549 field_count: args.as_coroutine_closure().upvar_tys().len(),
1550 }),
1551 }
1552 }
1553 AggregateKind::Array(ty) => Ok(ty),
1554 AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
1555 unreachable!("This should have been covered in check_rvalues");
1556 }
1557 }
1558 }
1559
1560 fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
1561 debug!(?op, ?location, "check_operand");
1562
1563 if let Operand::Constant(constant) = op {
1564 let maybe_uneval = match constant.const_ {
1565 Const::Val(..) | Const::Ty(_, _) => None,
1566 Const::Unevaluated(uv, _) => Some(uv),
1567 };
1568
1569 if let Some(uv) = maybe_uneval {
1570 if uv.promoted.is_none() {
1571 let tcx = self.tcx();
1572 let def_id = uv.def;
1573 if tcx.def_kind(def_id) == DefKind::InlineConst {
1574 let def_id = def_id.expect_local();
1575 let predicates = self.prove_closure_bounds(
1576 tcx,
1577 def_id,
1578 uv.args,
1579 location.to_locations(),
1580 );
1581 self.normalize_and_prove_instantiated_predicates(
1582 def_id.to_def_id(),
1583 predicates,
1584 location.to_locations(),
1585 );
1586 }
1587 }
1588 }
1589 }
1590 }
1591
1592 #[instrument(skip(self, body), level = "debug")]
1593 fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
1594 let tcx = self.tcx();
1595 let span = body.source_info(location).span;
1596
1597 match rvalue {
1598 Rvalue::Aggregate(ak, ops) => {
1599 for op in ops {
1600 self.check_operand(op, location);
1601 }
1602 self.check_aggregate_rvalue(body, rvalue, ak, ops, location)
1603 }
1604
1605 Rvalue::Repeat(operand, len) => {
1606 self.check_operand(operand, location);
1607
1608 let array_ty = rvalue.ty(body.local_decls(), tcx);
1609 self.prove_predicate(
1610 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
1611 Locations::Single(location),
1612 ConstraintCategory::Boring,
1613 );
1614
1615 if len.try_to_target_usize(tcx).is_none_or(|len| len > 1) {
1620 match operand {
1621 Operand::Copy(..) | Operand::Constant(..) => {
1622 }
1625 Operand::Move(place) => {
1626 let ty = place.ty(body, tcx).ty;
1628 let trait_ref = ty::TraitRef::new(
1629 tcx,
1630 tcx.require_lang_item(LangItem::Copy, Some(span)),
1631 [ty],
1632 );
1633
1634 self.prove_trait_ref(
1635 trait_ref,
1636 Locations::Single(location),
1637 ConstraintCategory::CopyBound,
1638 );
1639 }
1640 }
1641 }
1642 }
1643
1644 &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
1645 let trait_ref = ty::TraitRef::new(
1646 tcx,
1647 tcx.require_lang_item(LangItem::Sized, Some(span)),
1648 [ty],
1649 );
1650
1651 self.prove_trait_ref(
1652 trait_ref,
1653 location.to_locations(),
1654 ConstraintCategory::SizedBound,
1655 );
1656 }
1657 &Rvalue::NullaryOp(NullOp::ContractChecks, _) => {}
1658 &Rvalue::NullaryOp(NullOp::UbChecks, _) => {}
1659
1660 Rvalue::ShallowInitBox(operand, ty) => {
1661 self.check_operand(operand, location);
1662
1663 let trait_ref = ty::TraitRef::new(
1664 tcx,
1665 tcx.require_lang_item(LangItem::Sized, Some(span)),
1666 [*ty],
1667 );
1668
1669 self.prove_trait_ref(
1670 trait_ref,
1671 location.to_locations(),
1672 ConstraintCategory::SizedBound,
1673 );
1674 }
1675
1676 Rvalue::Cast(cast_kind, op, ty) => {
1677 self.check_operand(op, location);
1678
1679 match *cast_kind {
1680 CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
1681 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1682 let src_ty = op.ty(body, tcx);
1683 let mut src_sig = src_ty.fn_sig(tcx);
1684 if let ty::FnDef(def_id, _) = src_ty.kind()
1685 && let ty::FnPtr(_, target_hdr) = *ty.kind()
1686 && tcx.codegen_fn_attrs(def_id).safe_target_features
1687 && target_hdr.safety.is_safe()
1688 && let Some(safe_sig) = tcx.adjust_target_feature_sig(
1689 *def_id,
1690 src_sig,
1691 body.source.def_id(),
1692 )
1693 {
1694 src_sig = safe_sig;
1695 }
1696
1697 if src_sig.has_bound_regions()
1712 && let ty::FnPtr(target_fn_tys, target_hdr) = *ty.kind()
1713 && let target_sig = target_fn_tys.with(target_hdr)
1714 && let Some(target_sig) = target_sig.no_bound_vars()
1715 {
1716 let src_sig = self.infcx.instantiate_binder_with_fresh_vars(
1717 span,
1718 BoundRegionConversionTime::HigherRankedType,
1719 src_sig,
1720 );
1721 let src_ty = Ty::new_fn_ptr(self.tcx(), ty::Binder::dummy(src_sig));
1722 self.prove_predicate(
1723 ty::ClauseKind::WellFormed(src_ty.into()),
1724 location.to_locations(),
1725 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1726 );
1727
1728 let src_ty = self.normalize(src_ty, location);
1729 if let Err(terr) = self.sub_types(
1730 src_ty,
1731 *ty,
1732 location.to_locations(),
1733 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1734 ) {
1735 span_mirbug!(
1736 self,
1737 rvalue,
1738 "equating {:?} with {:?} yields {:?}",
1739 target_sig,
1740 src_sig,
1741 terr
1742 );
1743 };
1744 }
1745
1746 let src_ty = Ty::new_fn_ptr(tcx, src_sig);
1747 self.prove_predicate(
1752 ty::ClauseKind::WellFormed(src_ty.into()),
1753 location.to_locations(),
1754 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1755 );
1756
1757 let src_ty = self.normalize(src_ty, location);
1763 if let Err(terr) = self.sub_types(
1764 src_ty,
1765 *ty,
1766 location.to_locations(),
1767 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1768 ) {
1769 span_mirbug!(
1770 self,
1771 rvalue,
1772 "equating {:?} with {:?} yields {:?}",
1773 src_ty,
1774 ty,
1775 terr
1776 );
1777 }
1778 }
1779
1780 CastKind::PointerCoercion(
1781 PointerCoercion::ClosureFnPointer(safety),
1782 coercion_source,
1783 ) => {
1784 let sig = match op.ty(body, tcx).kind() {
1785 ty::Closure(_, args) => args.as_closure().sig(),
1786 _ => bug!(),
1787 };
1788 let ty_fn_ptr_from =
1789 Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, safety));
1790
1791 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1792 if let Err(terr) = self.sub_types(
1793 ty_fn_ptr_from,
1794 *ty,
1795 location.to_locations(),
1796 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1797 ) {
1798 span_mirbug!(
1799 self,
1800 rvalue,
1801 "equating {:?} with {:?} yields {:?}",
1802 ty_fn_ptr_from,
1803 ty,
1804 terr
1805 );
1806 }
1807 }
1808
1809 CastKind::PointerCoercion(
1810 PointerCoercion::UnsafeFnPointer,
1811 coercion_source,
1812 ) => {
1813 let fn_sig = op.ty(body, tcx).fn_sig(tcx);
1814
1815 let fn_sig = self.normalize(fn_sig, location);
1821
1822 let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
1823
1824 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1825 if let Err(terr) = self.sub_types(
1826 ty_fn_ptr_from,
1827 *ty,
1828 location.to_locations(),
1829 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1830 ) {
1831 span_mirbug!(
1832 self,
1833 rvalue,
1834 "equating {:?} with {:?} yields {:?}",
1835 ty_fn_ptr_from,
1836 ty,
1837 terr
1838 );
1839 }
1840 }
1841
1842 CastKind::PointerCoercion(PointerCoercion::Unsize, coercion_source) => {
1843 let &ty = ty;
1844 let trait_ref = ty::TraitRef::new(
1845 tcx,
1846 tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
1847 [op.ty(body, tcx), ty],
1848 );
1849
1850 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1851 let unsize_to = fold_regions(tcx, ty, |r, _| {
1852 if let ty::ReVar(_) = r.kind() { tcx.lifetimes.re_erased } else { r }
1853 });
1854 self.prove_trait_ref(
1855 trait_ref,
1856 location.to_locations(),
1857 ConstraintCategory::Cast {
1858 is_implicit_coercion,
1859 unsize_to: Some(unsize_to),
1860 },
1861 );
1862 }
1863
1864 CastKind::PointerCoercion(PointerCoercion::DynStar, coercion_source) => {
1865 let (existential_predicates, region) = match ty.kind() {
1869 Dynamic(predicates, region, ty::DynStar) => (predicates, region),
1870 _ => panic!("Invalid dyn* cast_ty"),
1871 };
1872
1873 let self_ty = op.ty(body, tcx);
1874
1875 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1876 self.prove_predicates(
1877 existential_predicates
1878 .iter()
1879 .map(|predicate| predicate.with_self_ty(tcx, self_ty)),
1880 location.to_locations(),
1881 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1882 );
1883
1884 let outlives_predicate = tcx.mk_predicate(Binder::dummy(
1885 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
1886 ty::OutlivesPredicate(self_ty, *region),
1887 )),
1888 ));
1889 self.prove_predicate(
1890 outlives_predicate,
1891 location.to_locations(),
1892 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1893 );
1894 }
1895
1896 CastKind::PointerCoercion(
1897 PointerCoercion::MutToConstPointer,
1898 coercion_source,
1899 ) => {
1900 let ty::RawPtr(ty_from, hir::Mutability::Mut) = op.ty(body, tcx).kind()
1901 else {
1902 span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
1903 return;
1904 };
1905 let ty::RawPtr(ty_to, hir::Mutability::Not) = ty.kind() else {
1906 span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,);
1907 return;
1908 };
1909 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1910 if let Err(terr) = self.sub_types(
1911 *ty_from,
1912 *ty_to,
1913 location.to_locations(),
1914 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1915 ) {
1916 span_mirbug!(
1917 self,
1918 rvalue,
1919 "relating {:?} with {:?} yields {:?}",
1920 ty_from,
1921 ty_to,
1922 terr
1923 );
1924 }
1925 }
1926
1927 CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
1928 let ty_from = op.ty(body, tcx);
1929
1930 let opt_ty_elem_mut = match ty_from.kind() {
1931 ty::RawPtr(array_ty, array_mut) => match array_ty.kind() {
1932 ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)),
1933 _ => None,
1934 },
1935 _ => None,
1936 };
1937
1938 let Some((ty_elem, ty_mut)) = opt_ty_elem_mut else {
1939 span_mirbug!(
1940 self,
1941 rvalue,
1942 "ArrayToPointer cast from unexpected type {:?}",
1943 ty_from,
1944 );
1945 return;
1946 };
1947
1948 let (ty_to, ty_to_mut) = match ty.kind() {
1949 ty::RawPtr(ty_to, ty_to_mut) => (ty_to, *ty_to_mut),
1950 _ => {
1951 span_mirbug!(
1952 self,
1953 rvalue,
1954 "ArrayToPointer cast to unexpected type {:?}",
1955 ty,
1956 );
1957 return;
1958 }
1959 };
1960
1961 if ty_to_mut.is_mut() && ty_mut.is_not() {
1962 span_mirbug!(
1963 self,
1964 rvalue,
1965 "ArrayToPointer cast from const {:?} to mut {:?}",
1966 ty,
1967 ty_to
1968 );
1969 return;
1970 }
1971
1972 let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
1973 if let Err(terr) = self.sub_types(
1974 *ty_elem,
1975 *ty_to,
1976 location.to_locations(),
1977 ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
1978 ) {
1979 span_mirbug!(
1980 self,
1981 rvalue,
1982 "relating {:?} with {:?} yields {:?}",
1983 ty_elem,
1984 ty_to,
1985 terr
1986 )
1987 }
1988 }
1989
1990 CastKind::PointerExposeProvenance => {
1991 let ty_from = op.ty(body, tcx);
1992 let cast_ty_from = CastTy::from_ty(ty_from);
1993 let cast_ty_to = CastTy::from_ty(*ty);
1994 match (cast_ty_from, cast_ty_to) {
1995 (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
1996 _ => {
1997 span_mirbug!(
1998 self,
1999 rvalue,
2000 "Invalid PointerExposeProvenance cast {:?} -> {:?}",
2001 ty_from,
2002 ty
2003 )
2004 }
2005 }
2006 }
2007
2008 CastKind::PointerWithExposedProvenance => {
2009 let ty_from = op.ty(body, tcx);
2010 let cast_ty_from = CastTy::from_ty(ty_from);
2011 let cast_ty_to = CastTy::from_ty(*ty);
2012 match (cast_ty_from, cast_ty_to) {
2013 (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
2014 _ => {
2015 span_mirbug!(
2016 self,
2017 rvalue,
2018 "Invalid PointerWithExposedProvenance cast {:?} -> {:?}",
2019 ty_from,
2020 ty
2021 )
2022 }
2023 }
2024 }
2025 CastKind::IntToInt => {
2026 let ty_from = op.ty(body, tcx);
2027 let cast_ty_from = CastTy::from_ty(ty_from);
2028 let cast_ty_to = CastTy::from_ty(*ty);
2029 match (cast_ty_from, cast_ty_to) {
2030 (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
2031 _ => {
2032 span_mirbug!(
2033 self,
2034 rvalue,
2035 "Invalid IntToInt cast {:?} -> {:?}",
2036 ty_from,
2037 ty
2038 )
2039 }
2040 }
2041 }
2042 CastKind::IntToFloat => {
2043 let ty_from = op.ty(body, tcx);
2044 let cast_ty_from = CastTy::from_ty(ty_from);
2045 let cast_ty_to = CastTy::from_ty(*ty);
2046 match (cast_ty_from, cast_ty_to) {
2047 (Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
2048 _ => {
2049 span_mirbug!(
2050 self,
2051 rvalue,
2052 "Invalid IntToFloat cast {:?} -> {:?}",
2053 ty_from,
2054 ty
2055 )
2056 }
2057 }
2058 }
2059 CastKind::FloatToInt => {
2060 let ty_from = op.ty(body, tcx);
2061 let cast_ty_from = CastTy::from_ty(ty_from);
2062 let cast_ty_to = CastTy::from_ty(*ty);
2063 match (cast_ty_from, cast_ty_to) {
2064 (Some(CastTy::Float), Some(CastTy::Int(_))) => (),
2065 _ => {
2066 span_mirbug!(
2067 self,
2068 rvalue,
2069 "Invalid FloatToInt cast {:?} -> {:?}",
2070 ty_from,
2071 ty
2072 )
2073 }
2074 }
2075 }
2076 CastKind::FloatToFloat => {
2077 let ty_from = op.ty(body, tcx);
2078 let cast_ty_from = CastTy::from_ty(ty_from);
2079 let cast_ty_to = CastTy::from_ty(*ty);
2080 match (cast_ty_from, cast_ty_to) {
2081 (Some(CastTy::Float), Some(CastTy::Float)) => (),
2082 _ => {
2083 span_mirbug!(
2084 self,
2085 rvalue,
2086 "Invalid FloatToFloat cast {:?} -> {:?}",
2087 ty_from,
2088 ty
2089 )
2090 }
2091 }
2092 }
2093 CastKind::FnPtrToPtr => {
2094 let ty_from = op.ty(body, tcx);
2095 let cast_ty_from = CastTy::from_ty(ty_from);
2096 let cast_ty_to = CastTy::from_ty(*ty);
2097 match (cast_ty_from, cast_ty_to) {
2098 (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
2099 _ => {
2100 span_mirbug!(
2101 self,
2102 rvalue,
2103 "Invalid FnPtrToPtr cast {:?} -> {:?}",
2104 ty_from,
2105 ty
2106 )
2107 }
2108 }
2109 }
2110 CastKind::PtrToPtr => {
2111 let ty_from = op.ty(body, tcx);
2112 let cast_ty_from = CastTy::from_ty(ty_from);
2113 let cast_ty_to = CastTy::from_ty(*ty);
2114 match (cast_ty_from, cast_ty_to) {
2115 (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
2116 let src_tail = self.struct_tail(src.ty, location);
2117 let dst_tail = self.struct_tail(dst.ty, location);
2118
2119 if let ty::Dynamic(src_tty, ..) = src_tail.kind()
2126 && let ty::Dynamic(dst_tty, ..) = dst_tail.kind()
2127 && src_tty.principal().is_some()
2128 && dst_tty.principal().is_some()
2129 {
2130 let src_obj = tcx.mk_ty_from_kind(ty::Dynamic(
2133 tcx.mk_poly_existential_predicates(
2134 &src_tty.without_auto_traits().collect::<Vec<_>>(),
2135 ),
2136 tcx.lifetimes.re_static,
2137 ty::Dyn,
2138 ));
2139 let dst_obj = tcx.mk_ty_from_kind(ty::Dynamic(
2140 tcx.mk_poly_existential_predicates(
2141 &dst_tty.without_auto_traits().collect::<Vec<_>>(),
2142 ),
2143 tcx.lifetimes.re_static,
2144 ty::Dyn,
2145 ));
2146
2147 let src_obj =
2151 freshen_single_trait_object_lifetime(self.infcx, src_obj);
2152 let dst_obj =
2153 freshen_single_trait_object_lifetime(self.infcx, dst_obj);
2154
2155 debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
2156
2157 self.sub_types(
2158 src_obj,
2159 dst_obj,
2160 location.to_locations(),
2161 ConstraintCategory::Cast {
2162 is_implicit_coercion: false,
2163 unsize_to: None,
2164 },
2165 )
2166 .unwrap();
2167 }
2168 }
2169 _ => {
2170 span_mirbug!(
2171 self,
2172 rvalue,
2173 "Invalid PtrToPtr cast {:?} -> {:?}",
2174 ty_from,
2175 ty
2176 )
2177 }
2178 }
2179 }
2180 CastKind::Transmute => {
2181 span_mirbug!(
2182 self,
2183 rvalue,
2184 "Unexpected CastKind::Transmute, which is not permitted in Analysis MIR",
2185 );
2186 }
2187 }
2188 }
2189
2190 Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
2191 self.add_reborrow_constraint(body, location, *region, borrowed_place);
2192 }
2193
2194 Rvalue::BinaryOp(
2195 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
2196 box (left, right),
2197 ) => {
2198 self.check_operand(left, location);
2199 self.check_operand(right, location);
2200
2201 let ty_left = left.ty(body, tcx);
2202 match ty_left.kind() {
2203 ty::RawPtr(_, _) | ty::FnPtr(..) => {
2205 let ty_right = right.ty(body, tcx);
2206 let common_ty = self.infcx.next_ty_var(body.source_info(location).span);
2207 self.sub_types(
2208 ty_left,
2209 common_ty,
2210 location.to_locations(),
2211 ConstraintCategory::CallArgument(None),
2212 )
2213 .unwrap_or_else(|err| {
2214 bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
2215 });
2216 if let Err(terr) = self.sub_types(
2217 ty_right,
2218 common_ty,
2219 location.to_locations(),
2220 ConstraintCategory::CallArgument(None),
2221 ) {
2222 span_mirbug!(
2223 self,
2224 rvalue,
2225 "unexpected comparison types {:?} and {:?} yields {:?}",
2226 ty_left,
2227 ty_right,
2228 terr
2229 )
2230 }
2231 }
2232 ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_)
2235 if ty_left == right.ty(body, tcx) => {}
2236 _ => span_mirbug!(
2239 self,
2240 rvalue,
2241 "unexpected comparison types {:?} and {:?}",
2242 ty_left,
2243 right.ty(body, tcx)
2244 ),
2245 }
2246 }
2247
2248 Rvalue::Use(operand) | Rvalue::UnaryOp(_, operand) => {
2249 self.check_operand(operand, location);
2250 }
2251 Rvalue::CopyForDeref(place) => {
2252 let op = &Operand::Copy(*place);
2253 self.check_operand(op, location);
2254 }
2255
2256 Rvalue::BinaryOp(_, box (left, right)) => {
2257 self.check_operand(left, location);
2258 self.check_operand(right, location);
2259 }
2260
2261 Rvalue::WrapUnsafeBinder(op, ty) => {
2262 self.check_operand(op, location);
2263 let operand_ty = op.ty(self.body, self.tcx());
2264
2265 let ty::UnsafeBinder(binder_ty) = *ty.kind() else {
2266 unreachable!();
2267 };
2268 let expected_ty = self.infcx.instantiate_binder_with_fresh_vars(
2269 self.body().source_info(location).span,
2270 BoundRegionConversionTime::HigherRankedType,
2271 binder_ty.into(),
2272 );
2273 self.sub_types(
2274 operand_ty,
2275 expected_ty,
2276 location.to_locations(),
2277 ConstraintCategory::Boring,
2278 )
2279 .unwrap();
2280 }
2281
2282 Rvalue::RawPtr(..)
2283 | Rvalue::ThreadLocalRef(..)
2284 | Rvalue::Len(..)
2285 | Rvalue::Discriminant(..)
2286 | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
2287 }
2288 }
2289
2290 fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex> {
2294 match rvalue {
2295 Rvalue::Use(_)
2296 | Rvalue::ThreadLocalRef(_)
2297 | Rvalue::Repeat(..)
2298 | Rvalue::Ref(..)
2299 | Rvalue::RawPtr(..)
2300 | Rvalue::Len(..)
2301 | Rvalue::Cast(..)
2302 | Rvalue::ShallowInitBox(..)
2303 | Rvalue::BinaryOp(..)
2304 | Rvalue::NullaryOp(..)
2305 | Rvalue::CopyForDeref(..)
2306 | Rvalue::UnaryOp(..)
2307 | Rvalue::Discriminant(..)
2308 | Rvalue::WrapUnsafeBinder(..) => None,
2309
2310 Rvalue::Aggregate(aggregate, _) => match **aggregate {
2311 AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,
2312 AggregateKind::Array(_) => None,
2313 AggregateKind::Tuple => None,
2314 AggregateKind::Closure(_, _) => None,
2315 AggregateKind::Coroutine(_, _) => None,
2316 AggregateKind::CoroutineClosure(_, _) => None,
2317 AggregateKind::RawPtr(_, _) => None,
2318 },
2319 }
2320 }
2321
2322 fn check_aggregate_rvalue(
2323 &mut self,
2324 body: &Body<'tcx>,
2325 rvalue: &Rvalue<'tcx>,
2326 aggregate_kind: &AggregateKind<'tcx>,
2327 operands: &IndexSlice<FieldIdx, Operand<'tcx>>,
2328 location: Location,
2329 ) {
2330 let tcx = self.tcx();
2331
2332 self.prove_aggregate_predicates(aggregate_kind, location);
2333
2334 if *aggregate_kind == AggregateKind::Tuple {
2335 return;
2337 }
2338
2339 if let AggregateKind::RawPtr(..) = aggregate_kind {
2340 bug!("RawPtr should only be in runtime MIR");
2341 }
2342
2343 for (i, operand) in operands.iter_enumerated() {
2344 let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
2345 Ok(field_ty) => field_ty,
2346 Err(FieldAccessError::OutOfRange { field_count }) => {
2347 span_mirbug!(
2348 self,
2349 rvalue,
2350 "accessed field #{} but variant only has {}",
2351 i.as_u32(),
2352 field_count,
2353 );
2354 continue;
2355 }
2356 };
2357 let operand_ty = operand.ty(body, tcx);
2358 let operand_ty = self.normalize(operand_ty, location);
2359
2360 if let Err(terr) = self.sub_types(
2361 operand_ty,
2362 field_ty,
2363 location.to_locations(),
2364 ConstraintCategory::Boring,
2365 ) {
2366 span_mirbug!(
2367 self,
2368 rvalue,
2369 "{:?} is not a subtype of {:?}: {:?}",
2370 operand_ty,
2371 field_ty,
2372 terr
2373 );
2374 }
2375 }
2376 }
2377
2378 fn add_reborrow_constraint(
2386 &mut self,
2387 body: &Body<'tcx>,
2388 location: Location,
2389 borrow_region: ty::Region<'tcx>,
2390 borrowed_place: &Place<'tcx>,
2391 ) {
2392 let Self { borrow_set, location_table, polonius_facts, constraints, .. } = self;
2394
2395 if let Some(polonius_facts) = polonius_facts {
2401 let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
2402 if let Some(borrow_index) = borrow_set.get_index_of(&location) {
2403 let region_vid = borrow_region.as_var();
2404 polonius_facts.loan_issued_at.push((
2405 region_vid.into(),
2406 borrow_index,
2407 location_table.mid_index(location),
2408 ));
2409 }
2410 }
2411
2412 debug!(
2418 "add_reborrow_constraint({:?}, {:?}, {:?})",
2419 location, borrow_region, borrowed_place
2420 );
2421
2422 let tcx = self.infcx.tcx;
2423 let def = self.body.source.def_id().expect_local();
2424 let upvars = tcx.closure_captures(def);
2425 let field =
2426 path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), body);
2427 let category = if let Some(field) = field {
2428 ConstraintCategory::ClosureUpvar(field)
2429 } else {
2430 ConstraintCategory::Boring
2431 };
2432
2433 for (base, elem) in borrowed_place.as_ref().iter_projections().rev() {
2434 debug!("add_reborrow_constraint - iteration {:?}", elem);
2435
2436 match elem {
2437 ProjectionElem::Deref => {
2438 let base_ty = base.ty(body, tcx).ty;
2439
2440 debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
2441 match base_ty.kind() {
2442 ty::Ref(ref_region, _, mutbl) => {
2443 constraints.outlives_constraints.push(OutlivesConstraint {
2444 sup: ref_region.as_var(),
2445 sub: borrow_region.as_var(),
2446 locations: location.to_locations(),
2447 span: location.to_locations().span(body),
2448 category,
2449 variance_info: ty::VarianceDiagInfo::default(),
2450 from_closure: false,
2451 });
2452
2453 match mutbl {
2454 hir::Mutability::Not => {
2455 break;
2459 }
2460 hir::Mutability::Mut => {
2461 }
2483 }
2484 }
2485 ty::RawPtr(..) => {
2486 break;
2488 }
2489 ty::Adt(def, _) if def.is_box() => {
2490 }
2492 _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
2493 }
2494 }
2495 ProjectionElem::Field(..)
2496 | ProjectionElem::Downcast(..)
2497 | ProjectionElem::OpaqueCast(..)
2498 | ProjectionElem::Index(..)
2499 | ProjectionElem::ConstantIndex { .. }
2500 | ProjectionElem::Subslice { .. }
2501 | ProjectionElem::UnwrapUnsafeBinder(_) => {
2502 }
2504 ProjectionElem::Subtype(_) => {
2505 bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
2506 }
2507 }
2508 }
2509 }
2510
2511 fn prove_aggregate_predicates(
2512 &mut self,
2513 aggregate_kind: &AggregateKind<'tcx>,
2514 location: Location,
2515 ) {
2516 let tcx = self.tcx();
2517
2518 debug!(
2519 "prove_aggregate_predicates(aggregate_kind={:?}, location={:?})",
2520 aggregate_kind, location
2521 );
2522
2523 let (def_id, instantiated_predicates) = match *aggregate_kind {
2524 AggregateKind::Adt(adt_did, _, args, _, _) => {
2525 (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, args))
2526 }
2527
2528 AggregateKind::Closure(def_id, args)
2548 | AggregateKind::CoroutineClosure(def_id, args)
2549 | AggregateKind::Coroutine(def_id, args) => (
2550 def_id,
2551 self.prove_closure_bounds(
2552 tcx,
2553 def_id.expect_local(),
2554 args,
2555 location.to_locations(),
2556 ),
2557 ),
2558
2559 AggregateKind::Array(_) | AggregateKind::Tuple | AggregateKind::RawPtr(..) => {
2560 (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
2561 }
2562 };
2563
2564 self.normalize_and_prove_instantiated_predicates(
2565 def_id,
2566 instantiated_predicates,
2567 location.to_locations(),
2568 );
2569 }
2570
2571 fn prove_closure_bounds(
2572 &mut self,
2573 tcx: TyCtxt<'tcx>,
2574 def_id: LocalDefId,
2575 args: GenericArgsRef<'tcx>,
2576 locations: Locations,
2577 ) -> ty::InstantiatedPredicates<'tcx> {
2578 if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
2579 constraint_conversion::ConstraintConversion::new(
2580 self.infcx,
2581 self.universal_regions,
2582 &self.region_bound_pairs,
2583 self.implicit_region_bound,
2584 self.infcx.param_env,
2585 &self.known_type_outlives_obligations,
2586 locations,
2587 self.body.span, ConstraintCategory::Boring, self.constraints,
2590 )
2591 .apply_closure_requirements(closure_requirements, def_id.to_def_id(), args);
2592 }
2593
2594 let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
2596 let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
2597
2598 let parent_args = match tcx.def_kind(def_id) {
2599 DefKind::Closure => {
2603 &args[..typeck_root_args.len()]
2607 }
2608 DefKind::InlineConst => args.as_inline_const().parent_args(),
2609 other => bug!("unexpected item {:?}", other),
2610 };
2611 let parent_args = tcx.mk_args(parent_args);
2612
2613 assert_eq!(typeck_root_args.len(), parent_args.len());
2614 if let Err(_) = self.eq_args(
2615 typeck_root_args,
2616 parent_args,
2617 locations,
2618 ConstraintCategory::BoringNoLocation,
2619 ) {
2620 span_mirbug!(
2621 self,
2622 def_id,
2623 "could not relate closure to parent {:?} != {:?}",
2624 typeck_root_args,
2625 parent_args
2626 );
2627 }
2628
2629 tcx.predicates_of(def_id).instantiate(tcx, args)
2630 }
2631
2632 #[instrument(skip(self, body), level = "debug")]
2633 fn typeck_mir(&mut self, body: &Body<'tcx>) {
2634 self.last_span = body.span;
2635 debug!(?body.span);
2636
2637 for (local, local_decl) in body.local_decls.iter_enumerated() {
2638 self.check_local(body, local, local_decl);
2639 }
2640
2641 for (block, block_data) in body.basic_blocks.iter_enumerated() {
2642 let mut location = Location { block, statement_index: 0 };
2643 for stmt in &block_data.statements {
2644 if !stmt.source_info.span.is_dummy() {
2645 self.last_span = stmt.source_info.span;
2646 }
2647 self.check_stmt(body, stmt, location);
2648 location.statement_index += 1;
2649 }
2650
2651 self.check_terminator(body, block_data.terminator(), location);
2652 self.check_iscleanup(body, block_data);
2653 }
2654 }
2655}
2656
2657trait NormalizeLocation: fmt::Debug + Copy {
2658 fn to_locations(self) -> Locations;
2659}
2660
2661impl NormalizeLocation for Locations {
2662 fn to_locations(self) -> Locations {
2663 self
2664 }
2665}
2666
2667impl NormalizeLocation for Location {
2668 fn to_locations(self) -> Locations {
2669 Locations::Single(self)
2670 }
2671}
2672
2673#[derive(Debug)]
2677pub(super) struct InstantiateOpaqueType<'tcx> {
2678 pub base_universe: Option<ty::UniverseIndex>,
2679 pub region_constraints: Option<RegionConstraintData<'tcx>>,
2680 pub obligations: PredicateObligations<'tcx>,
2681}
2682
2683impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
2684 type Output = ();
2685 type ErrorInfo = InstantiateOpaqueType<'tcx>;
2691
2692 fn fully_perform(
2693 mut self,
2694 infcx: &InferCtxt<'tcx>,
2695 span: Span,
2696 ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
2697 let (mut output, region_constraints) = scrape_region_constraints(
2698 infcx,
2699 |ocx| {
2700 ocx.register_obligations(self.obligations.clone());
2701 Ok(())
2702 },
2703 "InstantiateOpaqueType",
2704 span,
2705 )?;
2706 self.region_constraints = Some(region_constraints);
2707 output.error_info = Some(self);
2708 Ok(output)
2709 }
2710}
2711
2712fn freshen_single_trait_object_lifetime<'tcx>(
2713 infcx: &BorrowckInferCtxt<'tcx>,
2714 ty: Ty<'tcx>,
2715) -> Ty<'tcx> {
2716 let &ty::Dynamic(tty, _, dyn_kind @ ty::Dyn) = ty.kind() else { bug!("expected trait object") };
2717
2718 let fresh = infcx
2719 .next_region_var(rustc_infer::infer::RegionVariableOrigin::MiscVariable(DUMMY_SP), || {
2720 RegionCtxt::Unknown
2721 });
2722 infcx.tcx.mk_ty_from_kind(ty::Dynamic(tty, fresh, dyn_kind))
2723}