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