1 //! This pass type-checks the MIR to ensure it is not broken.
4 use std
::{fmt, iter, mem}
;
8 use rustc_data_structures
::frozen
::Frozen
;
9 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
10 use rustc_errors
::struct_span_err
;
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
,
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
,
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}
;
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
,
48 promote_consts
::should_suggest_const_in_array_repeat_expressions_attribute
,
51 use crate::borrow_check
::{
52 borrow_set
::BorrowSet
,
53 constraints
::{OutlivesConstraint, OutlivesConstraintSet}
,
55 location
::LocationTable
,
56 member_constraints
::MemberConstraintSet
,
59 region_infer
::values
::{
60 LivenessValues
, PlaceholderIndex
, PlaceholderIndices
, RegionValueElements
,
62 region_infer
::{ClosureRegionRequirementsExt, TypeTest}
,
64 type_check
::free_region_relations
::{CreateResult, UniversalRegionRelations}
,
65 universal_regions
::{DefiningTy, UniversalRegions}
,
69 macro_rules
! span_mirbug
{
70 ($context
:expr
, $elem
:expr
, $
($message
:tt
)*) => ({
71 $
crate::borrow_check
::type_check
::mirbug(
75 "broken MIR in {:?} ({:?}): {}",
78 format_args
!($
($message
)*),
84 macro_rules
! span_mirbug_and_err
{
85 ($context
:expr
, $elem
:expr
, $
($message
:tt
)*) => ({
87 span_mirbug
!($context
, $elem
, $
($message
)*);
93 mod constraint_conversion
;
94 pub mod free_region_relations
;
99 /// Type checks the given `mir` in the context of the inference
100 /// context `infcx`. Returns any region constraints that have yet to
101 /// be proven. This result is includes liveness constraints that
102 /// ensure that regions appearing in the types of all local variables
103 /// are live at all points where that local variable may later be
106 /// This phase of type-check ought to be infallible -- this is because
107 /// the original, HIR-based type-check succeeded. So if any errors
108 /// occur here, we will get a `bug!` reported.
112 /// - `infcx` -- inference context to use
113 /// - `param_env` -- parameter environment to use for trait solving
114 /// - `body` -- MIR body to type-check
115 /// - `promoted` -- map of promoted constants within `body`
116 /// - `mir_def_id` -- `LocalDefId` from which the MIR is derived
117 /// - `universal_regions` -- the universal regions from `body`s function signature
118 /// - `location_table` -- MIR location map of `body`
119 /// - `borrow_set` -- information about borrows occurring in `body`
120 /// - `all_facts` -- when using Polonius, this is the generated set of Polonius facts
121 /// - `flow_inits` -- results of a maybe-init dataflow analysis
122 /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis
123 /// - `elements` -- MIR region map
124 pub(crate) fn type_check
<'mir
, 'tcx
>(
125 infcx
: &InferCtxt
<'_
, 'tcx
>,
126 param_env
: ty
::ParamEnv
<'tcx
>,
128 promoted
: &IndexVec
<Promoted
, Body
<'tcx
>>,
129 mir_def_id
: LocalDefId
,
130 universal_regions
: &Rc
<UniversalRegions
<'tcx
>>,
131 location_table
: &LocationTable
,
132 borrow_set
: &BorrowSet
<'tcx
>,
133 all_facts
: &mut Option
<AllFacts
>,
134 flow_inits
: &mut ResultsCursor
<'mir
, 'tcx
, MaybeInitializedPlaces
<'mir
, 'tcx
>>,
135 move_data
: &MoveData
<'tcx
>,
136 elements
: &Rc
<RegionValueElements
>,
138 ) -> MirTypeckResults
<'tcx
> {
139 let implicit_region_bound
= infcx
.tcx
.mk_region(ty
::ReVar(universal_regions
.fr_fn_body
));
140 let mut constraints
= MirTypeckRegionConstraints
{
141 placeholder_indices
: PlaceholderIndices
::default(),
142 placeholder_index_to_region
: IndexVec
::default(),
143 liveness_constraints
: LivenessValues
::new(elements
.clone()),
144 outlives_constraints
: OutlivesConstraintSet
::default(),
145 member_constraints
: MemberConstraintSet
::default(),
146 closure_bounds_mapping
: Default
::default(),
147 type_tests
: Vec
::default(),
151 universal_region_relations
,
153 normalized_inputs_and_output
,
154 } = free_region_relations
::create(
157 Some(implicit_region_bound
),
162 let mut borrowck_context
= BorrowCheckContext
{
167 constraints
: &mut constraints
,
171 let opaque_type_values
= type_check_internal(
178 implicit_region_bound
,
179 &mut borrowck_context
,
180 &universal_region_relations
,
182 cx
.equate_inputs_and_outputs(&body
, universal_regions
, &normalized_inputs_and_output
);
183 liveness
::generate(&mut cx
, body
, elements
, flow_inits
, move_data
, location_table
);
185 translate_outlives_facts(&mut cx
);
186 cx
.opaque_type_values
190 MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
193 fn type_check_internal
<'a
, 'tcx
, R
>(
194 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
195 mir_def_id
: LocalDefId
,
196 param_env
: ty
::ParamEnv
<'tcx
>,
197 body
: &'a Body
<'tcx
>,
198 promoted
: &'a IndexVec
<Promoted
, Body
<'tcx
>>,
199 region_bound_pairs
: &'a RegionBoundPairs
<'tcx
>,
200 implicit_region_bound
: ty
::Region
<'tcx
>,
201 borrowck_context
: &'a
mut BorrowCheckContext
<'a
, 'tcx
>,
202 universal_region_relations
: &'a UniversalRegionRelations
<'tcx
>,
203 extra
: impl FnOnce(TypeChecker
<'a
, 'tcx
>) -> R
,
205 let mut checker
= TypeChecker
::new(
211 implicit_region_bound
,
213 universal_region_relations
,
215 let errors_reported
= {
216 let mut verifier
= TypeVerifier
::new(&mut checker
, body
, promoted
);
217 verifier
.visit_body(&body
);
218 verifier
.errors_reported
221 if !errors_reported
{
222 // if verifier failed, don't do further checks to avoid ICEs
223 checker
.typeck_mir(body
);
229 fn translate_outlives_facts(typeck
: &mut TypeChecker
<'_
, '_
>) {
230 let cx
= &mut typeck
.borrowck_context
;
231 if let Some(facts
) = cx
.all_facts
{
232 let _prof_timer
= typeck
.infcx
.tcx
.prof
.generic_activity("polonius_fact_generation");
233 let location_table
= cx
.location_table
;
234 facts
.outlives
.extend(cx
.constraints
.outlives_constraints
.outlives().iter().flat_map(
235 |constraint
: &OutlivesConstraint
| {
236 if let Some(from_location
) = constraint
.locations
.from_location() {
237 Either
::Left(iter
::once((
240 location_table
.mid_index(from_location
),
246 .map(move |location
| (constraint
.sup
, constraint
.sub
, location
)),
254 fn mirbug(tcx
: TyCtxt
<'_
>, span
: Span
, msg
: &str) {
255 // We sometimes see MIR failures (notably predicate failures) due to
256 // the fact that we check rvalue sized predicates here. So use `delay_span_bug`
257 // to avoid reporting bugs in those cases.
258 tcx
.sess
.diagnostic().delay_span_bug(span
, msg
);
261 enum FieldAccessError
{
262 OutOfRange { field_count: usize }
,
265 /// Verifies that MIR types are sane to not crash further checks.
267 /// The sanitize_XYZ methods here take an MIR object and compute its
268 /// type, calling `span_mirbug` and returning an error type if there
270 struct TypeVerifier
<'a
, 'b
, 'tcx
> {
271 cx
: &'a
mut TypeChecker
<'b
, 'tcx
>,
272 body
: &'b Body
<'tcx
>,
273 promoted
: &'b IndexVec
<Promoted
, Body
<'tcx
>>,
275 mir_def_id
: LocalDefId
,
276 errors_reported
: bool
,
279 impl<'a
, 'b
, 'tcx
> Visitor
<'tcx
> for TypeVerifier
<'a
, 'b
, 'tcx
> {
280 fn visit_span(&mut self, span
: &Span
) {
281 if !span
.is_dummy() {
282 self.last_span
= *span
;
286 fn visit_place(&mut self, place
: &Place
<'tcx
>, context
: PlaceContext
, location
: Location
) {
287 self.sanitize_place(place
, location
, context
);
290 fn visit_constant(&mut self, constant
: &Constant
<'tcx
>, location
: Location
) {
291 self.super_constant(constant
, location
);
292 let ty
= self.sanitize_type(constant
, constant
.literal
.ty
);
294 self.cx
.infcx
.tcx
.for_each_free_region(&ty
, |live_region
| {
295 let live_region_vid
=
296 self.cx
.borrowck_context
.universal_regions
.to_region_vid(live_region
);
300 .liveness_constraints
301 .add_element(live_region_vid
, location
);
304 if let Some(annotation_index
) = constant
.user_ty
{
305 if let Err(terr
) = self.cx
.relate_type_and_user_type(
307 ty
::Variance
::Invariant
,
308 &UserTypeProjection { base: annotation_index, projs: vec![] }
,
309 location
.to_locations(),
310 ConstraintCategory
::Boring
,
312 let annotation
= &self.cx
.user_type_annotations
[annotation_index
];
316 "bad constant user type {:?} vs {:?}: {:?}",
323 let tcx
= self.tcx();
324 if let ty
::ConstKind
::Unevaluated(def
, substs
, promoted
) = constant
.literal
.val
{
325 if let Some(promoted
) = promoted
{
326 let check_err
= |verifier
: &mut TypeVerifier
<'a
, 'b
, 'tcx
>,
327 promoted
: &Body
<'tcx
>,
330 if let Err(terr
) = verifier
.cx
.eq_types(
333 location
.to_locations(),
334 ConstraintCategory
::Boring
,
339 "bad promoted type ({:?}: {:?}): {:?}",
347 if !self.errors_reported
{
348 let promoted_body
= &self.promoted
[promoted
];
349 self.sanitize_promoted(promoted_body
, location
);
351 let promoted_ty
= promoted_body
.return_ty();
352 check_err(self, promoted_body
, ty
, promoted_ty
);
355 if let Err(terr
) = self.cx
.fully_perform_op(
356 location
.to_locations(),
357 ConstraintCategory
::Boring
,
358 self.cx
.param_env
.and(type_op
::ascribe_user_type
::AscribeUserType
::new(
361 UserSubsts { substs, user_self_ty: None }
,
367 "bad constant type {:?} ({:?})",
373 } else if let Some(static_def_id
) = constant
.check_static_ptr(tcx
) {
374 let unnormalized_ty
= tcx
.type_of(static_def_id
);
375 let locations
= location
.to_locations();
376 let normalized_ty
= self.cx
.normalize(unnormalized_ty
, locations
);
377 let literal_ty
= constant
.literal
.ty
.builtin_deref(true).unwrap().ty
;
379 if let Err(terr
) = self.cx
.eq_types(
383 ConstraintCategory
::Boring
,
385 span_mirbug
!(self, constant
, "bad static type {:?} ({:?})", constant
, terr
);
389 if let ty
::FnDef(def_id
, substs
) = *constant
.literal
.ty
.kind() {
390 let instantiated_predicates
= tcx
.predicates_of(def_id
).instantiate(tcx
, substs
);
391 self.cx
.normalize_and_prove_instantiated_predicates(
392 instantiated_predicates
,
393 location
.to_locations(),
399 fn visit_rvalue(&mut self, rvalue
: &Rvalue
<'tcx
>, location
: Location
) {
400 self.super_rvalue(rvalue
, location
);
401 let rval_ty
= rvalue
.ty(self.body
, self.tcx());
402 self.sanitize_type(rvalue
, rval_ty
);
405 fn visit_local_decl(&mut self, local
: Local
, local_decl
: &LocalDecl
<'tcx
>) {
406 self.super_local_decl(local
, local_decl
);
407 self.sanitize_type(local_decl
, local_decl
.ty
);
409 if let Some(user_ty
) = &local_decl
.user_ty
{
410 for (user_ty
, span
) in user_ty
.projections_and_spans() {
411 let ty
= if !local_decl
.is_nonref_binding() {
412 // If we have a binding of the form `let ref x: T = ..`
413 // then remove the outermost reference so we can check the
414 // type annotation for the remaining type.
415 if let ty
::Ref(_
, rty
, _
) = local_decl
.ty
.kind() {
418 bug
!("{:?} with ref binding has wrong type {}", local
, local_decl
.ty
);
424 if let Err(terr
) = self.cx
.relate_type_and_user_type(
426 ty
::Variance
::Invariant
,
428 Locations
::All(*span
),
429 ConstraintCategory
::TypeAnnotation
,
434 "bad user type on variable {:?}: {:?} != {:?} ({:?})",
445 fn visit_body(&mut self, body
: &Body
<'tcx
>) {
446 self.sanitize_type(&"return type", body
.return_ty());
447 for local_decl
in &body
.local_decls
{
448 self.sanitize_type(local_decl
, local_decl
.ty
);
450 if self.errors_reported
{
453 self.super_body(body
);
457 impl<'a
, 'b
, 'tcx
> TypeVerifier
<'a
, 'b
, 'tcx
> {
459 cx
: &'a
mut TypeChecker
<'b
, 'tcx
>,
460 body
: &'b Body
<'tcx
>,
461 promoted
: &'b IndexVec
<Promoted
, Body
<'tcx
>>,
466 mir_def_id
: cx
.mir_def_id
,
468 last_span
: body
.span
,
469 errors_reported
: false,
473 fn tcx(&self) -> TyCtxt
<'tcx
> {
477 fn sanitize_type(&mut self, parent
: &dyn fmt
::Debug
, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
478 if ty
.has_escaping_bound_vars() || ty
.references_error() {
479 span_mirbug_and_err
!(self, parent
, "bad type {:?}", ty
)
485 /// Checks that the types internal to the `place` match up with
486 /// what would be expected.
491 context
: PlaceContext
,
493 debug
!("sanitize_place: {:?}", place
);
495 let mut place_ty
= PlaceTy
::from_ty(self.body
.local_decls
[place
.local
].ty
);
497 for elem
in place
.projection
.iter() {
498 if place_ty
.variant_index
.is_none() {
499 if place_ty
.ty
.references_error() {
500 assert
!(self.errors_reported
);
501 return PlaceTy
::from_ty(self.tcx().ty_error());
504 place_ty
= self.sanitize_projection(place_ty
, elem
, place
, location
)
507 if let PlaceContext
::NonMutatingUse(NonMutatingUseContext
::Copy
) = context
{
508 let tcx
= self.tcx();
509 let trait_ref
= ty
::TraitRef
{
510 def_id
: tcx
.require_lang_item(LangItem
::Copy
, Some(self.last_span
)),
511 substs
: tcx
.mk_substs_trait(place_ty
.ty
, &[]),
514 // To have a `Copy` operand, the type `T` of the
515 // value must be `Copy`. Note that we prove that `T: Copy`,
516 // rather than using the `is_copy_modulo_regions`
517 // test. This is important because
518 // `is_copy_modulo_regions` ignores the resulting region
519 // obligations and assumes they pass. This can result in
520 // bounds from `Copy` impls being unsoundly ignored (e.g.,
521 // #29149). Note that we decide to use `Copy` before knowing
522 // whether the bounds fully apply: in effect, the rule is
523 // that if a value of some type could implement `Copy`, then
525 self.cx
.prove_trait_ref(
527 location
.to_locations(),
528 ConstraintCategory
::CopyBound
,
535 fn sanitize_promoted(&mut self, promoted_body
: &'b Body
<'tcx
>, location
: Location
) {
536 // Determine the constraints from the promoted MIR by running the type
537 // checker on the promoted MIR, then transfer the constraints back to
538 // the main MIR, changing the locations to the provided location.
540 let parent_body
= mem
::replace(&mut self.body
, promoted_body
);
542 // Use new sets of constraints and closure bounds so that we can
543 // modify their locations.
544 let all_facts
= &mut None
;
545 let mut constraints
= Default
::default();
546 let mut closure_bounds
= Default
::default();
547 let mut liveness_constraints
=
548 LivenessValues
::new(Rc
::new(RegionValueElements
::new(&promoted_body
)));
549 // Don't try to add borrow_region facts for the promoted MIR
551 let mut swap_constraints
= |this
: &mut Self| {
552 mem
::swap(this
.cx
.borrowck_context
.all_facts
, all_facts
);
554 &mut this
.cx
.borrowck_context
.constraints
.outlives_constraints
,
558 &mut this
.cx
.borrowck_context
.constraints
.closure_bounds_mapping
,
562 &mut this
.cx
.borrowck_context
.constraints
.liveness_constraints
,
563 &mut liveness_constraints
,
567 swap_constraints(self);
569 self.visit_body(&promoted_body
);
571 if !self.errors_reported
{
572 // if verifier failed, don't do further checks to avoid ICEs
573 self.cx
.typeck_mir(promoted_body
);
576 self.body
= parent_body
;
577 // Merge the outlives constraints back in, at the given location.
578 swap_constraints(self);
580 let locations
= location
.to_locations();
581 for constraint
in constraints
.outlives().iter() {
582 let mut constraint
= *constraint
;
583 constraint
.locations
= locations
;
584 if let ConstraintCategory
::Return(_
)
585 | ConstraintCategory
::UseAsConst
586 | ConstraintCategory
::UseAsStatic
= constraint
.category
588 // "Returning" from a promoted is an assignment to a
589 // temporary from the user's point of view.
590 constraint
.category
= ConstraintCategory
::Boring
;
592 self.cx
.borrowck_context
.constraints
.outlives_constraints
.push(constraint
)
594 for live_region
in liveness_constraints
.rows() {
598 .liveness_constraints
599 .add_element(live_region
, location
);
602 if !closure_bounds
.is_empty() {
603 let combined_bounds_mapping
=
604 closure_bounds
.into_iter().flat_map(|(_
, value
)| value
).collect();
609 .closure_bounds_mapping
610 .insert(location
, combined_bounds_mapping
);
611 assert
!(existing
.is_none(), "Multiple promoteds/closures at the same location.");
615 fn sanitize_projection(
622 debug
!("sanitize_projection: {:?} {:?} {:?}", base
, pi
, place
);
623 let tcx
= self.tcx();
624 let base_ty
= base
.ty
;
626 ProjectionElem
::Deref
=> {
627 let deref_ty
= base_ty
.builtin_deref(true);
628 PlaceTy
::from_ty(deref_ty
.map(|t
| t
.ty
).unwrap_or_else(|| {
629 span_mirbug_and_err
!(self, place
, "deref of non-pointer {:?}", base_ty
)
632 ProjectionElem
::Index(i
) => {
633 let index_ty
= Place
::from(i
).ty(self.body
, tcx
).ty
;
634 if index_ty
!= tcx
.types
.usize {
635 PlaceTy
::from_ty(span_mirbug_and_err
!(self, i
, "index by non-usize {:?}", i
))
637 PlaceTy
::from_ty(base_ty
.builtin_index().unwrap_or_else(|| {
638 span_mirbug_and_err
!(self, place
, "index of non-array {:?}", base_ty
)
642 ProjectionElem
::ConstantIndex { .. }
=> {
643 // consider verifying in-bounds
644 PlaceTy
::from_ty(base_ty
.builtin_index().unwrap_or_else(|| {
645 span_mirbug_and_err
!(self, place
, "index of non-array {:?}", base_ty
)
648 ProjectionElem
::Subslice { from, to, from_end }
=> {
649 PlaceTy
::from_ty(match base_ty
.kind() {
650 ty
::Array(inner
, _
) => {
651 assert
!(!from_end
, "array subslices should not use from_end");
652 tcx
.mk_array(inner
, to
- from
)
655 assert
!(from_end
, "slice subslices should use from_end");
658 _
=> span_mirbug_and_err
!(self, place
, "slice of non-array {:?}", base_ty
),
661 ProjectionElem
::Downcast(maybe_name
, index
) => match base_ty
.kind() {
662 ty
::Adt(adt_def
, _substs
) if adt_def
.is_enum() => {
663 if index
.as_usize() >= adt_def
.variants
.len() {
664 PlaceTy
::from_ty(span_mirbug_and_err
!(
667 "cast to variant #{:?} but enum only has {:?}",
669 adt_def
.variants
.len()
672 PlaceTy { ty: base_ty, variant_index: Some(index) }
675 // We do not need to handle generators here, because this runs
676 // before the generator transform stage.
678 let ty
= if let Some(name
) = maybe_name
{
679 span_mirbug_and_err
!(
682 "can't downcast {:?} as {:?}",
687 span_mirbug_and_err
!(self, place
, "can't downcast {:?}", base_ty
)
692 ProjectionElem
::Field(field
, fty
) => {
693 let fty
= self.sanitize_type(place
, fty
);
694 match self.field_ty(place
, base
, field
, location
) {
696 let ty
= self.cx
.normalize(ty
, location
);
697 if let Err(terr
) = self.cx
.eq_types(
700 location
.to_locations(),
701 ConstraintCategory
::Boring
,
706 "bad field access ({:?}: {:?}): {:?}",
713 Err(FieldAccessError
::OutOfRange { field_count }
) => span_mirbug
!(
716 "accessed field #{} but variant only has {}",
721 PlaceTy
::from_ty(fty
)
726 fn error(&mut self) -> Ty
<'tcx
> {
727 self.errors_reported
= true;
728 self.tcx().ty_error()
733 parent
: &dyn fmt
::Debug
,
734 base_ty
: PlaceTy
<'tcx
>,
737 ) -> Result
<Ty
<'tcx
>, FieldAccessError
> {
738 let tcx
= self.tcx();
740 let (variant
, substs
) = match base_ty
{
741 PlaceTy { ty, variant_index: Some(variant_index) }
=> match *ty
.kind() {
742 ty
::Adt(adt_def
, substs
) => (&adt_def
.variants
[variant_index
], substs
),
743 ty
::Generator(def_id
, substs
, _
) => {
744 let mut variants
= substs
.as_generator().state_tys(def_id
, tcx
);
745 let mut variant
= match variants
.nth(variant_index
.into()) {
748 "variant_index of generator out of range: {:?}/{:?}",
750 substs
.as_generator().state_tys(def_id
, tcx
).count()
753 return match variant
.nth(field
.index()) {
755 None
=> Err(FieldAccessError
::OutOfRange { field_count: variant.count() }
),
758 _
=> bug
!("can't have downcast of non-adt non-generator type"),
760 PlaceTy { ty, variant_index: None }
=> match *ty
.kind() {
761 ty
::Adt(adt_def
, substs
) if !adt_def
.is_enum() => {
762 (&adt_def
.variants
[VariantIdx
::new(0)], substs
)
764 ty
::Closure(_
, substs
) => {
765 return match substs
.as_closure().upvar_tys().nth(field
.index()) {
767 None
=> Err(FieldAccessError
::OutOfRange
{
768 field_count
: substs
.as_closure().upvar_tys().count(),
772 ty
::Generator(_
, substs
, _
) => {
773 // Only prefix fields (upvars and current state) are
774 // accessible without a variant index.
775 return match substs
.as_generator().prefix_tys().nth(field
.index()) {
777 None
=> Err(FieldAccessError
::OutOfRange
{
778 field_count
: substs
.as_generator().prefix_tys().count(),
783 return match tys
.get(field
.index()) {
784 Some(&ty
) => Ok(ty
.expect_ty()),
785 None
=> Err(FieldAccessError
::OutOfRange { field_count: tys.len() }
),
789 return Ok(span_mirbug_and_err
!(
792 "can't project out of {:?}",
799 if let Some(field
) = variant
.fields
.get(field
.index()) {
800 Ok(self.cx
.normalize(&field
.ty(tcx
, substs
), location
))
802 Err(FieldAccessError
::OutOfRange { field_count: variant.fields.len() }
)
807 /// The MIR type checker. Visits the MIR and enforces all the
808 /// constraints needed for it to be valid and well-typed. Along the
809 /// way, it accrues region constraints -- these can later be used by
810 /// NLL region checking.
811 struct TypeChecker
<'a
, 'tcx
> {
812 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
813 param_env
: ty
::ParamEnv
<'tcx
>,
815 body
: &'a Body
<'tcx
>,
816 /// User type annotations are shared between the main MIR and the MIR of
817 /// all of the promoted items.
818 user_type_annotations
: &'a CanonicalUserTypeAnnotations
<'tcx
>,
819 mir_def_id
: LocalDefId
,
820 region_bound_pairs
: &'a RegionBoundPairs
<'tcx
>,
821 implicit_region_bound
: ty
::Region
<'tcx
>,
822 reported_errors
: FxHashSet
<(Ty
<'tcx
>, Span
)>,
823 borrowck_context
: &'a
mut BorrowCheckContext
<'a
, 'tcx
>,
824 universal_region_relations
: &'a UniversalRegionRelations
<'tcx
>,
825 opaque_type_values
: FxHashMap
<DefId
, ty
::ResolvedOpaqueTy
<'tcx
>>,
828 struct BorrowCheckContext
<'a
, 'tcx
> {
829 universal_regions
: &'a UniversalRegions
<'tcx
>,
830 location_table
: &'a LocationTable
,
831 all_facts
: &'a
mut Option
<AllFacts
>,
832 borrow_set
: &'a BorrowSet
<'tcx
>,
833 constraints
: &'a
mut MirTypeckRegionConstraints
<'tcx
>,
837 crate struct MirTypeckResults
<'tcx
> {
838 crate constraints
: MirTypeckRegionConstraints
<'tcx
>,
839 pub(in crate::borrow_check
) universal_region_relations
: Frozen
<UniversalRegionRelations
<'tcx
>>,
840 crate opaque_type_values
: FxHashMap
<DefId
, ty
::ResolvedOpaqueTy
<'tcx
>>,
843 /// A collection of region constraints that must be satisfied for the
844 /// program to be considered well-typed.
845 crate struct MirTypeckRegionConstraints
<'tcx
> {
846 /// Maps from a `ty::Placeholder` to the corresponding
847 /// `PlaceholderIndex` bit that we will use for it.
849 /// To keep everything in sync, do not insert this set
850 /// directly. Instead, use the `placeholder_region` helper.
851 crate placeholder_indices
: PlaceholderIndices
,
853 /// Each time we add a placeholder to `placeholder_indices`, we
854 /// also create a corresponding "representative" region vid for
855 /// that wraps it. This vector tracks those. This way, when we
856 /// convert the same `ty::RePlaceholder(p)` twice, we can map to
857 /// the same underlying `RegionVid`.
858 crate placeholder_index_to_region
: IndexVec
<PlaceholderIndex
, ty
::Region
<'tcx
>>,
860 /// In general, the type-checker is not responsible for enforcing
861 /// liveness constraints; this job falls to the region inferencer,
862 /// which performs a liveness analysis. However, in some limited
863 /// cases, the MIR type-checker creates temporary regions that do
864 /// not otherwise appear in the MIR -- in particular, the
865 /// late-bound regions that it instantiates at call-sites -- and
866 /// hence it must report on their liveness constraints.
867 crate liveness_constraints
: LivenessValues
<RegionVid
>,
869 crate outlives_constraints
: OutlivesConstraintSet
,
871 crate member_constraints
: MemberConstraintSet
<'tcx
, RegionVid
>,
873 crate closure_bounds_mapping
:
874 FxHashMap
<Location
, FxHashMap
<(RegionVid
, RegionVid
), (ConstraintCategory
, Span
)>>,
876 crate type_tests
: Vec
<TypeTest
<'tcx
>>,
879 impl MirTypeckRegionConstraints
<'tcx
> {
880 fn placeholder_region(
882 infcx
: &InferCtxt
<'_
, 'tcx
>,
883 placeholder
: ty
::PlaceholderRegion
,
884 ) -> ty
::Region
<'tcx
> {
885 let placeholder_index
= self.placeholder_indices
.insert(placeholder
);
886 match self.placeholder_index_to_region
.get(placeholder_index
) {
889 let origin
= NLLRegionVariableOrigin
::Placeholder(placeholder
);
890 let region
= infcx
.next_nll_region_var_in_universe(origin
, placeholder
.universe
);
891 self.placeholder_index_to_region
.push(region
);
898 /// The `Locations` type summarizes *where* region constraints are
899 /// required to hold. Normally, this is at a particular point which
900 /// created the obligation, but for constraints that the user gave, we
901 /// want the constraint to hold at all points.
902 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
904 /// Indicates that a type constraint should always be true. This
905 /// is particularly important in the new borrowck analysis for
906 /// things like the type of the return slot. Consider this
910 /// fn foo<'a>(x: &'a u32) -> &'a u32 {
912 /// return &y; // error
916 /// Here, we wind up with the signature from the return type being
917 /// something like `&'1 u32` where `'1` is a universal region. But
918 /// the type of the return slot `_0` is something like `&'2 u32`
919 /// where `'2` is an existential region variable. The type checker
920 /// requires that `&'2 u32 = &'1 u32` -- but at what point? In the
921 /// older NLL analysis, we required this only at the entry point
922 /// to the function. By the nature of the constraints, this wound
923 /// up propagating to all points reachable from start (because
924 /// `'1` -- as a universal region -- is live everywhere). In the
925 /// newer analysis, though, this doesn't work: `_0` is considered
926 /// dead at the start (it has no usable value) and hence this type
927 /// equality is basically a no-op. Then, later on, when we do `_0
928 /// = &'3 y`, that region `'3` never winds up related to the
929 /// universal region `'1` and hence no error occurs. Therefore, we
930 /// use Locations::All instead, which ensures that the `'1` and
931 /// `'2` are equal everything. We also use this for other
932 /// user-given type annotations; e.g., if the user wrote `let mut
933 /// x: &'static u32 = ...`, we would ensure that all values
934 /// assigned to `x` are of `'static` lifetime.
936 /// The span points to the place the constraint arose. For example,
937 /// it points to the type in a user-given type annotation. If
938 /// there's no sensible span then it's DUMMY_SP.
941 /// An outlives constraint that only has to hold at a single location,
942 /// usually it represents a point where references flow from one spot to
943 /// another (e.g., `x = y`)
948 pub fn from_location(&self) -> Option
<Location
> {
950 Locations
::All(_
) => None
,
951 Locations
::Single(from_location
) => Some(*from_location
),
955 /// Gets a span representing the location.
956 pub fn span(&self, body
: &Body
<'_
>) -> Span
{
958 Locations
::All(span
) => *span
,
959 Locations
::Single(l
) => body
.source_info(*l
).span
,
964 impl<'a
, 'tcx
> TypeChecker
<'a
, 'tcx
> {
966 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
967 body
: &'a Body
<'tcx
>,
968 mir_def_id
: LocalDefId
,
969 param_env
: ty
::ParamEnv
<'tcx
>,
970 region_bound_pairs
: &'a RegionBoundPairs
<'tcx
>,
971 implicit_region_bound
: ty
::Region
<'tcx
>,
972 borrowck_context
: &'a
mut BorrowCheckContext
<'a
, 'tcx
>,
973 universal_region_relations
: &'a UniversalRegionRelations
<'tcx
>,
975 let mut checker
= Self {
980 user_type_annotations
: &body
.user_type_annotations
,
983 implicit_region_bound
,
985 reported_errors
: Default
::default(),
986 universal_region_relations
,
987 opaque_type_values
: FxHashMap
::default(),
989 checker
.check_user_type_annotations();
993 /// Equate the inferred type and the annotated type for user type annotations
994 fn check_user_type_annotations(&mut self) {
996 "check_user_type_annotations: user_type_annotations={:?}",
997 self.user_type_annotations
999 for user_annotation
in self.user_type_annotations
{
1000 let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty }
= *user_annotation
;
1001 let (annotation
, _
) =
1002 self.infcx
.instantiate_canonical_with_fresh_inference_vars(span
, user_ty
);
1004 UserType
::Ty(mut ty
) => {
1005 ty
= self.normalize(ty
, Locations
::All(span
));
1007 if let Err(terr
) = self.eq_types(
1010 Locations
::All(span
),
1011 ConstraintCategory
::BoringNoLocation
,
1016 "bad user type ({:?} = {:?}): {:?}",
1023 self.prove_predicate(
1024 ty
::PredicateAtom
::WellFormed(inferred_ty
.into()).to_predicate(self.tcx()),
1025 Locations
::All(span
),
1026 ConstraintCategory
::TypeAnnotation
,
1029 UserType
::TypeOf(def_id
, user_substs
) => {
1030 if let Err(terr
) = self.fully_perform_op(
1031 Locations
::All(span
),
1032 ConstraintCategory
::BoringNoLocation
,
1033 self.param_env
.and(type_op
::ascribe_user_type
::AscribeUserType
::new(
1042 "bad user type AscribeUserType({:?}, {:?} {:?}): {:?}",
1054 /// Given some operation `op` that manipulates types, proves
1055 /// predicates, or otherwise uses the inference context, executes
1056 /// `op` and then executes all the further obligations that `op`
1057 /// returns. This will yield a set of outlives constraints amongst
1058 /// regions which are extracted and stored as having occurred at
1061 /// **Any `rustc_infer::infer` operations that might generate region
1062 /// constraints should occur within this method so that those
1063 /// constraints can be properly localized!**
1064 fn fully_perform_op
<R
>(
1066 locations
: Locations
,
1067 category
: ConstraintCategory
,
1068 op
: impl type_op
::TypeOp
<'tcx
, Output
= R
>,
1070 let (r
, opt_data
) = op
.fully_perform(self.infcx
)?
;
1072 if let Some(data
) = &opt_data
{
1073 self.push_region_constraints(locations
, category
, data
);
1079 fn push_region_constraints(
1081 locations
: Locations
,
1082 category
: ConstraintCategory
,
1083 data
: &QueryRegionConstraints
<'tcx
>,
1085 debug
!("push_region_constraints: constraints generated at {:?} are {:#?}", locations
, data
);
1087 constraint_conversion
::ConstraintConversion
::new(
1089 self.borrowck_context
.universal_regions
,
1090 self.region_bound_pairs
,
1091 Some(self.implicit_region_bound
),
1095 &mut self.borrowck_context
.constraints
,
1100 /// Convenient wrapper around `relate_tys::relate_types` -- see
1101 /// that fn for docs.
1107 locations
: Locations
,
1108 category
: ConstraintCategory
,
1110 relate_tys
::relate_types(
1117 Some(self.borrowck_context
),
1125 locations
: Locations
,
1126 category
: ConstraintCategory
,
1128 self.relate_types(sub
, ty
::Variance
::Covariant
, sup
, locations
, category
)
1131 /// Try to relate `sub <: sup`; if this fails, instantiate opaque
1132 /// variables in `sub` with their inferred definitions and try
1133 /// again. This is used for opaque types in places (e.g., `let x:
1134 /// impl Foo = ..`).
1135 fn sub_types_or_anon(
1139 locations
: Locations
,
1140 category
: ConstraintCategory
,
1142 if let Err(terr
) = self.sub_types(sub
, sup
, locations
, category
) {
1143 if let ty
::Opaque(..) = sup
.kind() {
1144 // When you have `let x: impl Foo = ...` in a closure,
1145 // the resulting inferend values are stored with the
1146 // def-id of the base function.
1148 self.tcx().closure_base_def_id(self.mir_def_id
.to_def_id()).expect_local();
1149 return self.eq_opaque_type_and_type(sub
, sup
, parent_def_id
, locations
, category
);
1161 locations
: Locations
,
1162 category
: ConstraintCategory
,
1164 self.relate_types(a
, ty
::Variance
::Invariant
, b
, locations
, category
)
1167 fn relate_type_and_user_type(
1171 user_ty
: &UserTypeProjection
,
1172 locations
: Locations
,
1173 category
: ConstraintCategory
,
1176 "relate_type_and_user_type(a={:?}, v={:?}, user_ty={:?}, locations={:?})",
1177 a
, v
, user_ty
, locations
,
1180 let annotated_type
= self.user_type_annotations
[user_ty
.base
].inferred_ty
;
1181 let mut curr_projected_ty
= PlaceTy
::from_ty(annotated_type
);
1183 let tcx
= self.infcx
.tcx
;
1185 for proj
in &user_ty
.projs
{
1186 let projected_ty
= curr_projected_ty
.projection_ty_core(
1190 |this
, field
, &()| {
1191 let ty
= this
.field_ty(tcx
, field
);
1192 self.normalize(ty
, locations
)
1195 curr_projected_ty
= projected_ty
;
1198 "user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
1199 user_ty
.base
, annotated_type
, user_ty
.projs
, curr_projected_ty
1202 let ty
= curr_projected_ty
.ty
;
1203 self.relate_types(a
, v
, ty
, locations
, category
)?
;
1208 fn eq_opaque_type_and_type(
1210 revealed_ty
: Ty
<'tcx
>,
1212 anon_owner_def_id
: LocalDefId
,
1213 locations
: Locations
,
1214 category
: ConstraintCategory
,
1217 "eq_opaque_type_and_type( \
1220 revealed_ty
, anon_ty
1223 // Fast path for the common case.
1224 if !anon_ty
.has_opaque_types() {
1225 if let Err(terr
) = self.eq_types(anon_ty
, revealed_ty
, locations
, category
) {
1229 "eq_opaque_type_and_type: `{:?}=={:?}` failed with `{:?}`",
1238 let infcx
= self.infcx
;
1239 let tcx
= infcx
.tcx
;
1240 let param_env
= self.param_env
;
1241 let body
= self.body
;
1242 let concrete_opaque_types
= &tcx
.typeck(anon_owner_def_id
).concrete_opaque_types
;
1243 let mut opaque_type_values
= Vec
::new();
1245 debug
!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id
);
1246 let opaque_type_map
= self.fully_perform_op(
1251 let mut obligations
= ObligationAccumulator
::default();
1253 let dummy_body_id
= hir
::CRATE_HIR_ID
;
1254 let (output_ty
, opaque_type_map
) =
1255 obligations
.add(infcx
.instantiate_opaque_types(
1260 locations
.span(body
),
1263 "eq_opaque_type_and_type: \
1264 instantiated output_ty={:?} \
1265 opaque_type_map={:#?} \
1267 output_ty
, opaque_type_map
, revealed_ty
1269 // Make sure that the inferred types are well-formed. I'm
1270 // not entirely sure this is needed (the HIR type check
1271 // didn't do this) but it seems sensible to prevent opaque
1272 // types hiding ill-formed types.
1273 obligations
.obligations
.push(traits
::Obligation
::new(
1274 ObligationCause
::dummy(),
1276 ty
::PredicateAtom
::WellFormed(revealed_ty
.into()).to_predicate(infcx
.tcx
),
1280 .at(&ObligationCause
::dummy(), param_env
)
1281 .eq(output_ty
, revealed_ty
)?
,
1284 for (&opaque_def_id
, opaque_decl
) in &opaque_type_map
{
1285 let resolved_ty
= infcx
.resolve_vars_if_possible(&opaque_decl
.concrete_ty
);
1286 let concrete_is_opaque
= if let ty
::Opaque(def_id
, _
) = resolved_ty
.kind() {
1287 *def_id
== opaque_def_id
1291 let opaque_defn_ty
= match concrete_opaque_types
.get(&opaque_def_id
) {
1293 if !concrete_is_opaque
{
1294 tcx
.sess
.delay_span_bug(
1297 "Non-defining use of {:?} with revealed type",
1304 Some(opaque_defn_ty
) => opaque_defn_ty
,
1306 debug
!("opaque_defn_ty = {:?}", opaque_defn_ty
);
1307 let subst_opaque_defn_ty
=
1308 opaque_defn_ty
.concrete_type
.subst(tcx
, opaque_decl
.substs
);
1309 let renumbered_opaque_defn_ty
=
1310 renumber
::renumber_regions(infcx
, &subst_opaque_defn_ty
);
1313 "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}",
1314 opaque_decl
.concrete_ty
, resolved_ty
, renumbered_opaque_defn_ty
,
1317 if !concrete_is_opaque
{
1318 // Equate concrete_ty (an inference variable) with
1319 // the renumbered type from typeck.
1322 .at(&ObligationCause
::dummy(), param_env
)
1323 .eq(opaque_decl
.concrete_ty
, renumbered_opaque_defn_ty
)?
,
1325 opaque_type_values
.push((
1327 ty
::ResolvedOpaqueTy
{
1328 concrete_type
: renumbered_opaque_defn_ty
,
1329 substs
: opaque_decl
.substs
,
1333 // We're using an opaque `impl Trait` type without
1334 // 'revealing' it. For example, code like this:
1336 // type Foo = impl Debug;
1337 // fn foo1() -> Foo { ... }
1338 // fn foo2() -> Foo { foo1() }
1340 // In `foo2`, we're not revealing the type of `Foo` - we're
1341 // just treating it as the opaque type.
1343 // When this occurs, we do *not* want to try to equate
1344 // the concrete type with the underlying defining type
1345 // of the opaque type - this will always fail, since
1346 // the defining type of an opaque type is always
1347 // some other type (e.g. not itself)
1348 // Essentially, none of the normal obligations apply here -
1349 // we're just passing around some unknown opaque type,
1350 // without actually looking at the underlying type it
1351 // gets 'revealed' into
1353 "eq_opaque_type_and_type: non-defining use of {:?}",
1359 debug
!("eq_opaque_type_and_type: equated");
1362 value
: Some(opaque_type_map
),
1363 obligations
: obligations
.into_vec(),
1366 || "input_output".to_string(),
1370 self.opaque_type_values
.extend(opaque_type_values
);
1372 let universal_region_relations
= self.universal_region_relations
;
1374 // Finally, if we instantiated the anon types successfully, we
1375 // have to solve any bounds (e.g., `-> impl Iterator` needs to
1376 // prove that `T: Iterator` where `T` is the type we
1377 // instantiated it with).
1378 if let Some(opaque_type_map
) = opaque_type_map
{
1379 for (opaque_def_id
, opaque_decl
) in opaque_type_map
{
1380 self.fully_perform_op(
1382 ConstraintCategory
::OpaqueType
,
1385 infcx
.constrain_opaque_type(
1388 GenerateMemberConstraints
::IfNoStaticBound
,
1389 universal_region_relations
,
1391 Ok(InferOk { value: (), obligations: vec![] }
)
1393 || "opaque_type_map".to_string(),
1401 fn tcx(&self) -> TyCtxt
<'tcx
> {
1405 fn check_stmt(&mut self, body
: &Body
<'tcx
>, stmt
: &Statement
<'tcx
>, location
: Location
) {
1406 debug
!("check_stmt: {:?}", stmt
);
1407 let tcx
= self.tcx();
1409 StatementKind
::Assign(box (ref place
, ref rv
)) => {
1410 // Assignments to temporaries are not "interesting";
1411 // they are not caused by the user, but rather artifacts
1412 // of lowering. Assignments to other sorts of places *are* interesting
1414 let category
= match place
.as_local() {
1415 Some(RETURN_PLACE
) => {
1416 if let BorrowCheckContext
{
1418 UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), .. }
,
1420 } = self.borrowck_context
1422 if tcx
.is_static(*def_id
) {
1423 ConstraintCategory
::UseAsStatic
1425 ConstraintCategory
::UseAsConst
1428 ConstraintCategory
::Return(ReturnConstraint
::Normal
)
1431 Some(l
) if !body
.local_decls
[l
].is_user_variable() => {
1432 ConstraintCategory
::Boring
1434 _
=> ConstraintCategory
::Assignment
,
1437 let place_ty
= place
.ty(body
, tcx
).ty
;
1438 let place_ty
= self.normalize(place_ty
, location
);
1439 let rv_ty
= rv
.ty(body
, tcx
);
1440 let rv_ty
= self.normalize(rv_ty
, location
);
1442 self.sub_types_or_anon(rv_ty
, place_ty
, location
.to_locations(), category
)
1447 "bad assignment ({:?} = {:?}): {:?}",
1454 if let Some(annotation_index
) = self.rvalue_user_ty(rv
) {
1455 if let Err(terr
) = self.relate_type_and_user_type(
1457 ty
::Variance
::Invariant
,
1458 &UserTypeProjection { base: annotation_index, projs: vec![] }
,
1459 location
.to_locations(),
1460 ConstraintCategory
::Boring
,
1462 let annotation
= &self.user_type_annotations
[annotation_index
];
1466 "bad user type on rvalue ({:?} = {:?}): {:?}",
1474 self.check_rvalue(body
, rv
, location
);
1475 if !self.tcx().features().unsized_locals
{
1476 let trait_ref
= ty
::TraitRef
{
1477 def_id
: tcx
.require_lang_item(LangItem
::Sized
, Some(self.last_span
)),
1478 substs
: tcx
.mk_substs_trait(place_ty
, &[]),
1480 self.prove_trait_ref(
1482 location
.to_locations(),
1483 ConstraintCategory
::SizedBound
,
1487 StatementKind
::SetDiscriminant { ref place, variant_index }
=> {
1488 let place_type
= place
.ty(body
, tcx
).ty
;
1489 let adt
= match place_type
.kind() {
1490 ty
::Adt(adt
, _
) if adt
.is_enum() => adt
,
1493 stmt
.source_info
.span
,
1494 "bad set discriminant ({:?} = {:?}): lhs is not an enum",
1500 if variant_index
.as_usize() >= adt
.variants
.len() {
1502 stmt
.source_info
.span
,
1503 "bad set discriminant ({:?} = {:?}): value of of range",
1509 StatementKind
::AscribeUserType(box (ref place
, ref projection
), variance
) => {
1510 let place_ty
= place
.ty(body
, tcx
).ty
;
1511 if let Err(terr
) = self.relate_type_and_user_type(
1515 Locations
::All(stmt
.source_info
.span
),
1516 ConstraintCategory
::TypeAnnotation
,
1518 let annotation
= &self.user_type_annotations
[projection
.base
];
1522 "bad type assert ({:?} <: {:?} with projections {:?}): {:?}",
1530 StatementKind
::FakeRead(..)
1531 | StatementKind
::StorageLive(..)
1532 | StatementKind
::StorageDead(..)
1533 | StatementKind
::LlvmInlineAsm { .. }
1534 | StatementKind
::Retag { .. }
1535 | StatementKind
::Coverage(..)
1536 | StatementKind
::Nop
=> {}
1540 fn check_terminator(
1543 term
: &Terminator
<'tcx
>,
1544 term_location
: Location
,
1546 debug
!("check_terminator: {:?}", term
);
1547 let tcx
= self.tcx();
1549 TerminatorKind
::Goto { .. }
1550 | TerminatorKind
::Resume
1551 | TerminatorKind
::Abort
1552 | TerminatorKind
::Return
1553 | TerminatorKind
::GeneratorDrop
1554 | TerminatorKind
::Unreachable
1555 | TerminatorKind
::Drop { .. }
1556 | TerminatorKind
::FalseEdge { .. }
1557 | TerminatorKind
::FalseUnwind { .. }
1558 | TerminatorKind
::InlineAsm { .. }
=> {
1559 // no checks needed for these
1562 TerminatorKind
::DropAndReplace { ref place, ref value, target: _, unwind: _ }
=> {
1563 let place_ty
= place
.ty(body
, tcx
).ty
;
1564 let rv_ty
= value
.ty(body
, tcx
);
1566 let locations
= term_location
.to_locations();
1568 self.sub_types(rv_ty
, place_ty
, locations
, ConstraintCategory
::Assignment
)
1573 "bad DropAndReplace ({:?} = {:?}): {:?}",
1580 TerminatorKind
::SwitchInt { ref discr, switch_ty, .. }
=> {
1581 let discr_ty
= discr
.ty(body
, tcx
);
1582 if let Err(terr
) = self.sub_types(
1585 term_location
.to_locations(),
1586 ConstraintCategory
::Assignment
,
1591 "bad SwitchInt ({:?} on {:?}): {:?}",
1597 if !switch_ty
.is_integral() && !switch_ty
.is_char() && !switch_ty
.is_bool() {
1598 span_mirbug
!(self, term
, "bad SwitchInt discr ty {:?}", switch_ty
);
1600 // FIXME: check the values
1602 TerminatorKind
::Call { ref func, ref args, ref destination, from_hir_call, .. }
=> {
1603 let func_ty
= func
.ty(body
, tcx
);
1604 debug
!("check_terminator: call, func_ty={:?}", func_ty
);
1605 let sig
= match func_ty
.kind() {
1606 ty
::FnDef(..) | ty
::FnPtr(_
) => func_ty
.fn_sig(tcx
),
1608 span_mirbug
!(self, term
, "call to non-function {:?}", func_ty
);
1612 let (sig
, map
) = self.infcx
.replace_bound_vars_with_fresh_vars(
1613 term
.source_info
.span
,
1614 LateBoundRegionConversionTime
::FnCall
,
1617 let sig
= self.normalize(sig
, term_location
);
1618 self.check_call_dest(body
, term
, &sig
, destination
, term_location
);
1620 self.prove_predicates(
1621 sig
.inputs_and_output
.iter().map(|ty
| ty
::PredicateAtom
::WellFormed(ty
.into())),
1622 term_location
.to_locations(),
1623 ConstraintCategory
::Boring
,
1626 // The ordinary liveness rules will ensure that all
1627 // regions in the type of the callee are live here. We
1628 // then further constrain the late-bound regions that
1629 // were instantiated at the call site to be live as
1630 // well. The resulting is that all the input (and
1631 // output) types in the signature must be live, since
1632 // all the inputs that fed into it were live.
1633 for &late_bound_region
in map
.values() {
1635 self.borrowck_context
.universal_regions
.to_region_vid(late_bound_region
);
1636 self.borrowck_context
1638 .liveness_constraints
1639 .add_element(region_vid
, term_location
);
1642 self.check_call_inputs(body
, term
, &sig
, args
, term_location
, from_hir_call
);
1644 TerminatorKind
::Assert { ref cond, ref msg, .. }
=> {
1645 let cond_ty
= cond
.ty(body
, tcx
);
1646 if cond_ty
!= tcx
.types
.bool
{
1647 span_mirbug
!(self, term
, "bad Assert ({:?}, not bool", cond_ty
);
1650 if let AssertKind
::BoundsCheck { ref len, ref index }
= *msg
{
1651 if len
.ty(body
, tcx
) != tcx
.types
.usize {
1652 span_mirbug
!(self, len
, "bounds-check length non-usize {:?}", len
)
1654 if index
.ty(body
, tcx
) != tcx
.types
.usize {
1655 span_mirbug
!(self, index
, "bounds-check index non-usize {:?}", index
)
1659 TerminatorKind
::Yield { ref value, .. }
=> {
1660 let value_ty
= value
.ty(body
, tcx
);
1661 match body
.yield_ty
{
1662 None
=> span_mirbug
!(self, term
, "yield in non-generator"),
1664 if let Err(terr
) = self.sub_types(
1667 term_location
.to_locations(),
1668 ConstraintCategory
::Yield
,
1673 "type of yield value is {:?}, but the yield type is {:?}: {:?}",
1688 term
: &Terminator
<'tcx
>,
1689 sig
: &ty
::FnSig
<'tcx
>,
1690 destination
: &Option
<(Place
<'tcx
>, BasicBlock
)>,
1691 term_location
: Location
,
1693 let tcx
= self.tcx();
1694 match *destination
{
1695 Some((ref dest
, _target_block
)) => {
1696 let dest_ty
= dest
.ty(body
, tcx
).ty
;
1697 let dest_ty
= self.normalize(dest_ty
, term_location
);
1698 let category
= match dest
.as_local() {
1699 Some(RETURN_PLACE
) => {
1700 if let BorrowCheckContext
{
1702 UniversalRegions { defining_ty: DefiningTy::Const(def_id, _), .. }
,
1704 } = self.borrowck_context
1706 if tcx
.is_static(*def_id
) {
1707 ConstraintCategory
::UseAsStatic
1709 ConstraintCategory
::UseAsConst
1712 ConstraintCategory
::Return(ReturnConstraint
::Normal
)
1715 Some(l
) if !body
.local_decls
[l
].is_user_variable() => {
1716 ConstraintCategory
::Boring
1718 _
=> ConstraintCategory
::Assignment
,
1721 let locations
= term_location
.to_locations();
1724 self.sub_types_or_anon(sig
.output(), dest_ty
, locations
, category
)
1729 "call dest mismatch ({:?} <- {:?}): {:?}",
1736 // When `#![feature(unsized_locals)]` is not enabled,
1737 // this check is done at `check_local`.
1738 if self.tcx().features().unsized_locals
{
1739 let span
= term
.source_info
.span
;
1740 self.ensure_place_sized(dest_ty
, span
);
1744 if !sig
.output().conservative_is_privately_uninhabited(self.tcx()) {
1745 span_mirbug
!(self, term
, "call to converging function {:?} w/o dest", sig
);
1751 fn check_call_inputs(
1754 term
: &Terminator
<'tcx
>,
1755 sig
: &ty
::FnSig
<'tcx
>,
1756 args
: &[Operand
<'tcx
>],
1757 term_location
: Location
,
1758 from_hir_call
: bool
,
1760 debug
!("check_call_inputs({:?}, {:?})", sig
, args
);
1761 if args
.len() < sig
.inputs().len() || (args
.len() > sig
.inputs().len() && !sig
.c_variadic
) {
1762 span_mirbug
!(self, term
, "call to {:?} with wrong # of args", sig
);
1764 for (n
, (fn_arg
, op_arg
)) in sig
.inputs().iter().zip(args
).enumerate() {
1765 let op_arg_ty
= op_arg
.ty(body
, self.tcx());
1766 let op_arg_ty
= self.normalize(op_arg_ty
, term_location
);
1767 let category
= if from_hir_call
{
1768 ConstraintCategory
::CallArgument
1770 ConstraintCategory
::Boring
1773 self.sub_types(op_arg_ty
, fn_arg
, term_location
.to_locations(), category
)
1778 "bad arg #{:?} ({:?} <- {:?}): {:?}",
1788 fn check_iscleanup(&mut self, body
: &Body
<'tcx
>, block_data
: &BasicBlockData
<'tcx
>) {
1789 let is_cleanup
= block_data
.is_cleanup
;
1790 self.last_span
= block_data
.terminator().source_info
.span
;
1791 match block_data
.terminator().kind
{
1792 TerminatorKind
::Goto { target }
=> {
1793 self.assert_iscleanup(body
, block_data
, target
, is_cleanup
)
1795 TerminatorKind
::SwitchInt { ref targets, .. }
=> {
1796 for target
in targets
{
1797 self.assert_iscleanup(body
, block_data
, *target
, is_cleanup
);
1800 TerminatorKind
::Resume
=> {
1802 span_mirbug
!(self, block_data
, "resume on non-cleanup block!")
1805 TerminatorKind
::Abort
=> {
1807 span_mirbug
!(self, block_data
, "abort on non-cleanup block!")
1810 TerminatorKind
::Return
=> {
1812 span_mirbug
!(self, block_data
, "return on cleanup block")
1815 TerminatorKind
::GeneratorDrop { .. }
=> {
1817 span_mirbug
!(self, block_data
, "generator_drop in cleanup block")
1820 TerminatorKind
::Yield { resume, drop, .. }
=> {
1822 span_mirbug
!(self, block_data
, "yield in cleanup block")
1824 self.assert_iscleanup(body
, block_data
, resume
, is_cleanup
);
1825 if let Some(drop
) = drop
{
1826 self.assert_iscleanup(body
, block_data
, drop
, is_cleanup
);
1829 TerminatorKind
::Unreachable
=> {}
1830 TerminatorKind
::Drop { target, unwind, .. }
1831 | TerminatorKind
::DropAndReplace { target, unwind, .. }
1832 | TerminatorKind
::Assert { target, cleanup: unwind, .. }
=> {
1833 self.assert_iscleanup(body
, block_data
, target
, is_cleanup
);
1834 if let Some(unwind
) = unwind
{
1836 span_mirbug
!(self, block_data
, "unwind on cleanup block")
1838 self.assert_iscleanup(body
, block_data
, unwind
, true);
1841 TerminatorKind
::Call { ref destination, cleanup, .. }
=> {
1842 if let &Some((_
, target
)) = destination
{
1843 self.assert_iscleanup(body
, block_data
, target
, is_cleanup
);
1845 if let Some(cleanup
) = cleanup
{
1847 span_mirbug
!(self, block_data
, "cleanup on cleanup block")
1849 self.assert_iscleanup(body
, block_data
, cleanup
, true);
1852 TerminatorKind
::FalseEdge { real_target, imaginary_target }
=> {
1853 self.assert_iscleanup(body
, block_data
, real_target
, is_cleanup
);
1854 self.assert_iscleanup(body
, block_data
, imaginary_target
, is_cleanup
);
1856 TerminatorKind
::FalseUnwind { real_target, unwind }
=> {
1857 self.assert_iscleanup(body
, block_data
, real_target
, is_cleanup
);
1858 if let Some(unwind
) = unwind
{
1860 span_mirbug
!(self, block_data
, "cleanup in cleanup block via false unwind");
1862 self.assert_iscleanup(body
, block_data
, unwind
, true);
1865 TerminatorKind
::InlineAsm { ref destination, .. }
=> {
1866 if let &Some(target
) = destination
{
1867 self.assert_iscleanup(body
, block_data
, target
, is_cleanup
);
1873 fn assert_iscleanup(
1876 ctxt
: &dyn fmt
::Debug
,
1880 if body
[bb
].is_cleanup
!= iscleanuppad
{
1881 span_mirbug
!(self, ctxt
, "cleanuppad mismatch: {:?} should be {:?}", bb
, iscleanuppad
);
1885 fn check_local(&mut self, body
: &Body
<'tcx
>, local
: Local
, local_decl
: &LocalDecl
<'tcx
>) {
1886 match body
.local_kind(local
) {
1887 LocalKind
::ReturnPointer
| LocalKind
::Arg
=> {
1888 // return values of normal functions are required to be
1889 // sized by typeck, but return values of ADT constructors are
1890 // not because we don't include a `Self: Sized` bounds on them.
1892 // Unbound parts of arguments were never required to be Sized
1893 // - maybe we should make that a warning.
1896 LocalKind
::Var
| LocalKind
::Temp
=> {}
1899 // When `#![feature(unsized_locals)]` is enabled, only function calls
1900 // and nullary ops are checked in `check_call_dest`.
1901 if !self.tcx().features().unsized_locals
{
1902 let span
= local_decl
.source_info
.span
;
1903 let ty
= local_decl
.ty
;
1904 self.ensure_place_sized(ty
, span
);
1908 fn ensure_place_sized(&mut self, ty
: Ty
<'tcx
>, span
: Span
) {
1909 let tcx
= self.tcx();
1911 // Erase the regions from `ty` to get a global type. The
1912 // `Sized` bound in no way depends on precise regions, so this
1913 // shouldn't affect `is_sized`.
1914 let erased_ty
= tcx
.erase_regions(&ty
);
1915 if !erased_ty
.is_sized(tcx
.at(span
), self.param_env
) {
1916 // in current MIR construction, all non-control-flow rvalue
1917 // expressions evaluate through `as_temp` or `into` a return
1918 // slot or local, so to find all unsized rvalues it is enough
1919 // to check all temps, return slots and locals.
1920 if self.reported_errors
.replace((ty
, span
)).is_none() {
1921 let mut diag
= struct_span_err
!(
1925 "cannot move a value of type {0}: the size of {0} \
1926 cannot be statically determined",
1930 // While this is located in `nll::typeck` this error is not
1931 // an NLL error, it's a required check to prevent creation
1932 // of unsized rvalues in certain cases:
1933 // * operand of a box expression
1934 // * callee in a call expression
1940 fn aggregate_field_ty(
1942 ak
: &AggregateKind
<'tcx
>,
1945 ) -> Result
<Ty
<'tcx
>, FieldAccessError
> {
1946 let tcx
= self.tcx();
1949 AggregateKind
::Adt(def
, variant_index
, substs
, _
, active_field_index
) => {
1950 let variant
= &def
.variants
[variant_index
];
1951 let adj_field_index
= active_field_index
.unwrap_or(field_index
);
1952 if let Some(field
) = variant
.fields
.get(adj_field_index
) {
1953 Ok(self.normalize(field
.ty(tcx
, substs
), location
))
1955 Err(FieldAccessError
::OutOfRange { field_count: variant.fields.len() }
)
1958 AggregateKind
::Closure(_
, substs
) => {
1959 match substs
.as_closure().upvar_tys().nth(field_index
) {
1961 None
=> Err(FieldAccessError
::OutOfRange
{
1962 field_count
: substs
.as_closure().upvar_tys().count(),
1966 AggregateKind
::Generator(_
, substs
, _
) => {
1967 // It doesn't make sense to look at a field beyond the prefix;
1968 // these require a variant index, and are not initialized in
1969 // aggregate rvalues.
1970 match substs
.as_generator().prefix_tys().nth(field_index
) {
1972 None
=> Err(FieldAccessError
::OutOfRange
{
1973 field_count
: substs
.as_generator().prefix_tys().count(),
1977 AggregateKind
::Array(ty
) => Ok(ty
),
1978 AggregateKind
::Tuple
=> {
1979 unreachable
!("This should have been covered in check_rvalues");
1984 fn check_rvalue(&mut self, body
: &Body
<'tcx
>, rvalue
: &Rvalue
<'tcx
>, location
: Location
) {
1985 let tcx
= self.tcx();
1988 Rvalue
::Aggregate(ak
, ops
) => {
1989 self.check_aggregate_rvalue(&body
, rvalue
, ak
, ops
, location
)
1992 Rvalue
::Repeat(operand
, len
) => {
1993 // If the length cannot be evaluated we must assume that the length can be larger
1995 // If the length is larger than 1, the repeat expression will need to copy the
1996 // element, so we require the `Copy` trait.
1997 if len
.try_eval_usize(tcx
, self.param_env
).map_or(true, |len
| len
> 1) {
1998 if let Operand
::Move(_
) = operand
{
1999 // While this is located in `nll::typeck` this error is not an NLL error, it's
2000 // a required check to make sure that repeated elements implement `Copy`.
2001 let span
= body
.source_info(location
).span
;
2002 let ty
= operand
.ty(body
, tcx
);
2003 if !self.infcx
.type_is_copy_modulo_regions(self.param_env
, ty
, span
) {
2004 let ccx
= ConstCx
::new_with_param_env(
2010 // To determine if `const_in_array_repeat_expressions` feature gate should
2011 // be mentioned, need to check if the rvalue is promotable.
2012 let should_suggest
=
2013 should_suggest_const_in_array_repeat_expressions_attribute(
2016 debug
!("check_rvalue: should_suggest={:?}", should_suggest
);
2018 self.infcx
.report_selection_error(
2019 &traits
::Obligation
::new(
2020 ObligationCause
::new(
2022 self.tcx().hir().local_def_id_to_hir_id(self.mir_def_id
),
2023 traits
::ObligationCauseCode
::RepeatVec(should_suggest
),
2026 ty
::Binder
::bind(ty
::TraitRef
::new(
2027 self.tcx().require_lang_item(
2029 Some(self.last_span
),
2031 tcx
.mk_substs_trait(ty
, &[]),
2034 .to_predicate(self.tcx()),
2036 &traits
::SelectionError
::Unimplemented
,
2045 Rvalue
::NullaryOp(_
, ty
) => {
2046 // Even with unsized locals cannot box an unsized value.
2047 if self.tcx().features().unsized_locals
{
2048 let span
= body
.source_info(location
).span
;
2049 self.ensure_place_sized(ty
, span
);
2052 let trait_ref
= ty
::TraitRef
{
2053 def_id
: tcx
.require_lang_item(LangItem
::Sized
, Some(self.last_span
)),
2054 substs
: tcx
.mk_substs_trait(ty
, &[]),
2057 self.prove_trait_ref(
2059 location
.to_locations(),
2060 ConstraintCategory
::SizedBound
,
2064 Rvalue
::Cast(cast_kind
, op
, ty
) => {
2066 CastKind
::Pointer(PointerCast
::ReifyFnPointer
) => {
2067 let fn_sig
= op
.ty(body
, tcx
).fn_sig(tcx
);
2069 // The type that we see in the fcx is like
2070 // `foo::<'a, 'b>`, where `foo` is the path to a
2071 // function definition. When we extract the
2072 // signature, it comes from the `fn_sig` query,
2073 // and hence may contain unnormalized results.
2074 let fn_sig
= self.normalize(fn_sig
, location
);
2076 let ty_fn_ptr_from
= tcx
.mk_fn_ptr(fn_sig
);
2078 if let Err(terr
) = self.eq_types(
2081 location
.to_locations(),
2082 ConstraintCategory
::Cast
,
2087 "equating {:?} with {:?} yields {:?}",
2095 CastKind
::Pointer(PointerCast
::ClosureFnPointer(unsafety
)) => {
2096 let sig
= match op
.ty(body
, tcx
).kind() {
2097 ty
::Closure(_
, substs
) => substs
.as_closure().sig(),
2100 let ty_fn_ptr_from
= tcx
.mk_fn_ptr(tcx
.signature_unclosure(sig
, *unsafety
));
2102 if let Err(terr
) = self.eq_types(
2105 location
.to_locations(),
2106 ConstraintCategory
::Cast
,
2111 "equating {:?} with {:?} yields {:?}",
2119 CastKind
::Pointer(PointerCast
::UnsafeFnPointer
) => {
2120 let fn_sig
= op
.ty(body
, tcx
).fn_sig(tcx
);
2122 // The type that we see in the fcx is like
2123 // `foo::<'a, 'b>`, where `foo` is the path to a
2124 // function definition. When we extract the
2125 // signature, it comes from the `fn_sig` query,
2126 // and hence may contain unnormalized results.
2127 let fn_sig
= self.normalize(fn_sig
, location
);
2129 let ty_fn_ptr_from
= tcx
.safe_to_unsafe_fn_ty(fn_sig
);
2131 if let Err(terr
) = self.eq_types(
2134 location
.to_locations(),
2135 ConstraintCategory
::Cast
,
2140 "equating {:?} with {:?} yields {:?}",
2148 CastKind
::Pointer(PointerCast
::Unsize
) => {
2150 let trait_ref
= ty
::TraitRef
{
2152 .require_lang_item(LangItem
::CoerceUnsized
, Some(self.last_span
)),
2153 substs
: tcx
.mk_substs_trait(op
.ty(body
, tcx
), &[ty
.into()]),
2156 self.prove_trait_ref(
2158 location
.to_locations(),
2159 ConstraintCategory
::Cast
,
2163 CastKind
::Pointer(PointerCast
::MutToConstPointer
) => {
2164 let ty_from
= match op
.ty(body
, tcx
).kind() {
2165 ty
::RawPtr(ty
::TypeAndMut
{
2167 mutbl
: hir
::Mutability
::Mut
,
2173 "unexpected base type for cast {:?}",
2179 let ty_to
= match ty
.kind() {
2180 ty
::RawPtr(ty
::TypeAndMut
{
2182 mutbl
: hir
::Mutability
::Not
,
2188 "unexpected target type for cast {:?}",
2194 if let Err(terr
) = self.sub_types(
2197 location
.to_locations(),
2198 ConstraintCategory
::Cast
,
2203 "relating {:?} with {:?} yields {:?}",
2211 CastKind
::Pointer(PointerCast
::ArrayToPointer
) => {
2212 let ty_from
= op
.ty(body
, tcx
);
2214 let opt_ty_elem
= match ty_from
.kind() {
2215 ty
::RawPtr(ty
::TypeAndMut
{
2216 mutbl
: hir
::Mutability
::Not
,
2218 }) => match array_ty
.kind() {
2219 ty
::Array(ty_elem
, _
) => Some(ty_elem
),
2225 let ty_elem
= match opt_ty_elem
{
2226 Some(ty_elem
) => ty_elem
,
2231 "ArrayToPointer cast from unexpected type {:?}",
2238 let ty_to
= match ty
.kind() {
2239 ty
::RawPtr(ty
::TypeAndMut
{
2240 mutbl
: hir
::Mutability
::Not
,
2247 "ArrayToPointer cast to unexpected type {:?}",
2254 if let Err(terr
) = self.sub_types(
2257 location
.to_locations(),
2258 ConstraintCategory
::Cast
,
2263 "relating {:?} with {:?} yields {:?}",
2272 let ty_from
= op
.ty(body
, tcx
);
2273 let cast_ty_from
= CastTy
::from_ty(ty_from
);
2274 let cast_ty_to
= CastTy
::from_ty(ty
);
2275 match (cast_ty_from
, cast_ty_to
) {
2277 | (_
, None
| Some(CastTy
::FnPtr
))
2278 | (Some(CastTy
::Float
), Some(CastTy
::Ptr(_
)))
2279 | (Some(CastTy
::Ptr(_
) | CastTy
::FnPtr
), Some(CastTy
::Float
)) => {
2280 span_mirbug
!(self, rvalue
, "Invalid cast {:?} -> {:?}", ty_from
, ty
,)
2283 Some(CastTy
::Int(_
)),
2284 Some(CastTy
::Int(_
) | CastTy
::Float
| CastTy
::Ptr(_
)),
2286 | (Some(CastTy
::Float
), Some(CastTy
::Int(_
) | CastTy
::Float
))
2287 | (Some(CastTy
::Ptr(_
)), Some(CastTy
::Int(_
) | CastTy
::Ptr(_
)))
2288 | (Some(CastTy
::FnPtr
), Some(CastTy
::Int(_
) | CastTy
::Ptr(_
))) => (),
2294 Rvalue
::Ref(region
, _borrow_kind
, borrowed_place
) => {
2295 self.add_reborrow_constraint(&body
, location
, region
, borrowed_place
);
2299 BinOp
::Eq
| BinOp
::Ne
| BinOp
::Lt
| BinOp
::Le
| BinOp
::Gt
| BinOp
::Ge
,
2303 let ty_left
= left
.ty(body
, tcx
);
2304 match ty_left
.kind() {
2305 // Types with regions are comparable if they have a common super-type.
2306 ty
::RawPtr(_
) | ty
::FnPtr(_
) => {
2307 let ty_right
= right
.ty(body
, tcx
);
2308 let common_ty
= self.infcx
.next_ty_var(TypeVariableOrigin
{
2309 kind
: TypeVariableOriginKind
::MiscVariable
,
2310 span
: body
.source_info(location
).span
,
2314 ty
::Variance
::Contravariant
,
2316 location
.to_locations(),
2317 ConstraintCategory
::Boring
,
2319 .unwrap_or_else(|err
| {
2320 bug
!("Could not equate type variable with {:?}: {:?}", ty_left
, err
)
2322 if let Err(terr
) = self.relate_types(
2324 ty
::Variance
::Contravariant
,
2326 location
.to_locations(),
2327 ConstraintCategory
::Boring
,
2332 "unexpected comparison types {:?} and {:?} yields {:?}",
2339 // For types with no regions we can just check that the
2340 // both operands have the same type.
2341 ty
::Int(_
) | ty
::Uint(_
) | ty
::Bool
| ty
::Char
| ty
::Float(_
)
2342 if ty_left
== right
.ty(body
, tcx
) => {}
2343 // Other types are compared by trait methods, not by
2344 // `Rvalue::BinaryOp`.
2348 "unexpected comparison types {:?} and {:?}",
2355 Rvalue
::AddressOf(..)
2356 | Rvalue
::ThreadLocalRef(..)
2359 | Rvalue
::BinaryOp(..)
2360 | Rvalue
::CheckedBinaryOp(..)
2361 | Rvalue
::UnaryOp(..)
2362 | Rvalue
::Discriminant(..) => {}
2366 /// If this rvalue supports a user-given type annotation, then
2367 /// extract and return it. This represents the final type of the
2368 /// rvalue and will be unified with the inferred type.
2369 fn rvalue_user_ty(&self, rvalue
: &Rvalue
<'tcx
>) -> Option
<UserTypeAnnotationIndex
> {
2372 | Rvalue
::ThreadLocalRef(_
)
2373 | Rvalue
::Repeat(..)
2375 | Rvalue
::AddressOf(..)
2378 | Rvalue
::BinaryOp(..)
2379 | Rvalue
::CheckedBinaryOp(..)
2380 | Rvalue
::NullaryOp(..)
2381 | Rvalue
::UnaryOp(..)
2382 | Rvalue
::Discriminant(..) => None
,
2384 Rvalue
::Aggregate(aggregate
, _
) => match **aggregate
{
2385 AggregateKind
::Adt(_
, _
, _
, user_ty
, _
) => user_ty
,
2386 AggregateKind
::Array(_
) => None
,
2387 AggregateKind
::Tuple
=> None
,
2388 AggregateKind
::Closure(_
, _
) => None
,
2389 AggregateKind
::Generator(_
, _
, _
) => None
,
2394 fn check_aggregate_rvalue(
2397 rvalue
: &Rvalue
<'tcx
>,
2398 aggregate_kind
: &AggregateKind
<'tcx
>,
2399 operands
: &[Operand
<'tcx
>],
2402 let tcx
= self.tcx();
2404 self.prove_aggregate_predicates(aggregate_kind
, location
);
2406 if *aggregate_kind
== AggregateKind
::Tuple
{
2407 // tuple rvalue field type is always the type of the op. Nothing to check here.
2411 for (i
, operand
) in operands
.iter().enumerate() {
2412 let field_ty
= match self.aggregate_field_ty(aggregate_kind
, i
, location
) {
2413 Ok(field_ty
) => field_ty
,
2414 Err(FieldAccessError
::OutOfRange { field_count }
) => {
2418 "accessed field #{} but variant only has {}",
2425 let operand_ty
= operand
.ty(body
, tcx
);
2426 let operand_ty
= self.normalize(operand_ty
, location
);
2428 if let Err(terr
) = self.sub_types(
2431 location
.to_locations(),
2432 ConstraintCategory
::Boring
,
2437 "{:?} is not a subtype of {:?}: {:?}",
2446 /// Adds the constraints that arise from a borrow expression `&'a P` at the location `L`.
2450 /// - `location`: the location `L` where the borrow expression occurs
2451 /// - `borrow_region`: the region `'a` associated with the borrow
2452 /// - `borrowed_place`: the place `P` being borrowed
2453 fn add_reborrow_constraint(
2457 borrow_region
: ty
::Region
<'tcx
>,
2458 borrowed_place
: &Place
<'tcx
>,
2460 // These constraints are only meaningful during borrowck:
2461 let BorrowCheckContext { borrow_set, location_table, all_facts, constraints, .. }
=
2462 self.borrowck_context
;
2464 // In Polonius mode, we also push a `borrow_region` fact
2465 // linking the loan to the region (in some cases, though,
2466 // there is no loan associated with this borrow expression --
2467 // that occurs when we are borrowing an unsafe place, for
2469 if let Some(all_facts
) = all_facts
{
2470 let _prof_timer
= self.infcx
.tcx
.prof
.generic_activity("polonius_fact_generation");
2471 if let Some(borrow_index
) = borrow_set
.get_index_of(&location
) {
2472 let region_vid
= borrow_region
.to_region_vid();
2473 all_facts
.borrow_region
.push((
2476 location_table
.mid_index(location
),
2481 // If we are reborrowing the referent of another reference, we
2482 // need to add outlives relationships. In a case like `&mut
2483 // *p`, where the `p` has type `&'b mut Foo`, for example, we
2484 // need to ensure that `'b: 'a`.
2487 "add_reborrow_constraint({:?}, {:?}, {:?})",
2488 location
, borrow_region
, borrowed_place
2491 let mut cursor
= borrowed_place
.projection
.as_ref();
2492 let tcx
= self.infcx
.tcx
;
2493 let field
= path_utils
::is_upvar_field_projection(
2495 &self.borrowck_context
.upvars
,
2496 borrowed_place
.as_ref(),
2499 let category
= if let Some(field
) = field
{
2500 ConstraintCategory
::ClosureUpvar(self.borrowck_context
.upvars
[field
.index()].var_hir_id
)
2502 ConstraintCategory
::Boring
2505 while let [proj_base @
.., elem
] = cursor
{
2508 debug
!("add_reborrow_constraint - iteration {:?}", elem
);
2511 ProjectionElem
::Deref
=> {
2512 let base_ty
= Place
::ty_from(borrowed_place
.local
, proj_base
, body
, tcx
).ty
;
2514 debug
!("add_reborrow_constraint - base_ty = {:?}", base_ty
);
2515 match base_ty
.kind() {
2516 ty
::Ref(ref_region
, _
, mutbl
) => {
2517 constraints
.outlives_constraints
.push(OutlivesConstraint
{
2518 sup
: ref_region
.to_region_vid(),
2519 sub
: borrow_region
.to_region_vid(),
2520 locations
: location
.to_locations(),
2525 hir
::Mutability
::Not
=> {
2526 // Immutable reference. We don't need the base
2527 // to be valid for the entire lifetime of
2531 hir
::Mutability
::Mut
=> {
2532 // Mutable reference. We *do* need the base
2533 // to be valid, because after the base becomes
2534 // invalid, someone else can use our mutable deref.
2536 // This is in order to make the following function
2539 // fn unsafe_deref<'a, 'b>(x: &'a &'b mut T) -> &'b mut T {
2544 // As otherwise you could clone `&mut T` using the
2545 // following function:
2547 // fn bad(x: &mut T) -> (&mut T, &mut T) {
2548 // let my_clone = unsafe_deref(&'a x);
2557 // deref of raw pointer, guaranteed to be valid
2560 ty
::Adt(def
, _
) if def
.is_box() => {
2561 // deref of `Box`, need the base to be valid - propagate
2563 _
=> bug
!("unexpected deref ty {:?} in {:?}", base_ty
, borrowed_place
),
2566 ProjectionElem
::Field(..)
2567 | ProjectionElem
::Downcast(..)
2568 | ProjectionElem
::Index(..)
2569 | ProjectionElem
::ConstantIndex { .. }
2570 | ProjectionElem
::Subslice { .. }
=> {
2571 // other field access
2577 fn prove_aggregate_predicates(
2579 aggregate_kind
: &AggregateKind
<'tcx
>,
2582 let tcx
= self.tcx();
2585 "prove_aggregate_predicates(aggregate_kind={:?}, location={:?})",
2586 aggregate_kind
, location
2589 let instantiated_predicates
= match aggregate_kind
{
2590 AggregateKind
::Adt(def
, _
, substs
, _
, _
) => {
2591 tcx
.predicates_of(def
.did
).instantiate(tcx
, substs
)
2594 // For closures, we have some **extra requirements** we
2596 // have to check. In particular, in their upvars and
2597 // signatures, closures often reference various regions
2598 // from the surrounding function -- we call those the
2599 // closure's free regions. When we borrow-check (and hence
2600 // region-check) closures, we may find that the closure
2601 // requires certain relationships between those free
2602 // regions. However, because those free regions refer to
2603 // portions of the CFG of their caller, the closure is not
2604 // in a position to verify those relationships. In that
2605 // case, the requirements get "propagated" to us, and so
2606 // we have to solve them here where we instantiate the
2609 // Despite the opacity of the previous parapgrah, this is
2610 // actually relatively easy to understand in terms of the
2611 // desugaring. A closure gets desugared to a struct, and
2612 // these extra requirements are basically like where
2613 // clauses on the struct.
2614 AggregateKind
::Closure(def_id
, substs
)
2615 | AggregateKind
::Generator(def_id
, substs
, _
) => {
2616 self.prove_closure_bounds(tcx
, def_id
.expect_local(), substs
, location
)
2619 AggregateKind
::Array(_
) | AggregateKind
::Tuple
=> ty
::InstantiatedPredicates
::empty(),
2622 self.normalize_and_prove_instantiated_predicates(
2623 instantiated_predicates
,
2624 location
.to_locations(),
2628 fn prove_closure_bounds(
2632 substs
: SubstsRef
<'tcx
>,
2634 ) -> ty
::InstantiatedPredicates
<'tcx
> {
2635 if let Some(ref closure_region_requirements
) = tcx
.mir_borrowck(def_id
).closure_requirements
2637 let closure_constraints
= QueryRegionConstraints
{
2638 outlives
: closure_region_requirements
.apply_requirements(
2644 // Presently, closures never propagate member
2645 // constraints to their parents -- they are enforced
2646 // locally. This is largely a non-issue as member
2647 // constraints only come from `-> impl Trait` and
2648 // friends which don't appear (thus far...) in
2650 member_constraints
: vec
![],
2653 let bounds_mapping
= closure_constraints
2657 .filter_map(|(idx
, constraint
)| {
2658 let ty
::OutlivesPredicate(k1
, r2
) =
2659 constraint
.no_bound_vars().unwrap_or_else(|| {
2660 bug
!("query_constraint {:?} contained bound vars", constraint
,);
2664 GenericArgKind
::Lifetime(r1
) => {
2665 // constraint is r1: r2
2666 let r1_vid
= self.borrowck_context
.universal_regions
.to_region_vid(r1
);
2667 let r2_vid
= self.borrowck_context
.universal_regions
.to_region_vid(r2
);
2668 let outlives_requirements
=
2669 &closure_region_requirements
.outlives_requirements
[idx
];
2672 (outlives_requirements
.category
, outlives_requirements
.blame_span
),
2675 GenericArgKind
::Type(_
) | GenericArgKind
::Const(_
) => None
,
2683 .closure_bounds_mapping
2684 .insert(location
, bounds_mapping
);
2685 assert
!(existing
.is_none(), "Multiple closures at the same location.");
2687 self.push_region_constraints(
2688 location
.to_locations(),
2689 ConstraintCategory
::ClosureBounds
,
2690 &closure_constraints
,
2694 tcx
.predicates_of(def_id
).instantiate(tcx
, substs
)
2699 trait_ref
: ty
::TraitRef
<'tcx
>,
2700 locations
: Locations
,
2701 category
: ConstraintCategory
,
2703 self.prove_predicates(
2704 Some(ty
::PredicateAtom
::Trait(
2705 ty
::TraitPredicate { trait_ref }
,
2706 hir
::Constness
::NotConst
,
2713 fn normalize_and_prove_instantiated_predicates(
2715 instantiated_predicates
: ty
::InstantiatedPredicates
<'tcx
>,
2716 locations
: Locations
,
2718 for predicate
in instantiated_predicates
.predicates
{
2719 let predicate
= self.normalize(predicate
, locations
);
2720 self.prove_predicate(predicate
, locations
, ConstraintCategory
::Boring
);
2724 fn prove_predicates(
2726 predicates
: impl IntoIterator
<Item
= impl ToPredicate
<'tcx
>>,
2727 locations
: Locations
,
2728 category
: ConstraintCategory
,
2730 for predicate
in predicates
{
2731 let predicate
= predicate
.to_predicate(self.tcx());
2732 debug
!("prove_predicates(predicate={:?}, locations={:?})", predicate
, locations
,);
2734 self.prove_predicate(predicate
, locations
, category
);
2740 predicate
: ty
::Predicate
<'tcx
>,
2741 locations
: Locations
,
2742 category
: ConstraintCategory
,
2744 debug
!("prove_predicate(predicate={:?}, location={:?})", predicate
, locations
,);
2746 let param_env
= self.param_env
;
2747 self.fully_perform_op(
2750 param_env
.and(type_op
::prove_predicate
::ProvePredicate
::new(predicate
)),
2752 .unwrap_or_else(|NoSolution
| {
2753 span_mirbug
!(self, NoSolution
, "could not prove {:?}", predicate
);
2757 fn typeck_mir(&mut self, body
: &Body
<'tcx
>) {
2758 self.last_span
= body
.span
;
2759 debug
!("run_on_mir: {:?}", body
.span
);
2761 for (local
, local_decl
) in body
.local_decls
.iter_enumerated() {
2762 self.check_local(&body
, local
, local_decl
);
2765 for (block
, block_data
) in body
.basic_blocks().iter_enumerated() {
2766 let mut location
= Location { block, statement_index: 0 }
;
2767 for stmt
in &block_data
.statements
{
2768 if !stmt
.source_info
.span
.is_dummy() {
2769 self.last_span
= stmt
.source_info
.span
;
2771 self.check_stmt(body
, stmt
, location
);
2772 location
.statement_index
+= 1;
2775 self.check_terminator(&body
, block_data
.terminator(), location
);
2776 self.check_iscleanup(&body
, block_data
);
2780 fn normalize
<T
>(&mut self, value
: T
, location
: impl NormalizeLocation
) -> T
2782 T
: type_op
::normalize
::Normalizable
<'tcx
> + Copy
+ 'tcx
,
2784 debug
!("normalize(value={:?}, location={:?})", value
, location
);
2785 let param_env
= self.param_env
;
2786 self.fully_perform_op(
2787 location
.to_locations(),
2788 ConstraintCategory
::Boring
,
2789 param_env
.and(type_op
::normalize
::Normalize
::new(value
)),
2791 .unwrap_or_else(|NoSolution
| {
2792 span_mirbug
!(self, NoSolution
, "failed to normalize `{:?}`", value
);
2798 trait NormalizeLocation
: fmt
::Debug
+ Copy
{
2799 fn to_locations(self) -> Locations
;
2802 impl NormalizeLocation
for Locations
{
2803 fn to_locations(self) -> Locations
{
2808 impl NormalizeLocation
for Location
{
2809 fn to_locations(self) -> Locations
{
2810 Locations
::Single(self)
2814 #[derive(Debug, Default)]
2815 struct ObligationAccumulator
<'tcx
> {
2816 obligations
: PredicateObligations
<'tcx
>,
2819 impl<'tcx
> ObligationAccumulator
<'tcx
> {
2820 fn add
<T
>(&mut self, value
: InferOk
<'tcx
, T
>) -> T
{
2821 let InferOk { value, obligations }
= value
;
2822 self.obligations
.extend(obligations
);
2826 fn into_vec(self) -> PredicateObligations
<'tcx
> {