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 ®ion_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