• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![deny(rustc::untranslatable_diagnostic)]
2 #![deny(rustc::diagnostic_outside_of_impl)]
3 //! This pass type-checks the MIR to ensure it is not broken.
4 
5 use std::rc::Rc;
6 use std::{fmt, iter, mem};
7 
8 use either::Either;
9 
10 use rustc_data_structures::frozen::Frozen;
11 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
12 use rustc_errors::ErrorGuaranteed;
13 use rustc_hir as hir;
14 use rustc_hir::def::DefKind;
15 use rustc_hir::def_id::LocalDefId;
16 use rustc_hir::lang_items::LangItem;
17 use rustc_index::{IndexSlice, IndexVec};
18 use rustc_infer::infer::canonical::QueryRegionConstraints;
19 use rustc_infer::infer::outlives::env::RegionBoundPairs;
20 use rustc_infer::infer::region_constraints::RegionConstraintData;
21 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
22 use rustc_infer::infer::{
23     InferCtxt, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
24 };
25 use rustc_middle::mir::tcx::PlaceTy;
26 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
27 use rustc_middle::mir::AssertKind;
28 use rustc_middle::mir::*;
29 use rustc_middle::traits::query::NoSolution;
30 use rustc_middle::traits::ObligationCause;
31 use rustc_middle::ty::adjustment::PointerCoercion;
32 use rustc_middle::ty::cast::CastTy;
33 use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
34 use rustc_middle::ty::visit::TypeVisitableExt;
35 use rustc_middle::ty::{
36     self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
37     OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
38 };
39 use rustc_span::def_id::CRATE_DEF_ID;
40 use rustc_span::symbol::sym;
41 use rustc_span::{Span, DUMMY_SP};
42 use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
43 use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
44 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
45 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
46 
47 use rustc_trait_selection::traits::PredicateObligation;
48 
49 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
50 use rustc_mir_dataflow::move_paths::MoveData;
51 use rustc_mir_dataflow::ResultsCursor;
52 
53 use crate::session_diagnostics::MoveUnsized;
54 use crate::{
55     borrow_set::BorrowSet,
56     constraints::{OutlivesConstraint, OutlivesConstraintSet},
57     diagnostics::UniverseInfo,
58     facts::AllFacts,
59     location::LocationTable,
60     member_constraints::MemberConstraintSet,
61     path_utils,
62     region_infer::values::{
63         LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
64     },
65     region_infer::TypeTest,
66     type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
67     universal_regions::{DefiningTy, UniversalRegions},
68     BorrowckInferCtxt, Upvar,
69 };
70 
71 macro_rules! span_mirbug {
72     ($context:expr, $elem:expr, $($message:tt)*) => ({
73         $crate::type_check::mirbug(
74             $context.tcx(),
75             $context.last_span,
76             format!(
77                 "broken MIR in {:?} ({:?}): {}",
78                 $context.body().source.def_id(),
79                 $elem,
80                 format_args!($($message)*),
81             ),
82         )
83     })
84 }
85 
86 macro_rules! span_mirbug_and_err {
87     ($context:expr, $elem:expr, $($message:tt)*) => ({
88         {
89             span_mirbug!($context, $elem, $($message)*);
90             $context.error()
91         }
92     })
93 }
94 
95 mod canonical;
96 mod constraint_conversion;
97 pub mod free_region_relations;
98 mod input_output;
99 pub(crate) mod liveness;
100 mod relate_tys;
101 
102 /// Type checks the given `mir` in the context of the inference
103 /// context `infcx`. Returns any region constraints that have yet to
104 /// be proven. This result includes liveness constraints that
105 /// ensure that regions appearing in the types of all local variables
106 /// are live at all points where that local variable may later be
107 /// used.
108 ///
109 /// This phase of type-check ought to be infallible -- this is because
110 /// the original, HIR-based type-check succeeded. So if any errors
111 /// occur here, we will get a `bug!` reported.
112 ///
113 /// # Parameters
114 ///
115 /// - `infcx` -- inference context to use
116 /// - `param_env` -- parameter environment to use for trait solving
117 /// - `body` -- MIR body to type-check
118 /// - `promoted` -- map of promoted constants within `body`
119 /// - `universal_regions` -- the universal regions from `body`s function signature
120 /// - `location_table` -- MIR location map of `body`
121 /// - `borrow_set` -- information about borrows occurring in `body`
122 /// - `all_facts` -- when using Polonius, this is the generated set of Polonius facts
123 /// - `flow_inits` -- results of a maybe-init dataflow analysis
124 /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
125 /// - `elements` -- MIR region map
type_check<'mir, 'tcx>( infcx: &BorrowckInferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, promoted: &IndexSlice<Promoted, Body<'tcx>>, universal_regions: &Rc<UniversalRegions<'tcx>>, location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, all_facts: &mut Option<AllFacts>, flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, move_data: &MoveData<'tcx>, elements: &Rc<RegionValueElements>, upvars: &[Upvar<'tcx>], use_polonius: bool, ) -> MirTypeckResults<'tcx>126 pub(crate) fn type_check<'mir, 'tcx>(
127     infcx: &BorrowckInferCtxt<'_, 'tcx>,
128     param_env: ty::ParamEnv<'tcx>,
129     body: &Body<'tcx>,
130     promoted: &IndexSlice<Promoted, Body<'tcx>>,
131     universal_regions: &Rc<UniversalRegions<'tcx>>,
132     location_table: &LocationTable,
133     borrow_set: &BorrowSet<'tcx>,
134     all_facts: &mut Option<AllFacts>,
135     flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
136     move_data: &MoveData<'tcx>,
137     elements: &Rc<RegionValueElements>,
138     upvars: &[Upvar<'tcx>],
139     use_polonius: bool,
140 ) -> MirTypeckResults<'tcx> {
141     let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
142     let mut constraints = MirTypeckRegionConstraints {
143         placeholder_indices: PlaceholderIndices::default(),
144         placeholder_index_to_region: IndexVec::default(),
145         liveness_constraints: LivenessValues::new(elements.clone()),
146         outlives_constraints: OutlivesConstraintSet::default(),
147         member_constraints: MemberConstraintSet::default(),
148         type_tests: Vec::default(),
149         universe_causes: FxIndexMap::default(),
150     };
151 
152     let CreateResult {
153         universal_region_relations,
154         region_bound_pairs,
155         normalized_inputs_and_output,
156     } = free_region_relations::create(
157         infcx,
158         param_env,
159         implicit_region_bound,
160         universal_regions,
161         &mut constraints,
162     );
163 
164     debug!(?normalized_inputs_and_output);
165 
166     for u in ty::UniverseIndex::ROOT..=infcx.universe() {
167         constraints.universe_causes.insert(u, UniverseInfo::other());
168     }
169 
170     let mut borrowck_context = BorrowCheckContext {
171         universal_regions,
172         location_table,
173         borrow_set,
174         all_facts,
175         constraints: &mut constraints,
176         upvars,
177     };
178 
179     let mut checker = TypeChecker::new(
180         infcx,
181         body,
182         param_env,
183         &region_bound_pairs,
184         implicit_region_bound,
185         &mut borrowck_context,
186     );
187 
188     // FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
189     // predefined opaques in the typeck root.
190     if infcx.next_trait_solver() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
191         checker.register_predefined_opaques_in_new_solver();
192     }
193 
194     let mut verifier = TypeVerifier::new(&mut checker, promoted);
195     verifier.visit_body(&body);
196 
197     checker.typeck_mir(body);
198     checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
199     checker.check_signature_annotation(&body);
200 
201     liveness::generate(
202         &mut checker,
203         body,
204         elements,
205         flow_inits,
206         move_data,
207         location_table,
208         use_polonius,
209     );
210 
211     translate_outlives_facts(&mut checker);
212     let opaque_type_values = infcx.take_opaque_types();
213 
214     let opaque_type_values = opaque_type_values
215         .into_iter()
216         .map(|(opaque_type_key, decl)| {
217             let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op(
218                 Locations::All(body.span),
219                 ConstraintCategory::OpaqueType,
220                 CustomTypeOp::new(
221                     |ocx| {
222                         ocx.infcx.register_member_constraints(
223                             param_env,
224                             opaque_type_key,
225                             decl.hidden_type.ty,
226                             decl.hidden_type.span,
227                         );
228                         Ok(())
229                     },
230                     "opaque_type_map",
231                 ),
232             );
233             let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
234             trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
235             if hidden_type.has_non_region_infer() {
236                 let reported = infcx.tcx.sess.delay_span_bug(
237                     decl.hidden_type.span,
238                     format!("could not resolve {:#?}", hidden_type.ty.kind()),
239                 );
240                 hidden_type.ty = Ty::new_error(infcx.tcx, reported);
241             }
242 
243             (opaque_type_key, hidden_type)
244         })
245         .collect();
246 
247     MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
248 }
249 
translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>)250 fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
251     let cx = &mut typeck.borrowck_context;
252     if let Some(facts) = cx.all_facts {
253         let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
254         let location_table = cx.location_table;
255         facts.subset_base.extend(cx.constraints.outlives_constraints.outlives().iter().flat_map(
256             |constraint: &OutlivesConstraint<'_>| {
257                 if let Some(from_location) = constraint.locations.from_location() {
258                     Either::Left(iter::once((
259                         constraint.sup,
260                         constraint.sub,
261                         location_table.mid_index(from_location),
262                     )))
263                 } else {
264                     Either::Right(
265                         location_table
266                             .all_points()
267                             .map(move |location| (constraint.sup, constraint.sub, location)),
268                     )
269                 }
270             },
271         ));
272     }
273 }
274 
275 #[track_caller]
mirbug(tcx: TyCtxt<'_>, span: Span, msg: String)276 fn mirbug(tcx: TyCtxt<'_>, span: Span, msg: String) {
277     // We sometimes see MIR failures (notably predicate failures) due to
278     // the fact that we check rvalue sized predicates here. So use `delay_span_bug`
279     // to avoid reporting bugs in those cases.
280     tcx.sess.diagnostic().delay_span_bug(span, msg);
281 }
282 
283 enum FieldAccessError {
284     OutOfRange { field_count: usize },
285 }
286 
287 /// Verifies that MIR types are sane to not crash further checks.
288 ///
289 /// The sanitize_XYZ methods here take an MIR object and compute its
290 /// type, calling `span_mirbug` and returning an error type if there
291 /// is a problem.
292 struct TypeVerifier<'a, 'b, 'tcx> {
293     cx: &'a mut TypeChecker<'b, 'tcx>,
294     promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
295     last_span: Span,
296 }
297 
298 impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
visit_span(&mut self, span: Span)299     fn visit_span(&mut self, span: Span) {
300         if !span.is_dummy() {
301             self.last_span = span;
302         }
303     }
304 
visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location)305     fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
306         self.sanitize_place(place, location, context);
307     }
308 
visit_constant(&mut self, constant: &Constant<'tcx>, location: Location)309     fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
310         debug!(?constant, ?location, "visit_constant");
311 
312         self.super_constant(constant, location);
313         let ty = self.sanitize_type(constant, constant.literal.ty());
314 
315         self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
316             let live_region_vid =
317                 self.cx.borrowck_context.universal_regions.to_region_vid(live_region);
318             self.cx
319                 .borrowck_context
320                 .constraints
321                 .liveness_constraints
322                 .add_element(live_region_vid, location);
323         });
324 
325         // HACK(compiler-errors): Constants that are gathered into Body.required_consts
326         // have their locations erased...
327         let locations = if location != Location::START {
328             location.to_locations()
329         } else {
330             Locations::All(constant.span)
331         };
332 
333         if let Some(annotation_index) = constant.user_ty {
334             if let Err(terr) = self.cx.relate_type_and_user_type(
335                 constant.literal.ty(),
336                 ty::Variance::Invariant,
337                 &UserTypeProjection { base: annotation_index, projs: vec![] },
338                 locations,
339                 ConstraintCategory::Boring,
340             ) {
341                 let annotation = &self.cx.user_type_annotations[annotation_index];
342                 span_mirbug!(
343                     self,
344                     constant,
345                     "bad constant user type {:?} vs {:?}: {:?}",
346                     annotation,
347                     constant.literal.ty(),
348                     terr,
349                 );
350             }
351         } else {
352             let tcx = self.tcx();
353             let maybe_uneval = match constant.literal {
354                 ConstantKind::Ty(ct) => match ct.kind() {
355                     ty::ConstKind::Unevaluated(_) => {
356                         bug!("should not encounter unevaluated ConstantKind::Ty here, got {:?}", ct)
357                     }
358                     _ => None,
359                 },
360                 ConstantKind::Unevaluated(uv, _) => Some(uv),
361                 _ => None,
362             };
363 
364             if let Some(uv) = maybe_uneval {
365                 if let Some(promoted) = uv.promoted {
366                     let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>,
367                                      promoted: &Body<'tcx>,
368                                      ty,
369                                      san_ty| {
370                         if let Err(terr) =
371                             verifier.cx.eq_types(ty, san_ty, locations, ConstraintCategory::Boring)
372                         {
373                             span_mirbug!(
374                                 verifier,
375                                 promoted,
376                                 "bad promoted type ({:?}: {:?}): {:?}",
377                                 ty,
378                                 san_ty,
379                                 terr
380                             );
381                         };
382                     };
383 
384                     let promoted_body = &self.promoted[promoted];
385                     self.sanitize_promoted(promoted_body, location);
386 
387                     let promoted_ty = promoted_body.return_ty();
388                     check_err(self, promoted_body, ty, promoted_ty);
389                 } else {
390                     self.cx.ascribe_user_type(
391                         constant.literal.ty(),
392                         UserType::TypeOf(
393                             uv.def,
394                             UserSubsts { substs: uv.substs, user_self_ty: None },
395                         ),
396                         locations.span(&self.cx.body),
397                     );
398                 }
399             } else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
400                 let unnormalized_ty = tcx.type_of(static_def_id).subst_identity();
401                 let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
402                 let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;
403 
404                 if let Err(terr) = self.cx.eq_types(
405                     literal_ty,
406                     normalized_ty,
407                     locations,
408                     ConstraintCategory::Boring,
409                 ) {
410                     span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr);
411                 }
412             }
413 
414             if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
415                 // const_trait_impl: use a non-const param env when checking that a FnDef type is well formed.
416                 // this is because the well-formedness of the function does not need to be proved to have `const`
417                 // impls for trait bounds.
418                 let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
419                 let prev = self.cx.param_env;
420                 self.cx.param_env = prev.without_const();
421                 self.cx.normalize_and_prove_instantiated_predicates(
422                     def_id,
423                     instantiated_predicates,
424                     locations,
425                 );
426                 self.cx.param_env = prev;
427             }
428         }
429     }
430 
visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location)431     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
432         self.super_rvalue(rvalue, location);
433         let rval_ty = rvalue.ty(self.body(), self.tcx());
434         self.sanitize_type(rvalue, rval_ty);
435     }
436 
visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>)437     fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
438         self.super_local_decl(local, local_decl);
439         self.sanitize_type(local_decl, local_decl.ty);
440 
441         if let Some(user_ty) = &local_decl.user_ty {
442             for (user_ty, span) in user_ty.projections_and_spans() {
443                 let ty = if !local_decl.is_nonref_binding() {
444                     // If we have a binding of the form `let ref x: T = ..`
445                     // then remove the outermost reference so we can check the
446                     // type annotation for the remaining type.
447                     if let ty::Ref(_, rty, _) = local_decl.ty.kind() {
448                         *rty
449                     } else {
450                         bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty);
451                     }
452                 } else {
453                     local_decl.ty
454                 };
455 
456                 if let Err(terr) = self.cx.relate_type_and_user_type(
457                     ty,
458                     ty::Variance::Invariant,
459                     user_ty,
460                     Locations::All(*span),
461                     ConstraintCategory::TypeAnnotation,
462                 ) {
463                     span_mirbug!(
464                         self,
465                         local,
466                         "bad user type on variable {:?}: {:?} != {:?} ({:?})",
467                         local,
468                         local_decl.ty,
469                         local_decl.user_ty,
470                         terr,
471                     );
472                 }
473             }
474         }
475     }
476 
visit_body(&mut self, body: &Body<'tcx>)477     fn visit_body(&mut self, body: &Body<'tcx>) {
478         self.sanitize_type(&"return type", body.return_ty());
479         // The types of local_decls are checked above which is called in super_body.
480         self.super_body(body);
481     }
482 }
483 
484 impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
new( cx: &'a mut TypeChecker<'b, 'tcx>, promoted: &'b IndexSlice<Promoted, Body<'tcx>>, ) -> Self485     fn new(
486         cx: &'a mut TypeChecker<'b, 'tcx>,
487         promoted: &'b IndexSlice<Promoted, Body<'tcx>>,
488     ) -> Self {
489         TypeVerifier { promoted, last_span: cx.body.span, cx }
490     }
491 
body(&self) -> &Body<'tcx>492     fn body(&self) -> &Body<'tcx> {
493         self.cx.body
494     }
495 
tcx(&self) -> TyCtxt<'tcx>496     fn tcx(&self) -> TyCtxt<'tcx> {
497         self.cx.infcx.tcx
498     }
499 
sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx>500     fn sanitize_type(&mut self, parent: &dyn fmt::Debug, ty: Ty<'tcx>) -> Ty<'tcx> {
501         if ty.has_escaping_bound_vars() || ty.references_error() {
502             span_mirbug_and_err!(self, parent, "bad type {:?}", ty)
503         } else {
504             ty
505         }
506     }
507 
508     /// Checks that the types internal to the `place` match up with
509     /// what would be expected.
sanitize_place( &mut self, place: &Place<'tcx>, location: Location, context: PlaceContext, ) -> PlaceTy<'tcx>510     fn sanitize_place(
511         &mut self,
512         place: &Place<'tcx>,
513         location: Location,
514         context: PlaceContext,
515     ) -> PlaceTy<'tcx> {
516         debug!("sanitize_place: {:?}", place);
517 
518         let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty);
519 
520         for elem in place.projection.iter() {
521             if place_ty.variant_index.is_none() {
522                 if let Err(guar) = place_ty.ty.error_reported() {
523                     return PlaceTy::from_ty(Ty::new_error(self.tcx(), guar));
524                 }
525             }
526             place_ty = self.sanitize_projection(place_ty, elem, place, location, context);
527         }
528 
529         if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
530             let tcx = self.tcx();
531             let trait_ref =
532                 ty::TraitRef::from_lang_item(tcx, LangItem::Copy, self.last_span, [place_ty.ty]);
533 
534             // To have a `Copy` operand, the type `T` of the
535             // value must be `Copy`. Note that we prove that `T: Copy`,
536             // rather than using the `is_copy_modulo_regions`
537             // test. This is important because
538             // `is_copy_modulo_regions` ignores the resulting region
539             // obligations and assumes they pass. This can result in
540             // bounds from `Copy` impls being unsoundly ignored (e.g.,
541             // #29149). Note that we decide to use `Copy` before knowing
542             // whether the bounds fully apply: in effect, the rule is
543             // that if a value of some type could implement `Copy`, then
544             // it must.
545             self.cx.prove_trait_ref(
546                 trait_ref,
547                 location.to_locations(),
548                 ConstraintCategory::CopyBound,
549             );
550         }
551 
552         place_ty
553     }
554 
sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location)555     fn sanitize_promoted(&mut self, promoted_body: &'b Body<'tcx>, location: Location) {
556         // Determine the constraints from the promoted MIR by running the type
557         // checker on the promoted MIR, then transfer the constraints back to
558         // the main MIR, changing the locations to the provided location.
559 
560         let parent_body = mem::replace(&mut self.cx.body, promoted_body);
561 
562         // Use new sets of constraints and closure bounds so that we can
563         // modify their locations.
564         let all_facts = &mut None;
565         let mut constraints = Default::default();
566         let mut liveness_constraints =
567             LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
568         // Don't try to add borrow_region facts for the promoted MIR
569 
570         let mut swap_constraints = |this: &mut Self| {
571             mem::swap(this.cx.borrowck_context.all_facts, all_facts);
572             mem::swap(
573                 &mut this.cx.borrowck_context.constraints.outlives_constraints,
574                 &mut constraints,
575             );
576             mem::swap(
577                 &mut this.cx.borrowck_context.constraints.liveness_constraints,
578                 &mut liveness_constraints,
579             );
580         };
581 
582         swap_constraints(self);
583 
584         self.visit_body(&promoted_body);
585 
586         self.cx.typeck_mir(promoted_body);
587 
588         self.cx.body = parent_body;
589         // Merge the outlives constraints back in, at the given location.
590         swap_constraints(self);
591 
592         let locations = location.to_locations();
593         for constraint in constraints.outlives().iter() {
594             let mut constraint = *constraint;
595             constraint.locations = locations;
596             if let ConstraintCategory::Return(_)
597             | ConstraintCategory::UseAsConst
598             | ConstraintCategory::UseAsStatic = constraint.category
599             {
600                 // "Returning" from a promoted is an assignment to a
601                 // temporary from the user's point of view.
602                 constraint.category = ConstraintCategory::Boring;
603             }
604             self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
605         }
606         for region in liveness_constraints.rows() {
607             // If the region is live at at least one location in the promoted MIR,
608             // then add a liveness constraint to the main MIR for this region
609             // at the location provided as an argument to this method
610             if liveness_constraints.get_elements(region).next().is_some() {
611                 self.cx
612                     .borrowck_context
613                     .constraints
614                     .liveness_constraints
615                     .add_element(region, location);
616             }
617         }
618     }
619 
620     #[instrument(skip(self), level = "debug")]
sanitize_projection( &mut self, base: PlaceTy<'tcx>, pi: PlaceElem<'tcx>, place: &Place<'tcx>, location: Location, context: PlaceContext, ) -> PlaceTy<'tcx>621     fn sanitize_projection(
622         &mut self,
623         base: PlaceTy<'tcx>,
624         pi: PlaceElem<'tcx>,
625         place: &Place<'tcx>,
626         location: Location,
627         context: PlaceContext,
628     ) -> PlaceTy<'tcx> {
629         debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place);
630         let tcx = self.tcx();
631         let base_ty = base.ty;
632         match pi {
633             ProjectionElem::Deref => {
634                 let deref_ty = base_ty.builtin_deref(true);
635                 PlaceTy::from_ty(deref_ty.map(|t| t.ty).unwrap_or_else(|| {
636                     span_mirbug_and_err!(self, place, "deref of non-pointer {:?}", base_ty)
637                 }))
638             }
639             ProjectionElem::Index(i) => {
640                 let index_ty = Place::from(i).ty(self.body(), tcx).ty;
641                 if index_ty != tcx.types.usize {
642                     PlaceTy::from_ty(span_mirbug_and_err!(self, i, "index by non-usize {:?}", i))
643                 } else {
644                     PlaceTy::from_ty(base_ty.builtin_index().unwrap_or_else(|| {
645                         span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
646                     }))
647                 }
648             }
649             ProjectionElem::ConstantIndex { .. } => {
650                 // consider verifying in-bounds
651                 PlaceTy::from_ty(base_ty.builtin_index().unwrap_or_else(|| {
652                     span_mirbug_and_err!(self, place, "index of non-array {:?}", base_ty)
653                 }))
654             }
655             ProjectionElem::Subslice { from, to, from_end } => {
656                 PlaceTy::from_ty(match base_ty.kind() {
657                     ty::Array(inner, _) => {
658                         assert!(!from_end, "array subslices should not use from_end");
659                         Ty::new_array(tcx, *inner, to - from)
660                     }
661                     ty::Slice(..) => {
662                         assert!(from_end, "slice subslices should use from_end");
663                         base_ty
664                     }
665                     _ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty),
666                 })
667             }
668             ProjectionElem::Downcast(maybe_name, index) => match base_ty.kind() {
669                 ty::Adt(adt_def, _substs) if adt_def.is_enum() => {
670                     if index.as_usize() >= adt_def.variants().len() {
671                         PlaceTy::from_ty(span_mirbug_and_err!(
672                             self,
673                             place,
674                             "cast to variant #{:?} but enum only has {:?}",
675                             index,
676                             adt_def.variants().len()
677                         ))
678                     } else {
679                         PlaceTy { ty: base_ty, variant_index: Some(index) }
680                     }
681                 }
682                 // We do not need to handle generators here, because this runs
683                 // before the generator transform stage.
684                 _ => {
685                     let ty = if let Some(name) = maybe_name {
686                         span_mirbug_and_err!(
687                             self,
688                             place,
689                             "can't downcast {:?} as {:?}",
690                             base_ty,
691                             name
692                         )
693                     } else {
694                         span_mirbug_and_err!(self, place, "can't downcast {:?}", base_ty)
695                     };
696                     PlaceTy::from_ty(ty)
697                 }
698             },
699             ProjectionElem::Field(field, fty) => {
700                 let fty = self.sanitize_type(place, fty);
701                 let fty = self.cx.normalize(fty, location);
702                 match self.field_ty(place, base, field, location) {
703                     Ok(ty) => {
704                         let ty = self.cx.normalize(ty, location);
705                         debug!(?fty, ?ty);
706 
707                         if let Err(terr) = self.cx.relate_types(
708                             ty,
709                             self.get_ambient_variance(context),
710                             fty,
711                             location.to_locations(),
712                             ConstraintCategory::Boring,
713                         ) {
714                             span_mirbug!(
715                                 self,
716                                 place,
717                                 "bad field access ({:?}: {:?}): {:?}",
718                                 ty,
719                                 fty,
720                                 terr
721                             );
722                         }
723                     }
724                     Err(FieldAccessError::OutOfRange { field_count }) => span_mirbug!(
725                         self,
726                         place,
727                         "accessed field #{} but variant only has {}",
728                         field.index(),
729                         field_count
730                     ),
731                 }
732                 PlaceTy::from_ty(fty)
733             }
734             ProjectionElem::OpaqueCast(ty) => {
735                 let ty = self.sanitize_type(place, ty);
736                 let ty = self.cx.normalize(ty, location);
737                 self.cx
738                     .relate_types(
739                         ty,
740                         self.get_ambient_variance(context),
741                         base.ty,
742                         location.to_locations(),
743                         ConstraintCategory::TypeAnnotation,
744                     )
745                     .unwrap();
746                 PlaceTy::from_ty(ty)
747             }
748         }
749     }
750 
error(&mut self) -> Ty<'tcx>751     fn error(&mut self) -> Ty<'tcx> {
752         Ty::new_misc_error(self.tcx())
753     }
754 
get_ambient_variance(&self, context: PlaceContext) -> ty::Variance755     fn get_ambient_variance(&self, context: PlaceContext) -> ty::Variance {
756         use rustc_middle::mir::visit::NonMutatingUseContext::*;
757         use rustc_middle::mir::visit::NonUseContext::*;
758 
759         match context {
760             PlaceContext::MutatingUse(_) => ty::Invariant,
761             PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
762             PlaceContext::NonMutatingUse(
763                 Inspect | Copy | Move | PlaceMention | SharedBorrow | ShallowBorrow | AddressOf
764                 | Projection,
765             ) => ty::Covariant,
766             PlaceContext::NonUse(AscribeUserTy(variance)) => variance,
767         }
768     }
769 
field_ty( &mut self, parent: &dyn fmt::Debug, base_ty: PlaceTy<'tcx>, field: FieldIdx, location: Location, ) -> Result<Ty<'tcx>, FieldAccessError>770     fn field_ty(
771         &mut self,
772         parent: &dyn fmt::Debug,
773         base_ty: PlaceTy<'tcx>,
774         field: FieldIdx,
775         location: Location,
776     ) -> Result<Ty<'tcx>, FieldAccessError> {
777         let tcx = self.tcx();
778 
779         let (variant, substs) = match base_ty {
780             PlaceTy { ty, variant_index: Some(variant_index) } => match *ty.kind() {
781                 ty::Adt(adt_def, substs) => (adt_def.variant(variant_index), substs),
782                 ty::Generator(def_id, substs, _) => {
783                     let mut variants = substs.as_generator().state_tys(def_id, tcx);
784                     let Some(mut variant) = variants.nth(variant_index.into()) else {
785                         bug!(
786                             "variant_index of generator out of range: {:?}/{:?}",
787                             variant_index,
788                             substs.as_generator().state_tys(def_id, tcx).count()
789                         );
790                     };
791                     return match variant.nth(field.index()) {
792                         Some(ty) => Ok(ty),
793                         None => Err(FieldAccessError::OutOfRange { field_count: variant.count() }),
794                     };
795                 }
796                 _ => bug!("can't have downcast of non-adt non-generator type"),
797             },
798             PlaceTy { ty, variant_index: None } => match *ty.kind() {
799                 ty::Adt(adt_def, substs) if !adt_def.is_enum() => {
800                     (adt_def.variant(FIRST_VARIANT), substs)
801                 }
802                 ty::Closure(_, substs) => {
803                     return match substs
804                         .as_closure()
805                         .tupled_upvars_ty()
806                         .tuple_fields()
807                         .get(field.index())
808                     {
809                         Some(&ty) => Ok(ty),
810                         None => Err(FieldAccessError::OutOfRange {
811                             field_count: substs.as_closure().upvar_tys().count(),
812                         }),
813                     };
814                 }
815                 ty::Generator(_, substs, _) => {
816                     // Only prefix fields (upvars and current state) are
817                     // accessible without a variant index.
818                     return match substs.as_generator().prefix_tys().nth(field.index()) {
819                         Some(ty) => Ok(ty),
820                         None => Err(FieldAccessError::OutOfRange {
821                             field_count: substs.as_generator().prefix_tys().count(),
822                         }),
823                     };
824                 }
825                 ty::Tuple(tys) => {
826                     return match tys.get(field.index()) {
827                         Some(&ty) => Ok(ty),
828                         None => Err(FieldAccessError::OutOfRange { field_count: tys.len() }),
829                     };
830                 }
831                 _ => {
832                     return Ok(span_mirbug_and_err!(
833                         self,
834                         parent,
835                         "can't project out of {:?}",
836                         base_ty
837                     ));
838                 }
839             },
840         };
841 
842         if let Some(field) = variant.fields.get(field) {
843             Ok(self.cx.normalize(field.ty(tcx, substs), location))
844         } else {
845             Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
846         }
847     }
848 }
849 
850 /// The MIR type checker. Visits the MIR and enforces all the
851 /// constraints needed for it to be valid and well-typed. Along the
852 /// way, it accrues region constraints -- these can later be used by
853 /// NLL region checking.
854 struct TypeChecker<'a, 'tcx> {
855     infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
856     param_env: ty::ParamEnv<'tcx>,
857     last_span: Span,
858     body: &'a Body<'tcx>,
859     /// User type annotations are shared between the main MIR and the MIR of
860     /// all of the promoted items.
861     user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
862     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
863     implicit_region_bound: ty::Region<'tcx>,
864     reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
865     borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
866 }
867 
868 struct BorrowCheckContext<'a, 'tcx> {
869     pub(crate) universal_regions: &'a UniversalRegions<'tcx>,
870     location_table: &'a LocationTable,
871     all_facts: &'a mut Option<AllFacts>,
872     borrow_set: &'a BorrowSet<'tcx>,
873     pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
874     upvars: &'a [Upvar<'tcx>],
875 }
876 
877 pub(crate) struct MirTypeckResults<'tcx> {
878     pub(crate) constraints: MirTypeckRegionConstraints<'tcx>,
879     pub(crate) universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
880     pub(crate) opaque_type_values: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
881 }
882 
883 /// A collection of region constraints that must be satisfied for the
884 /// program to be considered well-typed.
885 pub(crate) struct MirTypeckRegionConstraints<'tcx> {
886     /// Maps from a `ty::Placeholder` to the corresponding
887     /// `PlaceholderIndex` bit that we will use for it.
888     ///
889     /// To keep everything in sync, do not insert this set
890     /// directly. Instead, use the `placeholder_region` helper.
891     pub(crate) placeholder_indices: PlaceholderIndices,
892 
893     /// Each time we add a placeholder to `placeholder_indices`, we
894     /// also create a corresponding "representative" region vid for
895     /// that wraps it. This vector tracks those. This way, when we
896     /// convert the same `ty::RePlaceholder(p)` twice, we can map to
897     /// the same underlying `RegionVid`.
898     pub(crate) placeholder_index_to_region: IndexVec<PlaceholderIndex, ty::Region<'tcx>>,
899 
900     /// In general, the type-checker is not responsible for enforcing
901     /// liveness constraints; this job falls to the region inferencer,
902     /// which performs a liveness analysis. However, in some limited
903     /// cases, the MIR type-checker creates temporary regions that do
904     /// not otherwise appear in the MIR -- in particular, the
905     /// late-bound regions that it instantiates at call-sites -- and
906     /// hence it must report on their liveness constraints.
907     pub(crate) liveness_constraints: LivenessValues<RegionVid>,
908 
909     pub(crate) outlives_constraints: OutlivesConstraintSet<'tcx>,
910 
911     pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
912 
913     pub(crate) universe_causes: FxIndexMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
914 
915     pub(crate) type_tests: Vec<TypeTest<'tcx>>,
916 }
917 
918 impl<'tcx> MirTypeckRegionConstraints<'tcx> {
919     /// Creates a `Region` for a given `PlaceholderRegion`, or returns the
920     /// region that corresponds to a previously created one.
placeholder_region( &mut self, infcx: &InferCtxt<'tcx>, placeholder: ty::PlaceholderRegion, ) -> ty::Region<'tcx>921     fn placeholder_region(
922         &mut self,
923         infcx: &InferCtxt<'tcx>,
924         placeholder: ty::PlaceholderRegion,
925     ) -> ty::Region<'tcx> {
926         let placeholder_index = self.placeholder_indices.insert(placeholder);
927         match self.placeholder_index_to_region.get(placeholder_index) {
928             Some(&v) => v,
929             None => {
930                 let origin = NllRegionVariableOrigin::Placeholder(placeholder);
931                 let region = infcx.next_nll_region_var_in_universe(origin, placeholder.universe);
932                 self.placeholder_index_to_region.push(region);
933                 region
934             }
935         }
936     }
937 }
938 
939 /// The `Locations` type summarizes *where* region constraints are
940 /// required to hold. Normally, this is at a particular point which
941 /// created the obligation, but for constraints that the user gave, we
942 /// want the constraint to hold at all points.
943 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
944 pub enum Locations {
945     /// Indicates that a type constraint should always be true. This
946     /// is particularly important in the new borrowck analysis for
947     /// things like the type of the return slot. Consider this
948     /// example:
949     ///
950     /// ```compile_fail,E0515
951     /// fn foo<'a>(x: &'a u32) -> &'a u32 {
952     ///     let y = 22;
953     ///     return &y; // error
954     /// }
955     /// ```
956     ///
957     /// Here, we wind up with the signature from the return type being
958     /// something like `&'1 u32` where `'1` is a universal region. But
959     /// the type of the return slot `_0` is something like `&'2 u32`
960     /// where `'2` is an existential region variable. The type checker
961     /// requires that `&'2 u32 = &'1 u32` -- but at what point? In the
962     /// older NLL analysis, we required this only at the entry point
963     /// to the function. By the nature of the constraints, this wound
964     /// up propagating to all points reachable from start (because
965     /// `'1` -- as a universal region -- is live everywhere). In the
966     /// newer analysis, though, this doesn't work: `_0` is considered
967     /// dead at the start (it has no usable value) and hence this type
968     /// equality is basically a no-op. Then, later on, when we do `_0
969     /// = &'3 y`, that region `'3` never winds up related to the
970     /// universal region `'1` and hence no error occurs. Therefore, we
971     /// use Locations::All instead, which ensures that the `'1` and
972     /// `'2` are equal everything. We also use this for other
973     /// user-given type annotations; e.g., if the user wrote `let mut
974     /// x: &'static u32 = ...`, we would ensure that all values
975     /// assigned to `x` are of `'static` lifetime.
976     ///
977     /// The span points to the place the constraint arose. For example,
978     /// it points to the type in a user-given type annotation. If
979     /// there's no sensible span then it's DUMMY_SP.
980     All(Span),
981 
982     /// An outlives constraint that only has to hold at a single location,
983     /// usually it represents a point where references flow from one spot to
984     /// another (e.g., `x = y`)
985     Single(Location),
986 }
987 
988 impl Locations {
from_location(&self) -> Option<Location>989     pub fn from_location(&self) -> Option<Location> {
990         match self {
991             Locations::All(_) => None,
992             Locations::Single(from_location) => Some(*from_location),
993         }
994     }
995 
996     /// Gets a span representing the location.
span(&self, body: &Body<'_>) -> Span997     pub fn span(&self, body: &Body<'_>) -> Span {
998         match self {
999             Locations::All(span) => *span,
1000             Locations::Single(l) => body.source_info(*l).span,
1001         }
1002     }
1003 }
1004 
1005 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
new( infcx: &'a BorrowckInferCtxt<'a, 'tcx>, body: &'a Body<'tcx>, param_env: ty::ParamEnv<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, ) -> Self1006     fn new(
1007         infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
1008         body: &'a Body<'tcx>,
1009         param_env: ty::ParamEnv<'tcx>,
1010         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
1011         implicit_region_bound: ty::Region<'tcx>,
1012         borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
1013     ) -> Self {
1014         let mut checker = Self {
1015             infcx,
1016             last_span: DUMMY_SP,
1017             body,
1018             user_type_annotations: &body.user_type_annotations,
1019             param_env,
1020             region_bound_pairs,
1021             implicit_region_bound,
1022             borrowck_context,
1023             reported_errors: Default::default(),
1024         };
1025         checker.check_user_type_annotations();
1026         checker
1027     }
1028 
register_predefined_opaques_in_new_solver(&mut self)1029     pub(super) fn register_predefined_opaques_in_new_solver(&mut self) {
1030         // OK to use the identity substitutions for each opaque type key, since
1031         // we remap opaques from HIR typeck back to their definition params.
1032         let opaques: Vec<_> = self
1033             .infcx
1034             .tcx
1035             .typeck(self.body.source.def_id().expect_local())
1036             .concrete_opaque_types
1037             .iter()
1038             .map(|(k, v)| (*k, *v))
1039             .collect();
1040 
1041         let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
1042             self.infcx.next_nll_region_var_in_universe(
1043                 NllRegionVariableOrigin::Existential { from_forall: false },
1044                 ty::UniverseIndex::ROOT,
1045             )
1046         });
1047 
1048         let param_env = self.param_env;
1049         let result = self.fully_perform_op(
1050             Locations::All(self.body.span),
1051             ConstraintCategory::OpaqueType,
1052             CustomTypeOp::new(
1053                 |ocx| {
1054                     let mut obligations = Vec::new();
1055                     for (opaque_type_key, hidden_ty) in renumbered_opaques {
1056                         let cause = ObligationCause::dummy();
1057                         ocx.infcx.insert_hidden_type(
1058                             opaque_type_key,
1059                             &cause,
1060                             param_env,
1061                             hidden_ty.ty,
1062                             true,
1063                             &mut obligations,
1064                         )?;
1065 
1066                         ocx.infcx.add_item_bounds_for_hidden_type(
1067                             opaque_type_key.def_id.to_def_id(),
1068                             opaque_type_key.substs,
1069                             cause,
1070                             param_env,
1071                             hidden_ty.ty,
1072                             &mut obligations,
1073                         );
1074                     }
1075 
1076                     ocx.register_obligations(obligations);
1077                     Ok(())
1078                 },
1079                 "register pre-defined opaques",
1080             ),
1081         );
1082 
1083         if result.is_err() {
1084             self.infcx.tcx.sess.delay_span_bug(
1085                 self.body.span,
1086                 "failed re-defining predefined opaques in mir typeck",
1087             );
1088         }
1089     }
1090 
body(&self) -> &Body<'tcx>1091     fn body(&self) -> &Body<'tcx> {
1092         self.body
1093     }
1094 
unsized_feature_enabled(&self) -> bool1095     fn unsized_feature_enabled(&self) -> bool {
1096         let features = self.tcx().features();
1097         features.unsized_locals || features.unsized_fn_params
1098     }
1099 
1100     /// Equate the inferred type and the annotated type for user type annotations
1101     #[instrument(skip(self), level = "debug")]
check_user_type_annotations(&mut self)1102     fn check_user_type_annotations(&mut self) {
1103         debug!(?self.user_type_annotations);
1104         for user_annotation in self.user_type_annotations {
1105             let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation;
1106             let annotation = self.instantiate_canonical_with_fresh_inference_vars(span, user_ty);
1107             self.ascribe_user_type(inferred_ty, annotation, span);
1108         }
1109     }
1110 
1111     #[instrument(skip(self, data), level = "debug")]
push_region_constraints( &mut self, locations: Locations, category: ConstraintCategory<'tcx>, data: &QueryRegionConstraints<'tcx>, )1112     fn push_region_constraints(
1113         &mut self,
1114         locations: Locations,
1115         category: ConstraintCategory<'tcx>,
1116         data: &QueryRegionConstraints<'tcx>,
1117     ) {
1118         debug!("constraints generated: {:#?}", data);
1119 
1120         constraint_conversion::ConstraintConversion::new(
1121             self.infcx,
1122             self.borrowck_context.universal_regions,
1123             self.region_bound_pairs,
1124             self.implicit_region_bound,
1125             self.param_env,
1126             locations,
1127             locations.span(self.body),
1128             category,
1129             &mut self.borrowck_context.constraints,
1130         )
1131         .convert_all(data);
1132     }
1133 
1134     /// Try to relate `sub <: sup`
sub_types( &mut self, sub: Ty<'tcx>, sup: Ty<'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, ) -> Result<(), NoSolution>1135     fn sub_types(
1136         &mut self,
1137         sub: Ty<'tcx>,
1138         sup: Ty<'tcx>,
1139         locations: Locations,
1140         category: ConstraintCategory<'tcx>,
1141     ) -> Result<(), NoSolution> {
1142         // Use this order of parameters because the sup type is usually the
1143         // "expected" type in diagnostics.
1144         self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
1145     }
1146 
1147     #[instrument(skip(self, category), level = "debug")]
eq_types( &mut self, expected: Ty<'tcx>, found: Ty<'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, ) -> Result<(), NoSolution>1148     fn eq_types(
1149         &mut self,
1150         expected: Ty<'tcx>,
1151         found: Ty<'tcx>,
1152         locations: Locations,
1153         category: ConstraintCategory<'tcx>,
1154     ) -> Result<(), NoSolution> {
1155         self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
1156     }
1157 
1158     #[instrument(skip(self), level = "debug")]
relate_type_and_user_type( &mut self, a: Ty<'tcx>, v: ty::Variance, user_ty: &UserTypeProjection, locations: Locations, category: ConstraintCategory<'tcx>, ) -> Result<(), NoSolution>1159     fn relate_type_and_user_type(
1160         &mut self,
1161         a: Ty<'tcx>,
1162         v: ty::Variance,
1163         user_ty: &UserTypeProjection,
1164         locations: Locations,
1165         category: ConstraintCategory<'tcx>,
1166     ) -> Result<(), NoSolution> {
1167         let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
1168         trace!(?annotated_type);
1169         let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
1170 
1171         let tcx = self.infcx.tcx;
1172 
1173         for proj in &user_ty.projs {
1174             if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() {
1175                 // There is nothing that we can compare here if we go through an opaque type.
1176                 // We're always in its defining scope as we can otherwise not project through
1177                 // it, so we're constraining it anyways.
1178                 return Ok(());
1179             }
1180             let projected_ty = curr_projected_ty.projection_ty_core(
1181                 tcx,
1182                 self.param_env,
1183                 proj,
1184                 |this, field, ()| {
1185                     let ty = this.field_ty(tcx, field);
1186                     self.normalize(ty, locations)
1187                 },
1188                 |_, _| unreachable!(),
1189             );
1190             curr_projected_ty = projected_ty;
1191         }
1192         trace!(?curr_projected_ty);
1193 
1194         let ty = curr_projected_ty.ty;
1195         self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?;
1196 
1197         Ok(())
1198     }
1199 
tcx(&self) -> TyCtxt<'tcx>1200     fn tcx(&self) -> TyCtxt<'tcx> {
1201         self.infcx.tcx
1202     }
1203 
1204     #[instrument(skip(self, body, location), level = "debug")]
check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location)1205     fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
1206         let tcx = self.tcx();
1207         debug!("stmt kind: {:?}", stmt.kind);
1208         match &stmt.kind {
1209             StatementKind::Assign(box (place, rv)) => {
1210                 // Assignments to temporaries are not "interesting";
1211                 // they are not caused by the user, but rather artifacts
1212                 // of lowering. Assignments to other sorts of places *are* interesting
1213                 // though.
1214                 let category = match place.as_local() {
1215                     Some(RETURN_PLACE) => {
1216                         let defining_ty = &self.borrowck_context.universal_regions.defining_ty;
1217                         if defining_ty.is_const() {
1218                             if tcx.is_static(defining_ty.def_id()) {
1219                                 ConstraintCategory::UseAsStatic
1220                             } else {
1221                                 ConstraintCategory::UseAsConst
1222                             }
1223                         } else {
1224                             ConstraintCategory::Return(ReturnConstraint::Normal)
1225                         }
1226                     }
1227                     Some(l)
1228                         if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) =>
1229                     {
1230                         ConstraintCategory::Usage
1231                     }
1232                     Some(l) if !body.local_decls[l].is_user_variable() => {
1233                         ConstraintCategory::Boring
1234                     }
1235                     _ => ConstraintCategory::Assignment,
1236                 };
1237                 debug!(
1238                     "assignment category: {:?} {:?}",
1239                     category,
1240                     place.as_local().map(|l| &body.local_decls[l])
1241                 );
1242 
1243                 let place_ty = place.ty(body, tcx).ty;
1244                 debug!(?place_ty);
1245                 let place_ty = self.normalize(place_ty, location);
1246                 debug!("place_ty normalized: {:?}", place_ty);
1247                 let rv_ty = rv.ty(body, tcx);
1248                 debug!(?rv_ty);
1249                 let rv_ty = self.normalize(rv_ty, location);
1250                 debug!("normalized rv_ty: {:?}", rv_ty);
1251                 if let Err(terr) =
1252                     self.sub_types(rv_ty, place_ty, location.to_locations(), category)
1253                 {
1254                     span_mirbug!(
1255                         self,
1256                         stmt,
1257                         "bad assignment ({:?} = {:?}): {:?}",
1258                         place_ty,
1259                         rv_ty,
1260                         terr
1261                     );
1262                 }
1263 
1264                 if let Some(annotation_index) = self.rvalue_user_ty(rv) {
1265                     if let Err(terr) = self.relate_type_and_user_type(
1266                         rv_ty,
1267                         ty::Variance::Invariant,
1268                         &UserTypeProjection { base: annotation_index, projs: vec![] },
1269                         location.to_locations(),
1270                         ConstraintCategory::Boring,
1271                     ) {
1272                         let annotation = &self.user_type_annotations[annotation_index];
1273                         span_mirbug!(
1274                             self,
1275                             stmt,
1276                             "bad user type on rvalue ({:?} = {:?}): {:?}",
1277                             annotation,
1278                             rv_ty,
1279                             terr
1280                         );
1281                     }
1282                 }
1283 
1284                 self.check_rvalue(body, rv, location);
1285                 if !self.unsized_feature_enabled() {
1286                     let trait_ref = ty::TraitRef::from_lang_item(
1287                         tcx,
1288                         LangItem::Sized,
1289                         self.last_span,
1290                         [place_ty],
1291                     );
1292                     self.prove_trait_ref(
1293                         trait_ref,
1294                         location.to_locations(),
1295                         ConstraintCategory::SizedBound,
1296                     );
1297                 }
1298             }
1299             StatementKind::AscribeUserType(box (place, projection), variance) => {
1300                 let place_ty = place.ty(body, tcx).ty;
1301                 if let Err(terr) = self.relate_type_and_user_type(
1302                     place_ty,
1303                     *variance,
1304                     projection,
1305                     Locations::All(stmt.source_info.span),
1306                     ConstraintCategory::TypeAnnotation,
1307                 ) {
1308                     let annotation = &self.user_type_annotations[projection.base];
1309                     span_mirbug!(
1310                         self,
1311                         stmt,
1312                         "bad type assert ({:?} <: {:?} with projections {:?}): {:?}",
1313                         place_ty,
1314                         annotation,
1315                         projection.projs,
1316                         terr
1317                     );
1318                 }
1319             }
1320             StatementKind::Intrinsic(box kind) => match kind {
1321                 NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
1322                 NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
1323                     stmt.source_info.span,
1324                     "Unexpected NonDivergingIntrinsic::CopyNonOverlapping, should only appear after lowering_intrinsics",
1325                 ),
1326             },
1327             StatementKind::FakeRead(..)
1328             | StatementKind::StorageLive(..)
1329             | StatementKind::StorageDead(..)
1330             | StatementKind::Retag { .. }
1331             | StatementKind::Coverage(..)
1332             | StatementKind::ConstEvalCounter
1333             | StatementKind::PlaceMention(..)
1334             | StatementKind::Nop => {}
1335             StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
1336                 bug!("Statement not allowed in this MIR phase")
1337             }
1338         }
1339     }
1340 
1341     #[instrument(skip(self, body, term_location), level = "debug")]
check_terminator( &mut self, body: &Body<'tcx>, term: &Terminator<'tcx>, term_location: Location, )1342     fn check_terminator(
1343         &mut self,
1344         body: &Body<'tcx>,
1345         term: &Terminator<'tcx>,
1346         term_location: Location,
1347     ) {
1348         let tcx = self.tcx();
1349         debug!("terminator kind: {:?}", term.kind);
1350         match &term.kind {
1351             TerminatorKind::Goto { .. }
1352             | TerminatorKind::Resume
1353             | TerminatorKind::Terminate
1354             | TerminatorKind::Return
1355             | TerminatorKind::GeneratorDrop
1356             | TerminatorKind::Unreachable
1357             | TerminatorKind::Drop { .. }
1358             | TerminatorKind::FalseEdge { .. }
1359             | TerminatorKind::FalseUnwind { .. }
1360             | TerminatorKind::InlineAsm { .. } => {
1361                 // no checks needed for these
1362             }
1363 
1364             TerminatorKind::SwitchInt { discr, .. } => {
1365                 self.check_operand(discr, term_location);
1366 
1367                 let switch_ty = discr.ty(body, tcx);
1368                 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
1369                     span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
1370                 }
1371                 // FIXME: check the values
1372             }
1373             TerminatorKind::Call { func, args, destination, call_source, target, .. } => {
1374                 self.check_operand(func, term_location);
1375                 for arg in args {
1376                     self.check_operand(arg, term_location);
1377                 }
1378 
1379                 let func_ty = func.ty(body, tcx);
1380                 debug!("func_ty.kind: {:?}", func_ty.kind());
1381 
1382                 let sig = match func_ty.kind() {
1383                     ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx),
1384                     _ => {
1385                         span_mirbug!(self, term, "call to non-function {:?}", func_ty);
1386                         return;
1387                     }
1388                 };
1389                 let (sig, map) = tcx.replace_late_bound_regions(sig, |br| {
1390                     use crate::renumber::{BoundRegionInfo, RegionCtxt};
1391 
1392                     let region_ctxt_fn = || {
1393                         let reg_info = match br.kind {
1394                             ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
1395                             ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(sym::anon),
1396                             ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
1397                             ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env),
1398                         };
1399 
1400                         RegionCtxt::LateBound(reg_info)
1401                     };
1402 
1403                     self.infcx.next_region_var(
1404                         LateBoundRegion(
1405                             term.source_info.span,
1406                             br.kind,
1407                             LateBoundRegionConversionTime::FnCall,
1408                         ),
1409                         region_ctxt_fn,
1410                     )
1411                 });
1412                 debug!(?sig);
1413                 // IMPORTANT: We have to prove well formed for the function signature before
1414                 // we normalize it, as otherwise types like `<&'a &'b () as Trait>::Assoc`
1415                 // get normalized away, causing us to ignore the `'b: 'a` bound used by the function.
1416                 //
1417                 // Normalization results in a well formed type if the input is well formed, so we
1418                 // don't have to check it twice.
1419                 //
1420                 // See #91068 for an example.
1421                 self.prove_predicates(
1422                     sig.inputs_and_output.iter().map(|ty| {
1423                         ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
1424                             ty.into(),
1425                         )))
1426                     }),
1427                     term_location.to_locations(),
1428                     ConstraintCategory::Boring,
1429                 );
1430                 let sig = self.normalize(sig, term_location);
1431                 self.check_call_dest(body, term, &sig, *destination, *target, term_location);
1432 
1433                 // The ordinary liveness rules will ensure that all
1434                 // regions in the type of the callee are live here. We
1435                 // then further constrain the late-bound regions that
1436                 // were instantiated at the call site to be live as
1437                 // well. The resulting is that all the input (and
1438                 // output) types in the signature must be live, since
1439                 // all the inputs that fed into it were live.
1440                 for &late_bound_region in map.values() {
1441                     let region_vid =
1442                         self.borrowck_context.universal_regions.to_region_vid(late_bound_region);
1443                     self.borrowck_context
1444                         .constraints
1445                         .liveness_constraints
1446                         .add_element(region_vid, term_location);
1447                 }
1448 
1449                 self.check_call_inputs(body, term, &sig, args, term_location, *call_source);
1450             }
1451             TerminatorKind::Assert { cond, msg, .. } => {
1452                 self.check_operand(cond, term_location);
1453 
1454                 let cond_ty = cond.ty(body, tcx);
1455                 if cond_ty != tcx.types.bool {
1456                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
1457                 }
1458 
1459                 if let AssertKind::BoundsCheck { len, index } = &**msg {
1460                     if len.ty(body, tcx) != tcx.types.usize {
1461                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
1462                     }
1463                     if index.ty(body, tcx) != tcx.types.usize {
1464                         span_mirbug!(self, index, "bounds-check index non-usize {:?}", index)
1465                     }
1466                 }
1467             }
1468             TerminatorKind::Yield { value, .. } => {
1469                 self.check_operand(value, term_location);
1470 
1471                 let value_ty = value.ty(body, tcx);
1472                 match body.yield_ty() {
1473                     None => span_mirbug!(self, term, "yield in non-generator"),
1474                     Some(ty) => {
1475                         if let Err(terr) = self.sub_types(
1476                             value_ty,
1477                             ty,
1478                             term_location.to_locations(),
1479                             ConstraintCategory::Yield,
1480                         ) {
1481                             span_mirbug!(
1482                                 self,
1483                                 term,
1484                                 "type of yield value is {:?}, but the yield type is {:?}: {:?}",
1485                                 value_ty,
1486                                 ty,
1487                                 terr
1488                             );
1489                         }
1490                     }
1491                 }
1492             }
1493         }
1494     }
1495 
check_call_dest( &mut self, body: &Body<'tcx>, term: &Terminator<'tcx>, sig: &ty::FnSig<'tcx>, destination: Place<'tcx>, target: Option<BasicBlock>, term_location: Location, )1496     fn check_call_dest(
1497         &mut self,
1498         body: &Body<'tcx>,
1499         term: &Terminator<'tcx>,
1500         sig: &ty::FnSig<'tcx>,
1501         destination: Place<'tcx>,
1502         target: Option<BasicBlock>,
1503         term_location: Location,
1504     ) {
1505         let tcx = self.tcx();
1506         match target {
1507             Some(_) => {
1508                 let dest_ty = destination.ty(body, tcx).ty;
1509                 let dest_ty = self.normalize(dest_ty, term_location);
1510                 let category = match destination.as_local() {
1511                     Some(RETURN_PLACE) => {
1512                         if let BorrowCheckContext {
1513                             universal_regions:
1514                                 UniversalRegions {
1515                                     defining_ty:
1516                                         DefiningTy::Const(def_id, _)
1517                                         | DefiningTy::InlineConst(def_id, _),
1518                                     ..
1519                                 },
1520                             ..
1521                         } = self.borrowck_context
1522                         {
1523                             if tcx.is_static(*def_id) {
1524                                 ConstraintCategory::UseAsStatic
1525                             } else {
1526                                 ConstraintCategory::UseAsConst
1527                             }
1528                         } else {
1529                             ConstraintCategory::Return(ReturnConstraint::Normal)
1530                         }
1531                     }
1532                     Some(l) if !body.local_decls[l].is_user_variable() => {
1533                         ConstraintCategory::Boring
1534                     }
1535                     _ => ConstraintCategory::Assignment,
1536                 };
1537 
1538                 let locations = term_location.to_locations();
1539 
1540                 if let Err(terr) = self.sub_types(sig.output(), dest_ty, locations, category) {
1541                     span_mirbug!(
1542                         self,
1543                         term,
1544                         "call dest mismatch ({:?} <- {:?}): {:?}",
1545                         dest_ty,
1546                         sig.output(),
1547                         terr
1548                     );
1549                 }
1550 
1551                 // When `unsized_fn_params` and `unsized_locals` are both not enabled,
1552                 // this check is done at `check_local`.
1553                 if self.unsized_feature_enabled() {
1554                     let span = term.source_info.span;
1555                     self.ensure_place_sized(dest_ty, span);
1556                 }
1557             }
1558             None => {
1559                 // The signature in this call can reference region variables,
1560                 // so erase them before calling a query.
1561                 let output_ty = self.tcx().erase_regions(sig.output());
1562                 if !output_ty.is_privately_uninhabited(self.tcx(), self.param_env) {
1563                     span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
1564                 }
1565             }
1566         }
1567     }
1568 
check_call_inputs( &mut self, body: &Body<'tcx>, term: &Terminator<'tcx>, sig: &ty::FnSig<'tcx>, args: &[Operand<'tcx>], term_location: Location, call_source: CallSource, )1569     fn check_call_inputs(
1570         &mut self,
1571         body: &Body<'tcx>,
1572         term: &Terminator<'tcx>,
1573         sig: &ty::FnSig<'tcx>,
1574         args: &[Operand<'tcx>],
1575         term_location: Location,
1576         call_source: CallSource,
1577     ) {
1578         debug!("check_call_inputs({:?}, {:?})", sig, args);
1579         if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.c_variadic) {
1580             span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
1581         }
1582 
1583         let func_ty = if let TerminatorKind::Call { func, .. } = &term.kind {
1584             Some(func.ty(body, self.infcx.tcx))
1585         } else {
1586             None
1587         };
1588         debug!(?func_ty);
1589 
1590         for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
1591             let op_arg_ty = op_arg.ty(body, self.tcx());
1592 
1593             let op_arg_ty = self.normalize(op_arg_ty, term_location);
1594             let category = if call_source.from_hir_call() {
1595                 ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
1596             } else {
1597                 ConstraintCategory::Boring
1598             };
1599             if let Err(terr) =
1600                 self.sub_types(op_arg_ty, *fn_arg, term_location.to_locations(), category)
1601             {
1602                 span_mirbug!(
1603                     self,
1604                     term,
1605                     "bad arg #{:?} ({:?} <- {:?}): {:?}",
1606                     n,
1607                     fn_arg,
1608                     op_arg_ty,
1609                     terr
1610                 );
1611             }
1612         }
1613     }
1614 
check_iscleanup(&mut self, body: &Body<'tcx>, block_data: &BasicBlockData<'tcx>)1615     fn check_iscleanup(&mut self, body: &Body<'tcx>, block_data: &BasicBlockData<'tcx>) {
1616         let is_cleanup = block_data.is_cleanup;
1617         self.last_span = block_data.terminator().source_info.span;
1618         match block_data.terminator().kind {
1619             TerminatorKind::Goto { target } => {
1620                 self.assert_iscleanup(body, block_data, target, is_cleanup)
1621             }
1622             TerminatorKind::SwitchInt { ref targets, .. } => {
1623                 for target in targets.all_targets() {
1624                     self.assert_iscleanup(body, block_data, *target, is_cleanup);
1625                 }
1626             }
1627             TerminatorKind::Resume => {
1628                 if !is_cleanup {
1629                     span_mirbug!(self, block_data, "resume on non-cleanup block!")
1630                 }
1631             }
1632             TerminatorKind::Terminate => {
1633                 if !is_cleanup {
1634                     span_mirbug!(self, block_data, "abort on non-cleanup block!")
1635                 }
1636             }
1637             TerminatorKind::Return => {
1638                 if is_cleanup {
1639                     span_mirbug!(self, block_data, "return on cleanup block")
1640                 }
1641             }
1642             TerminatorKind::GeneratorDrop { .. } => {
1643                 if is_cleanup {
1644                     span_mirbug!(self, block_data, "generator_drop in cleanup block")
1645                 }
1646             }
1647             TerminatorKind::Yield { resume, drop, .. } => {
1648                 if is_cleanup {
1649                     span_mirbug!(self, block_data, "yield in cleanup block")
1650                 }
1651                 self.assert_iscleanup(body, block_data, resume, is_cleanup);
1652                 if let Some(drop) = drop {
1653                     self.assert_iscleanup(body, block_data, drop, is_cleanup);
1654                 }
1655             }
1656             TerminatorKind::Unreachable => {}
1657             TerminatorKind::Drop { target, unwind, .. }
1658             | TerminatorKind::Assert { target, unwind, .. } => {
1659                 self.assert_iscleanup(body, block_data, target, is_cleanup);
1660                 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1661             }
1662             TerminatorKind::Call { ref target, unwind, .. } => {
1663                 if let &Some(target) = target {
1664                     self.assert_iscleanup(body, block_data, target, is_cleanup);
1665                 }
1666                 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1667             }
1668             TerminatorKind::FalseEdge { real_target, imaginary_target } => {
1669                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
1670                 self.assert_iscleanup(body, block_data, imaginary_target, is_cleanup);
1671             }
1672             TerminatorKind::FalseUnwind { real_target, unwind } => {
1673                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
1674                 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1675             }
1676             TerminatorKind::InlineAsm { destination, unwind, .. } => {
1677                 if let Some(target) = destination {
1678                     self.assert_iscleanup(body, block_data, target, is_cleanup);
1679                 }
1680                 self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
1681             }
1682         }
1683     }
1684 
assert_iscleanup( &mut self, body: &Body<'tcx>, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool, )1685     fn assert_iscleanup(
1686         &mut self,
1687         body: &Body<'tcx>,
1688         ctxt: &dyn fmt::Debug,
1689         bb: BasicBlock,
1690         iscleanuppad: bool,
1691     ) {
1692         if body[bb].is_cleanup != iscleanuppad {
1693             span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
1694         }
1695     }
1696 
assert_iscleanup_unwind( &mut self, body: &Body<'tcx>, ctxt: &dyn fmt::Debug, unwind: UnwindAction, is_cleanup: bool, )1697     fn assert_iscleanup_unwind(
1698         &mut self,
1699         body: &Body<'tcx>,
1700         ctxt: &dyn fmt::Debug,
1701         unwind: UnwindAction,
1702         is_cleanup: bool,
1703     ) {
1704         match unwind {
1705             UnwindAction::Cleanup(unwind) => {
1706                 if is_cleanup {
1707                     span_mirbug!(self, ctxt, "unwind on cleanup block")
1708                 }
1709                 self.assert_iscleanup(body, ctxt, unwind, true);
1710             }
1711             UnwindAction::Continue => {
1712                 if is_cleanup {
1713                     span_mirbug!(self, ctxt, "unwind on cleanup block")
1714                 }
1715             }
1716             UnwindAction::Unreachable | UnwindAction::Terminate => (),
1717         }
1718     }
1719 
check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>)1720     fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
1721         match body.local_kind(local) {
1722             LocalKind::ReturnPointer | LocalKind::Arg => {
1723                 // return values of normal functions are required to be
1724                 // sized by typeck, but return values of ADT constructors are
1725                 // not because we don't include a `Self: Sized` bounds on them.
1726                 //
1727                 // Unbound parts of arguments were never required to be Sized
1728                 // - maybe we should make that a warning.
1729                 return;
1730             }
1731             LocalKind::Temp => {}
1732         }
1733 
1734         // When `unsized_fn_params` or `unsized_locals` is enabled, only function calls
1735         // and nullary ops are checked in `check_call_dest`.
1736         if !self.unsized_feature_enabled() {
1737             let span = local_decl.source_info.span;
1738             let ty = local_decl.ty;
1739             self.ensure_place_sized(ty, span);
1740         }
1741     }
1742 
ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span)1743     fn ensure_place_sized(&mut self, ty: Ty<'tcx>, span: Span) {
1744         let tcx = self.tcx();
1745 
1746         // Erase the regions from `ty` to get a global type. The
1747         // `Sized` bound in no way depends on precise regions, so this
1748         // shouldn't affect `is_sized`.
1749         let erased_ty = tcx.erase_regions(ty);
1750         if !erased_ty.is_sized(tcx, self.param_env) {
1751             // in current MIR construction, all non-control-flow rvalue
1752             // expressions evaluate through `as_temp` or `into` a return
1753             // slot or local, so to find all unsized rvalues it is enough
1754             // to check all temps, return slots and locals.
1755             if self.reported_errors.replace((ty, span)).is_none() {
1756                 // While this is located in `nll::typeck` this error is not
1757                 // an NLL error, it's a required check to prevent creation
1758                 // of unsized rvalues in a call expression.
1759                 self.tcx().sess.emit_err(MoveUnsized { ty, span });
1760             }
1761         }
1762     }
1763 
aggregate_field_ty( &mut self, ak: &AggregateKind<'tcx>, field_index: FieldIdx, location: Location, ) -> Result<Ty<'tcx>, FieldAccessError>1764     fn aggregate_field_ty(
1765         &mut self,
1766         ak: &AggregateKind<'tcx>,
1767         field_index: FieldIdx,
1768         location: Location,
1769     ) -> Result<Ty<'tcx>, FieldAccessError> {
1770         let tcx = self.tcx();
1771 
1772         match *ak {
1773             AggregateKind::Adt(adt_did, variant_index, substs, _, active_field_index) => {
1774                 let def = tcx.adt_def(adt_did);
1775                 let variant = &def.variant(variant_index);
1776                 let adj_field_index = active_field_index.unwrap_or(field_index);
1777                 if let Some(field) = variant.fields.get(adj_field_index) {
1778                     Ok(self.normalize(field.ty(tcx, substs), location))
1779                 } else {
1780                     Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() })
1781                 }
1782             }
1783             AggregateKind::Closure(_, substs) => {
1784                 match substs.as_closure().upvar_tys().nth(field_index.as_usize()) {
1785                     Some(ty) => Ok(ty),
1786                     None => Err(FieldAccessError::OutOfRange {
1787                         field_count: substs.as_closure().upvar_tys().count(),
1788                     }),
1789                 }
1790             }
1791             AggregateKind::Generator(_, substs, _) => {
1792                 // It doesn't make sense to look at a field beyond the prefix;
1793                 // these require a variant index, and are not initialized in
1794                 // aggregate rvalues.
1795                 match substs.as_generator().prefix_tys().nth(field_index.as_usize()) {
1796                     Some(ty) => Ok(ty),
1797                     None => Err(FieldAccessError::OutOfRange {
1798                         field_count: substs.as_generator().prefix_tys().count(),
1799                     }),
1800                 }
1801             }
1802             AggregateKind::Array(ty) => Ok(ty),
1803             AggregateKind::Tuple => {
1804                 unreachable!("This should have been covered in check_rvalues");
1805             }
1806         }
1807     }
1808 
check_operand(&mut self, op: &Operand<'tcx>, location: Location)1809     fn check_operand(&mut self, op: &Operand<'tcx>, location: Location) {
1810         debug!(?op, ?location, "check_operand");
1811 
1812         if let Operand::Constant(constant) = op {
1813             let maybe_uneval = match constant.literal {
1814                 ConstantKind::Val(..) | ConstantKind::Ty(_) => None,
1815                 ConstantKind::Unevaluated(uv, _) => Some(uv),
1816             };
1817 
1818             if let Some(uv) = maybe_uneval {
1819                 if uv.promoted.is_none() {
1820                     let tcx = self.tcx();
1821                     let def_id = uv.def;
1822                     if tcx.def_kind(def_id) == DefKind::InlineConst {
1823                         let def_id = def_id.expect_local();
1824                         let predicates =
1825                             self.prove_closure_bounds(tcx, def_id, uv.substs, location);
1826                         self.normalize_and_prove_instantiated_predicates(
1827                             def_id.to_def_id(),
1828                             predicates,
1829                             location.to_locations(),
1830                         );
1831                     }
1832                 }
1833             }
1834         }
1835     }
1836 
1837     #[instrument(skip(self, body), level = "debug")]
check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location)1838     fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
1839         let tcx = self.tcx();
1840         let span = body.source_info(location).span;
1841 
1842         match rvalue {
1843             Rvalue::Aggregate(ak, ops) => {
1844                 for op in ops {
1845                     self.check_operand(op, location);
1846                 }
1847                 self.check_aggregate_rvalue(&body, rvalue, ak, ops, location)
1848             }
1849 
1850             Rvalue::Repeat(operand, len) => {
1851                 self.check_operand(operand, location);
1852 
1853                 let array_ty = rvalue.ty(body.local_decls(), tcx);
1854                 self.prove_predicate(
1855                     ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
1856                     Locations::Single(location),
1857                     ConstraintCategory::Boring,
1858                 );
1859 
1860                 // If the length cannot be evaluated we must assume that the length can be larger
1861                 // than 1.
1862                 // If the length is larger than 1, the repeat expression will need to copy the
1863                 // element, so we require the `Copy` trait.
1864                 if len.try_eval_target_usize(tcx, self.param_env).map_or(true, |len| len > 1) {
1865                     match operand {
1866                         Operand::Copy(..) | Operand::Constant(..) => {
1867                             // These are always okay: direct use of a const, or a value that can evidently be copied.
1868                         }
1869                         Operand::Move(place) => {
1870                             // Make sure that repeated elements implement `Copy`.
1871                             let ty = place.ty(body, tcx).ty;
1872                             let trait_ref =
1873                                 ty::TraitRef::from_lang_item(tcx, LangItem::Copy, span, [ty]);
1874 
1875                             self.prove_trait_ref(
1876                                 trait_ref,
1877                                 Locations::Single(location),
1878                                 ConstraintCategory::CopyBound,
1879                             );
1880                         }
1881                     }
1882                 }
1883             }
1884 
1885             &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
1886                 let trait_ref = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, span, [ty]);
1887 
1888                 self.prove_trait_ref(
1889                     trait_ref,
1890                     location.to_locations(),
1891                     ConstraintCategory::SizedBound,
1892                 );
1893             }
1894 
1895             Rvalue::ShallowInitBox(operand, ty) => {
1896                 self.check_operand(operand, location);
1897 
1898                 let trait_ref = ty::TraitRef::from_lang_item(tcx, LangItem::Sized, span, [*ty]);
1899 
1900                 self.prove_trait_ref(
1901                     trait_ref,
1902                     location.to_locations(),
1903                     ConstraintCategory::SizedBound,
1904                 );
1905             }
1906 
1907             Rvalue::Cast(cast_kind, op, ty) => {
1908                 self.check_operand(op, location);
1909 
1910                 match cast_kind {
1911                     CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer) => {
1912                         let fn_sig = op.ty(body, tcx).fn_sig(tcx);
1913 
1914                         // The type that we see in the fcx is like
1915                         // `foo::<'a, 'b>`, where `foo` is the path to a
1916                         // function definition. When we extract the
1917                         // signature, it comes from the `fn_sig` query,
1918                         // and hence may contain unnormalized results.
1919                         let fn_sig = self.normalize(fn_sig, location);
1920 
1921                         let ty_fn_ptr_from = Ty::new_fn_ptr(tcx, fn_sig);
1922 
1923                         if let Err(terr) = self.eq_types(
1924                             *ty,
1925                             ty_fn_ptr_from,
1926                             location.to_locations(),
1927                             ConstraintCategory::Cast,
1928                         ) {
1929                             span_mirbug!(
1930                                 self,
1931                                 rvalue,
1932                                 "equating {:?} with {:?} yields {:?}",
1933                                 ty_fn_ptr_from,
1934                                 ty,
1935                                 terr
1936                             );
1937                         }
1938                     }
1939 
1940                     CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(unsafety)) => {
1941                         let sig = match op.ty(body, tcx).kind() {
1942                             ty::Closure(_, substs) => substs.as_closure().sig(),
1943                             _ => bug!(),
1944                         };
1945                         let ty_fn_ptr_from =
1946                             Ty::new_fn_ptr(tcx, tcx.signature_unclosure(sig, *unsafety));
1947 
1948                         if let Err(terr) = self.eq_types(
1949                             *ty,
1950                             ty_fn_ptr_from,
1951                             location.to_locations(),
1952                             ConstraintCategory::Cast,
1953                         ) {
1954                             span_mirbug!(
1955                                 self,
1956                                 rvalue,
1957                                 "equating {:?} with {:?} yields {:?}",
1958                                 ty_fn_ptr_from,
1959                                 ty,
1960                                 terr
1961                             );
1962                         }
1963                     }
1964 
1965                     CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer) => {
1966                         let fn_sig = op.ty(body, tcx).fn_sig(tcx);
1967 
1968                         // The type that we see in the fcx is like
1969                         // `foo::<'a, 'b>`, where `foo` is the path to a
1970                         // function definition. When we extract the
1971                         // signature, it comes from the `fn_sig` query,
1972                         // and hence may contain unnormalized results.
1973                         let fn_sig = self.normalize(fn_sig, location);
1974 
1975                         let ty_fn_ptr_from = tcx.safe_to_unsafe_fn_ty(fn_sig);
1976 
1977                         if let Err(terr) = self.eq_types(
1978                             *ty,
1979                             ty_fn_ptr_from,
1980                             location.to_locations(),
1981                             ConstraintCategory::Cast,
1982                         ) {
1983                             span_mirbug!(
1984                                 self,
1985                                 rvalue,
1986                                 "equating {:?} with {:?} yields {:?}",
1987                                 ty_fn_ptr_from,
1988                                 ty,
1989                                 terr
1990                             );
1991                         }
1992                     }
1993 
1994                     CastKind::PointerCoercion(PointerCoercion::Unsize) => {
1995                         let &ty = ty;
1996                         let trait_ref = ty::TraitRef::from_lang_item(
1997                             tcx,
1998                             LangItem::CoerceUnsized,
1999                             span,
2000                             [op.ty(body, tcx), ty],
2001                         );
2002 
2003                         self.prove_trait_ref(
2004                             trait_ref,
2005                             location.to_locations(),
2006                             ConstraintCategory::Cast,
2007                         );
2008                     }
2009 
2010                     CastKind::DynStar => {
2011                         // get the constraints from the target type (`dyn* Clone`)
2012                         //
2013                         // apply them to prove that the source type `Foo` implements `Clone` etc
2014                         let (existential_predicates, region) = match ty.kind() {
2015                             Dynamic(predicates, region, ty::DynStar) => (predicates, region),
2016                             _ => panic!("Invalid dyn* cast_ty"),
2017                         };
2018 
2019                         let self_ty = op.ty(body, tcx);
2020 
2021                         self.prove_predicates(
2022                             existential_predicates
2023                                 .iter()
2024                                 .map(|predicate| predicate.with_self_ty(tcx, self_ty)),
2025                             location.to_locations(),
2026                             ConstraintCategory::Cast,
2027                         );
2028 
2029                         let outlives_predicate = tcx.mk_predicate(Binder::dummy(
2030                             ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
2031                                 ty::OutlivesPredicate(self_ty, *region),
2032                             )),
2033                         ));
2034                         self.prove_predicate(
2035                             outlives_predicate,
2036                             location.to_locations(),
2037                             ConstraintCategory::Cast,
2038                         );
2039                     }
2040 
2041                     CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => {
2042                         let ty::RawPtr(ty::TypeAndMut {
2043                             ty: ty_from,
2044                             mutbl: hir::Mutability::Mut,
2045                         }) = op.ty(body, tcx).kind() else {
2046                             span_mirbug!(
2047                                 self,
2048                                 rvalue,
2049                                 "unexpected base type for cast {:?}",
2050                                 ty,
2051                             );
2052                             return;
2053                         };
2054                         let ty::RawPtr(ty::TypeAndMut {
2055                             ty: ty_to,
2056                             mutbl: hir::Mutability::Not,
2057                         }) = ty.kind() else {
2058                             span_mirbug!(
2059                                 self,
2060                                 rvalue,
2061                                 "unexpected target type for cast {:?}",
2062                                 ty,
2063                             );
2064                             return;
2065                         };
2066                         if let Err(terr) = self.sub_types(
2067                             *ty_from,
2068                             *ty_to,
2069                             location.to_locations(),
2070                             ConstraintCategory::Cast,
2071                         ) {
2072                             span_mirbug!(
2073                                 self,
2074                                 rvalue,
2075                                 "relating {:?} with {:?} yields {:?}",
2076                                 ty_from,
2077                                 ty_to,
2078                                 terr
2079                             );
2080                         }
2081                     }
2082 
2083                     CastKind::PointerCoercion(PointerCoercion::ArrayToPointer) => {
2084                         let ty_from = op.ty(body, tcx);
2085 
2086                         let opt_ty_elem_mut = match ty_from.kind() {
2087                             ty::RawPtr(ty::TypeAndMut { mutbl: array_mut, ty: array_ty }) => {
2088                                 match array_ty.kind() {
2089                                     ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)),
2090                                     _ => None,
2091                                 }
2092                             }
2093                             _ => None,
2094                         };
2095 
2096                         let Some((ty_elem, ty_mut)) = opt_ty_elem_mut else {
2097                             span_mirbug!(
2098                                 self,
2099                                 rvalue,
2100                                 "ArrayToPointer cast from unexpected type {:?}",
2101                                 ty_from,
2102                             );
2103                             return;
2104                         };
2105 
2106                         let (ty_to, ty_to_mut) = match ty.kind() {
2107                             ty::RawPtr(ty::TypeAndMut { mutbl: ty_to_mut, ty: ty_to }) => {
2108                                 (ty_to, *ty_to_mut)
2109                             }
2110                             _ => {
2111                                 span_mirbug!(
2112                                     self,
2113                                     rvalue,
2114                                     "ArrayToPointer cast to unexpected type {:?}",
2115                                     ty,
2116                                 );
2117                                 return;
2118                             }
2119                         };
2120 
2121                         if ty_to_mut.is_mut() && ty_mut.is_not() {
2122                             span_mirbug!(
2123                                 self,
2124                                 rvalue,
2125                                 "ArrayToPointer cast from const {:?} to mut {:?}",
2126                                 ty,
2127                                 ty_to
2128                             );
2129                             return;
2130                         }
2131 
2132                         if let Err(terr) = self.sub_types(
2133                             *ty_elem,
2134                             *ty_to,
2135                             location.to_locations(),
2136                             ConstraintCategory::Cast,
2137                         ) {
2138                             span_mirbug!(
2139                                 self,
2140                                 rvalue,
2141                                 "relating {:?} with {:?} yields {:?}",
2142                                 ty_elem,
2143                                 ty_to,
2144                                 terr
2145                             )
2146                         }
2147                     }
2148 
2149                     CastKind::PointerExposeAddress => {
2150                         let ty_from = op.ty(body, tcx);
2151                         let cast_ty_from = CastTy::from_ty(ty_from);
2152                         let cast_ty_to = CastTy::from_ty(*ty);
2153                         match (cast_ty_from, cast_ty_to) {
2154                             (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
2155                             _ => {
2156                                 span_mirbug!(
2157                                     self,
2158                                     rvalue,
2159                                     "Invalid PointerExposeAddress cast {:?} -> {:?}",
2160                                     ty_from,
2161                                     ty
2162                                 )
2163                             }
2164                         }
2165                     }
2166 
2167                     CastKind::PointerFromExposedAddress => {
2168                         let ty_from = op.ty(body, tcx);
2169                         let cast_ty_from = CastTy::from_ty(ty_from);
2170                         let cast_ty_to = CastTy::from_ty(*ty);
2171                         match (cast_ty_from, cast_ty_to) {
2172                             (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
2173                             _ => {
2174                                 span_mirbug!(
2175                                     self,
2176                                     rvalue,
2177                                     "Invalid PointerFromExposedAddress cast {:?} -> {:?}",
2178                                     ty_from,
2179                                     ty
2180                                 )
2181                             }
2182                         }
2183                     }
2184                     CastKind::IntToInt => {
2185                         let ty_from = op.ty(body, tcx);
2186                         let cast_ty_from = CastTy::from_ty(ty_from);
2187                         let cast_ty_to = CastTy::from_ty(*ty);
2188                         match (cast_ty_from, cast_ty_to) {
2189                             (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
2190                             _ => {
2191                                 span_mirbug!(
2192                                     self,
2193                                     rvalue,
2194                                     "Invalid IntToInt cast {:?} -> {:?}",
2195                                     ty_from,
2196                                     ty
2197                                 )
2198                             }
2199                         }
2200                     }
2201                     CastKind::IntToFloat => {
2202                         let ty_from = op.ty(body, tcx);
2203                         let cast_ty_from = CastTy::from_ty(ty_from);
2204                         let cast_ty_to = CastTy::from_ty(*ty);
2205                         match (cast_ty_from, cast_ty_to) {
2206                             (Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
2207                             _ => {
2208                                 span_mirbug!(
2209                                     self,
2210                                     rvalue,
2211                                     "Invalid IntToFloat cast {:?} -> {:?}",
2212                                     ty_from,
2213                                     ty
2214                                 )
2215                             }
2216                         }
2217                     }
2218                     CastKind::FloatToInt => {
2219                         let ty_from = op.ty(body, tcx);
2220                         let cast_ty_from = CastTy::from_ty(ty_from);
2221                         let cast_ty_to = CastTy::from_ty(*ty);
2222                         match (cast_ty_from, cast_ty_to) {
2223                             (Some(CastTy::Float), Some(CastTy::Int(_))) => (),
2224                             _ => {
2225                                 span_mirbug!(
2226                                     self,
2227                                     rvalue,
2228                                     "Invalid FloatToInt cast {:?} -> {:?}",
2229                                     ty_from,
2230                                     ty
2231                                 )
2232                             }
2233                         }
2234                     }
2235                     CastKind::FloatToFloat => {
2236                         let ty_from = op.ty(body, tcx);
2237                         let cast_ty_from = CastTy::from_ty(ty_from);
2238                         let cast_ty_to = CastTy::from_ty(*ty);
2239                         match (cast_ty_from, cast_ty_to) {
2240                             (Some(CastTy::Float), Some(CastTy::Float)) => (),
2241                             _ => {
2242                                 span_mirbug!(
2243                                     self,
2244                                     rvalue,
2245                                     "Invalid FloatToFloat cast {:?} -> {:?}",
2246                                     ty_from,
2247                                     ty
2248                                 )
2249                             }
2250                         }
2251                     }
2252                     CastKind::FnPtrToPtr => {
2253                         let ty_from = op.ty(body, tcx);
2254                         let cast_ty_from = CastTy::from_ty(ty_from);
2255                         let cast_ty_to = CastTy::from_ty(*ty);
2256                         match (cast_ty_from, cast_ty_to) {
2257                             (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
2258                             _ => {
2259                                 span_mirbug!(
2260                                     self,
2261                                     rvalue,
2262                                     "Invalid FnPtrToPtr cast {:?} -> {:?}",
2263                                     ty_from,
2264                                     ty
2265                                 )
2266                             }
2267                         }
2268                     }
2269                     CastKind::PtrToPtr => {
2270                         let ty_from = op.ty(body, tcx);
2271                         let cast_ty_from = CastTy::from_ty(ty_from);
2272                         let cast_ty_to = CastTy::from_ty(*ty);
2273                         match (cast_ty_from, cast_ty_to) {
2274                             (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => (),
2275                             _ => {
2276                                 span_mirbug!(
2277                                     self,
2278                                     rvalue,
2279                                     "Invalid PtrToPtr cast {:?} -> {:?}",
2280                                     ty_from,
2281                                     ty
2282                                 )
2283                             }
2284                         }
2285                     }
2286                     CastKind::Transmute => {
2287                         span_mirbug!(
2288                             self,
2289                             rvalue,
2290                             "Unexpected CastKind::Transmute, which is not permitted in Analysis MIR",
2291                         );
2292                     }
2293                 }
2294             }
2295 
2296             Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
2297                 self.add_reborrow_constraint(&body, location, *region, borrowed_place);
2298             }
2299 
2300             Rvalue::BinaryOp(
2301                 BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge,
2302                 box (left, right),
2303             ) => {
2304                 self.check_operand(left, location);
2305                 self.check_operand(right, location);
2306 
2307                 let ty_left = left.ty(body, tcx);
2308                 match ty_left.kind() {
2309                     // Types with regions are comparable if they have a common super-type.
2310                     ty::RawPtr(_) | ty::FnPtr(_) => {
2311                         let ty_right = right.ty(body, tcx);
2312                         let common_ty = self.infcx.next_ty_var(TypeVariableOrigin {
2313                             kind: TypeVariableOriginKind::MiscVariable,
2314                             span: body.source_info(location).span,
2315                         });
2316                         self.sub_types(
2317                             ty_left,
2318                             common_ty,
2319                             location.to_locations(),
2320                             ConstraintCategory::Boring,
2321                         )
2322                         .unwrap_or_else(|err| {
2323                             bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
2324                         });
2325                         if let Err(terr) = self.sub_types(
2326                             ty_right,
2327                             common_ty,
2328                             location.to_locations(),
2329                             ConstraintCategory::Boring,
2330                         ) {
2331                             span_mirbug!(
2332                                 self,
2333                                 rvalue,
2334                                 "unexpected comparison types {:?} and {:?} yields {:?}",
2335                                 ty_left,
2336                                 ty_right,
2337                                 terr
2338                             )
2339                         }
2340                     }
2341                     // For types with no regions we can just check that the
2342                     // both operands have the same type.
2343                     ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_)
2344                         if ty_left == right.ty(body, tcx) => {}
2345                     // Other types are compared by trait methods, not by
2346                     // `Rvalue::BinaryOp`.
2347                     _ => span_mirbug!(
2348                         self,
2349                         rvalue,
2350                         "unexpected comparison types {:?} and {:?}",
2351                         ty_left,
2352                         right.ty(body, tcx)
2353                     ),
2354                 }
2355             }
2356 
2357             Rvalue::Use(operand) | Rvalue::UnaryOp(_, operand) => {
2358                 self.check_operand(operand, location);
2359             }
2360             Rvalue::CopyForDeref(place) => {
2361                 let op = &Operand::Copy(*place);
2362                 self.check_operand(op, location);
2363             }
2364 
2365             Rvalue::BinaryOp(_, box (left, right))
2366             | Rvalue::CheckedBinaryOp(_, box (left, right)) => {
2367                 self.check_operand(left, location);
2368                 self.check_operand(right, location);
2369             }
2370 
2371             Rvalue::AddressOf(..)
2372             | Rvalue::ThreadLocalRef(..)
2373             | Rvalue::Len(..)
2374             | Rvalue::Discriminant(..)
2375             | Rvalue::NullaryOp(NullOp::OffsetOf(..), _) => {}
2376         }
2377     }
2378 
2379     /// If this rvalue supports a user-given type annotation, then
2380     /// extract and return it. This represents the final type of the
2381     /// rvalue and will be unified with the inferred type.
rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex>2382     fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex> {
2383         match rvalue {
2384             Rvalue::Use(_)
2385             | Rvalue::ThreadLocalRef(_)
2386             | Rvalue::Repeat(..)
2387             | Rvalue::Ref(..)
2388             | Rvalue::AddressOf(..)
2389             | Rvalue::Len(..)
2390             | Rvalue::Cast(..)
2391             | Rvalue::ShallowInitBox(..)
2392             | Rvalue::BinaryOp(..)
2393             | Rvalue::CheckedBinaryOp(..)
2394             | Rvalue::NullaryOp(..)
2395             | Rvalue::CopyForDeref(..)
2396             | Rvalue::UnaryOp(..)
2397             | Rvalue::Discriminant(..) => None,
2398 
2399             Rvalue::Aggregate(aggregate, _) => match **aggregate {
2400                 AggregateKind::Adt(_, _, _, user_ty, _) => user_ty,
2401                 AggregateKind::Array(_) => None,
2402                 AggregateKind::Tuple => None,
2403                 AggregateKind::Closure(_, _) => None,
2404                 AggregateKind::Generator(_, _, _) => None,
2405             },
2406         }
2407     }
2408 
check_aggregate_rvalue( &mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, aggregate_kind: &AggregateKind<'tcx>, operands: &IndexSlice<FieldIdx, Operand<'tcx>>, location: Location, )2409     fn check_aggregate_rvalue(
2410         &mut self,
2411         body: &Body<'tcx>,
2412         rvalue: &Rvalue<'tcx>,
2413         aggregate_kind: &AggregateKind<'tcx>,
2414         operands: &IndexSlice<FieldIdx, Operand<'tcx>>,
2415         location: Location,
2416     ) {
2417         let tcx = self.tcx();
2418 
2419         self.prove_aggregate_predicates(aggregate_kind, location);
2420 
2421         if *aggregate_kind == AggregateKind::Tuple {
2422             // tuple rvalue field type is always the type of the op. Nothing to check here.
2423             return;
2424         }
2425 
2426         for (i, operand) in operands.iter_enumerated() {
2427             let field_ty = match self.aggregate_field_ty(aggregate_kind, i, location) {
2428                 Ok(field_ty) => field_ty,
2429                 Err(FieldAccessError::OutOfRange { field_count }) => {
2430                     span_mirbug!(
2431                         self,
2432                         rvalue,
2433                         "accessed field #{} but variant only has {}",
2434                         i.as_u32(),
2435                         field_count,
2436                     );
2437                     continue;
2438                 }
2439             };
2440             let operand_ty = operand.ty(body, tcx);
2441             let operand_ty = self.normalize(operand_ty, location);
2442 
2443             if let Err(terr) = self.sub_types(
2444                 operand_ty,
2445                 field_ty,
2446                 location.to_locations(),
2447                 ConstraintCategory::Boring,
2448             ) {
2449                 span_mirbug!(
2450                     self,
2451                     rvalue,
2452                     "{:?} is not a subtype of {:?}: {:?}",
2453                     operand_ty,
2454                     field_ty,
2455                     terr
2456                 );
2457             }
2458         }
2459     }
2460 
2461     /// Adds the constraints that arise from a borrow expression `&'a P` at the location `L`.
2462     ///
2463     /// # Parameters
2464     ///
2465     /// - `location`: the location `L` where the borrow expression occurs
2466     /// - `borrow_region`: the region `'a` associated with the borrow
2467     /// - `borrowed_place`: the place `P` being borrowed
add_reborrow_constraint( &mut self, body: &Body<'tcx>, location: Location, borrow_region: ty::Region<'tcx>, borrowed_place: &Place<'tcx>, )2468     fn add_reborrow_constraint(
2469         &mut self,
2470         body: &Body<'tcx>,
2471         location: Location,
2472         borrow_region: ty::Region<'tcx>,
2473         borrowed_place: &Place<'tcx>,
2474     ) {
2475         // These constraints are only meaningful during borrowck:
2476         let BorrowCheckContext { borrow_set, location_table, all_facts, constraints, .. } =
2477             self.borrowck_context;
2478 
2479         // In Polonius mode, we also push a `loan_issued_at` fact
2480         // linking the loan to the region (in some cases, though,
2481         // there is no loan associated with this borrow expression --
2482         // that occurs when we are borrowing an unsafe place, for
2483         // example).
2484         if let Some(all_facts) = all_facts {
2485             let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
2486             if let Some(borrow_index) = borrow_set.get_index_of(&location) {
2487                 let region_vid = borrow_region.as_var();
2488                 all_facts.loan_issued_at.push((
2489                     region_vid,
2490                     borrow_index,
2491                     location_table.mid_index(location),
2492                 ));
2493             }
2494         }
2495 
2496         // If we are reborrowing the referent of another reference, we
2497         // need to add outlives relationships. In a case like `&mut
2498         // *p`, where the `p` has type `&'b mut Foo`, for example, we
2499         // need to ensure that `'b: 'a`.
2500 
2501         debug!(
2502             "add_reborrow_constraint({:?}, {:?}, {:?})",
2503             location, borrow_region, borrowed_place
2504         );
2505 
2506         let tcx = self.infcx.tcx;
2507         let field = path_utils::is_upvar_field_projection(
2508             tcx,
2509             &self.borrowck_context.upvars,
2510             borrowed_place.as_ref(),
2511             body,
2512         );
2513         let category = if let Some(field) = field {
2514             ConstraintCategory::ClosureUpvar(field)
2515         } else {
2516             ConstraintCategory::Boring
2517         };
2518 
2519         for (base, elem) in borrowed_place.as_ref().iter_projections().rev() {
2520             debug!("add_reborrow_constraint - iteration {:?}", elem);
2521 
2522             match elem {
2523                 ProjectionElem::Deref => {
2524                     let base_ty = base.ty(body, tcx).ty;
2525 
2526                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
2527                     match base_ty.kind() {
2528                         ty::Ref(ref_region, _, mutbl) => {
2529                             constraints.outlives_constraints.push(OutlivesConstraint {
2530                                 sup: ref_region.as_var(),
2531                                 sub: borrow_region.as_var(),
2532                                 locations: location.to_locations(),
2533                                 span: location.to_locations().span(body),
2534                                 category,
2535                                 variance_info: ty::VarianceDiagInfo::default(),
2536                                 from_closure: false,
2537                             });
2538 
2539                             match mutbl {
2540                                 hir::Mutability::Not => {
2541                                     // Immutable reference. We don't need the base
2542                                     // to be valid for the entire lifetime of
2543                                     // the borrow.
2544                                     break;
2545                                 }
2546                                 hir::Mutability::Mut => {
2547                                     // Mutable reference. We *do* need the base
2548                                     // to be valid, because after the base becomes
2549                                     // invalid, someone else can use our mutable deref.
2550 
2551                                     // This is in order to make the following function
2552                                     // illegal:
2553                                     // ```
2554                                     // fn unsafe_deref<'a, 'b>(x: &'a &'b mut T) -> &'b mut T {
2555                                     //     &mut *x
2556                                     // }
2557                                     // ```
2558                                     //
2559                                     // As otherwise you could clone `&mut T` using the
2560                                     // following function:
2561                                     // ```
2562                                     // fn bad(x: &mut T) -> (&mut T, &mut T) {
2563                                     //     let my_clone = unsafe_deref(&'a x);
2564                                     //     ENDREGION 'a;
2565                                     //     (my_clone, x)
2566                                     // }
2567                                     // ```
2568                                 }
2569                             }
2570                         }
2571                         ty::RawPtr(..) => {
2572                             // deref of raw pointer, guaranteed to be valid
2573                             break;
2574                         }
2575                         ty::Adt(def, _) if def.is_box() => {
2576                             // deref of `Box`, need the base to be valid - propagate
2577                         }
2578                         _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place),
2579                     }
2580                 }
2581                 ProjectionElem::Field(..)
2582                 | ProjectionElem::Downcast(..)
2583                 | ProjectionElem::OpaqueCast(..)
2584                 | ProjectionElem::Index(..)
2585                 | ProjectionElem::ConstantIndex { .. }
2586                 | ProjectionElem::Subslice { .. } => {
2587                     // other field access
2588                 }
2589             }
2590         }
2591     }
2592 
prove_aggregate_predicates( &mut self, aggregate_kind: &AggregateKind<'tcx>, location: Location, )2593     fn prove_aggregate_predicates(
2594         &mut self,
2595         aggregate_kind: &AggregateKind<'tcx>,
2596         location: Location,
2597     ) {
2598         let tcx = self.tcx();
2599 
2600         debug!(
2601             "prove_aggregate_predicates(aggregate_kind={:?}, location={:?})",
2602             aggregate_kind, location
2603         );
2604 
2605         let (def_id, instantiated_predicates) = match *aggregate_kind {
2606             AggregateKind::Adt(adt_did, _, substs, _, _) => {
2607                 (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, substs))
2608             }
2609 
2610             // For closures, we have some **extra requirements** we
2611             // have to check. In particular, in their upvars and
2612             // signatures, closures often reference various regions
2613             // from the surrounding function -- we call those the
2614             // closure's free regions. When we borrow-check (and hence
2615             // region-check) closures, we may find that the closure
2616             // requires certain relationships between those free
2617             // regions. However, because those free regions refer to
2618             // portions of the CFG of their caller, the closure is not
2619             // in a position to verify those relationships. In that
2620             // case, the requirements get "propagated" to us, and so
2621             // we have to solve them here where we instantiate the
2622             // closure.
2623             //
2624             // Despite the opacity of the previous paragraph, this is
2625             // actually relatively easy to understand in terms of the
2626             // desugaring. A closure gets desugared to a struct, and
2627             // these extra requirements are basically like where
2628             // clauses on the struct.
2629             AggregateKind::Closure(def_id, substs)
2630             | AggregateKind::Generator(def_id, substs, _) => {
2631                 (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location))
2632             }
2633 
2634             AggregateKind::Array(_) | AggregateKind::Tuple => {
2635                 (CRATE_DEF_ID.to_def_id(), ty::InstantiatedPredicates::empty())
2636             }
2637         };
2638 
2639         self.normalize_and_prove_instantiated_predicates(
2640             def_id,
2641             instantiated_predicates,
2642             location.to_locations(),
2643         );
2644     }
2645 
prove_closure_bounds( &mut self, tcx: TyCtxt<'tcx>, def_id: LocalDefId, substs: SubstsRef<'tcx>, location: Location, ) -> ty::InstantiatedPredicates<'tcx>2646     fn prove_closure_bounds(
2647         &mut self,
2648         tcx: TyCtxt<'tcx>,
2649         def_id: LocalDefId,
2650         substs: SubstsRef<'tcx>,
2651         location: Location,
2652     ) -> ty::InstantiatedPredicates<'tcx> {
2653         if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
2654             constraint_conversion::ConstraintConversion::new(
2655                 self.infcx,
2656                 self.borrowck_context.universal_regions,
2657                 self.region_bound_pairs,
2658                 self.implicit_region_bound,
2659                 self.param_env,
2660                 location.to_locations(),
2661                 DUMMY_SP,                   // irrelevant; will be overridden.
2662                 ConstraintCategory::Boring, // same as above.
2663                 &mut self.borrowck_context.constraints,
2664             )
2665             .apply_closure_requirements(
2666                 &closure_requirements,
2667                 def_id.to_def_id(),
2668                 substs,
2669             );
2670         }
2671 
2672         // Now equate closure substs to regions inherited from `typeck_root_def_id`. Fixes #98589.
2673         let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
2674         let typeck_root_substs = ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
2675 
2676         let parent_substs = match tcx.def_kind(def_id) {
2677             DefKind::Closure => substs.as_closure().parent_substs(),
2678             DefKind::Generator => substs.as_generator().parent_substs(),
2679             DefKind::InlineConst => substs.as_inline_const().parent_substs(),
2680             other => bug!("unexpected item {:?}", other),
2681         };
2682         let parent_substs = tcx.mk_substs(parent_substs);
2683 
2684         assert_eq!(typeck_root_substs.len(), parent_substs.len());
2685         if let Err(_) = self.eq_substs(
2686             typeck_root_substs,
2687             parent_substs,
2688             location.to_locations(),
2689             ConstraintCategory::BoringNoLocation,
2690         ) {
2691             span_mirbug!(
2692                 self,
2693                 def_id,
2694                 "could not relate closure to parent {:?} != {:?}",
2695                 typeck_root_substs,
2696                 parent_substs
2697             );
2698         }
2699 
2700         tcx.predicates_of(def_id).instantiate(tcx, substs)
2701     }
2702 
2703     #[instrument(skip(self, body), level = "debug")]
typeck_mir(&mut self, body: &Body<'tcx>)2704     fn typeck_mir(&mut self, body: &Body<'tcx>) {
2705         self.last_span = body.span;
2706         debug!(?body.span);
2707 
2708         for (local, local_decl) in body.local_decls.iter_enumerated() {
2709             self.check_local(&body, local, local_decl);
2710         }
2711 
2712         for (block, block_data) in body.basic_blocks.iter_enumerated() {
2713             let mut location = Location { block, statement_index: 0 };
2714             for stmt in &block_data.statements {
2715                 if !stmt.source_info.span.is_dummy() {
2716                     self.last_span = stmt.source_info.span;
2717                 }
2718                 self.check_stmt(body, stmt, location);
2719                 location.statement_index += 1;
2720             }
2721 
2722             self.check_terminator(&body, block_data.terminator(), location);
2723             self.check_iscleanup(&body, block_data);
2724         }
2725     }
2726 }
2727 
2728 trait NormalizeLocation: fmt::Debug + Copy {
to_locations(self) -> Locations2729     fn to_locations(self) -> Locations;
2730 }
2731 
2732 impl NormalizeLocation for Locations {
to_locations(self) -> Locations2733     fn to_locations(self) -> Locations {
2734         self
2735     }
2736 }
2737 
2738 impl NormalizeLocation for Location {
to_locations(self) -> Locations2739     fn to_locations(self) -> Locations {
2740         Locations::Single(self)
2741     }
2742 }
2743 
2744 /// Runs `infcx.instantiate_opaque_types`. Unlike other `TypeOp`s,
2745 /// this is not canonicalized - it directly affects the main `InferCtxt`
2746 /// that we use during MIR borrowchecking.
2747 #[derive(Debug)]
2748 pub(super) struct InstantiateOpaqueType<'tcx> {
2749     pub base_universe: Option<ty::UniverseIndex>,
2750     pub region_constraints: Option<RegionConstraintData<'tcx>>,
2751     pub obligations: Vec<PredicateObligation<'tcx>>,
2752 }
2753 
2754 impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
2755     type Output = ();
2756     /// We use this type itself to store the information used
2757     /// when reporting errors. Since this is not a query, we don't
2758     /// re-run anything during error reporting - we just use the information
2759     /// we saved to help extract an error from the already-existing region
2760     /// constraints in our `InferCtxt`
2761     type ErrorInfo = InstantiateOpaqueType<'tcx>;
2762 
fully_perform( mut self, infcx: &InferCtxt<'tcx>, span: Span, ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>2763     fn fully_perform(
2764         mut self,
2765         infcx: &InferCtxt<'tcx>,
2766         span: Span,
2767     ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
2768         let (mut output, region_constraints) = scrape_region_constraints(
2769             infcx,
2770             |ocx| {
2771                 ocx.register_obligations(self.obligations.clone());
2772                 Ok(())
2773             },
2774             "InstantiateOpaqueType",
2775             span,
2776         )?;
2777         self.region_constraints = Some(region_constraints);
2778         output.error_info = Some(self);
2779         Ok(output)
2780     }
2781 }
2782