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