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