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