1
Fork 0

Rollup merge of #138354 - lcnr:goodbye-TypeVerifier, r=compiler-errors

remove redundant `body`  arguments

it's already stored in the `TypeChecker` itself
This commit is contained in:
Matthias Krüger 2025-03-11 19:35:35 +01:00 committed by GitHub
commit 4c1a1867c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 152 additions and 172 deletions

View file

@ -24,9 +24,9 @@ use crate::universal_regions::DefiningTy;
impl<'a, 'tcx> TypeChecker<'a, 'tcx> { impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// Check explicit closure signature annotation, /// Check explicit closure signature annotation,
/// e.g., `|x: FxIndexMap<_, &'static u32>| ...`. /// e.g., `|x: FxIndexMap<_, &'static u32>| ...`.
#[instrument(skip(self, body), level = "debug")] #[instrument(skip(self), level = "debug")]
pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) { pub(super) fn check_signature_annotation(&mut self) {
let mir_def_id = body.source.def_id().expect_local(); let mir_def_id = self.body.source.def_id().expect_local();
if !self.tcx().is_closure_like(mir_def_id.to_def_id()) { if !self.tcx().is_closure_like(mir_def_id.to_def_id()) {
return; return;
@ -38,9 +38,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// (e.g., the `_` in the code above) with fresh variables. // (e.g., the `_` in the code above) with fresh variables.
// Then replace the bound items in the fn sig with fresh variables, // Then replace the bound items in the fn sig with fresh variables,
// so that they represent the view from "inside" the closure. // so that they represent the view from "inside" the closure.
let user_provided_sig = self.instantiate_canonical(body.span, &user_provided_poly_sig); let user_provided_sig = self.instantiate_canonical(self.body.span, &user_provided_poly_sig);
let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars( let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars(
body.span, self.body.span,
BoundRegionConversionTime::FnCall, BoundRegionConversionTime::FnCall,
user_provided_sig, user_provided_sig,
); );
@ -66,12 +66,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Ty::new_tup(self.tcx(), user_provided_sig.inputs()), Ty::new_tup(self.tcx(), user_provided_sig.inputs()),
args.tupled_upvars_ty(), args.tupled_upvars_ty(),
args.coroutine_captures_by_ref_ty(), args.coroutine_captures_by_ref_ty(),
self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(body.span), || { self.infcx
RegionCtxt::Unknown .next_region_var(RegionVariableOrigin::MiscVariable(self.body.span), || {
}), RegionCtxt::Unknown
}),
); );
let next_ty_var = || self.infcx.next_ty_var(body.span); let next_ty_var = || self.infcx.next_ty_var(self.body.span);
let output_ty = Ty::new_coroutine( let output_ty = Ty::new_coroutine(
self.tcx(), self.tcx(),
self.tcx().coroutine_for_closure(mir_def_id), self.tcx().coroutine_for_closure(mir_def_id),
@ -107,9 +108,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq( for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq(
// In MIR, closure args begin with an implicit `self`. // In MIR, closure args begin with an implicit `self`.
// Also, coroutines have a resume type which may be implicitly `()`. // Also, coroutines have a resume type which may be implicitly `()`.
body.args_iter() self.body
.args_iter()
.skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 }) .skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 })
.map(|local| &body.local_decls[local]), .map(|local| &self.body.local_decls[local]),
) { ) {
self.ascribe_user_type_skip_wf( self.ascribe_user_type_skip_wf(
arg_decl.ty, arg_decl.ty,
@ -119,7 +121,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
// If the user explicitly annotated the output type, enforce it. // If the user explicitly annotated the output type, enforce it.
let output_decl = &body.local_decls[RETURN_PLACE]; let output_decl = &self.body.local_decls[RETURN_PLACE];
self.ascribe_user_type_skip_wf( self.ascribe_user_type_skip_wf(
output_decl.ty, output_decl.ty,
ty::UserType::new(ty::UserTypeKind::Ty(user_provided_sig.output())), ty::UserType::new(ty::UserTypeKind::Ty(user_provided_sig.output())),
@ -127,12 +129,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
); );
} }
#[instrument(skip(self, body), level = "debug")] #[instrument(skip(self), level = "debug")]
pub(super) fn equate_inputs_and_outputs( pub(super) fn equate_inputs_and_outputs(&mut self, normalized_inputs_and_output: &[Ty<'tcx>]) {
&mut self,
body: &Body<'tcx>,
normalized_inputs_and_output: &[Ty<'tcx>],
) {
let (&normalized_output_ty, normalized_input_tys) = let (&normalized_output_ty, normalized_input_tys) =
normalized_inputs_and_output.split_last().unwrap(); normalized_inputs_and_output.split_last().unwrap();
@ -141,18 +139,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// Equate expected input tys with those in the MIR. // Equate expected input tys with those in the MIR.
for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() { for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
if argument_index + 1 >= body.local_decls.len() { if argument_index + 1 >= self.body.local_decls.len() {
self.tcx() self.tcx()
.dcx() .dcx()
.span_bug(body.span, "found more normalized_input_ty than local_decls"); .span_bug(self.body.span, "found more normalized_input_ty than local_decls");
} }
// In MIR, argument N is stored in local N+1. // In MIR, argument N is stored in local N+1.
let local = Local::from_usize(argument_index + 1); let local = Local::from_usize(argument_index + 1);
let mir_input_ty = body.local_decls[local].ty; let mir_input_ty = self.body.local_decls[local].ty;
let mir_input_span = body.local_decls[local].source_info.span; let mir_input_span = self.body.local_decls[local].source_info.span;
self.equate_normalized_input_or_output( self.equate_normalized_input_or_output(
normalized_input_ty, normalized_input_ty,
mir_input_ty, mir_input_ty,
@ -160,8 +158,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
); );
} }
if let Some(mir_yield_ty) = body.yield_ty() { if let Some(mir_yield_ty) = self.body.yield_ty() {
let yield_span = body.local_decls[RETURN_PLACE].source_info.span; let yield_span = self.body.local_decls[RETURN_PLACE].source_info.span;
self.equate_normalized_input_or_output( self.equate_normalized_input_or_output(
self.universal_regions.yield_ty.unwrap(), self.universal_regions.yield_ty.unwrap(),
mir_yield_ty, mir_yield_ty,
@ -169,8 +167,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
); );
} }
if let Some(mir_resume_ty) = body.resume_ty() { if let Some(mir_resume_ty) = self.body.resume_ty() {
let yield_span = body.local_decls[RETURN_PLACE].source_info.span; let yield_span = self.body.local_decls[RETURN_PLACE].source_info.span;
self.equate_normalized_input_or_output( self.equate_normalized_input_or_output(
self.universal_regions.resume_ty.unwrap(), self.universal_regions.resume_ty.unwrap(),
mir_resume_ty, mir_resume_ty,
@ -179,8 +177,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
// Return types are a bit more complex. They may contain opaque `impl Trait` types. // Return types are a bit more complex. They may contain opaque `impl Trait` types.
let mir_output_ty = body.local_decls[RETURN_PLACE].ty; let mir_output_ty = self.body.local_decls[RETURN_PLACE].ty;
let output_span = body.local_decls[RETURN_PLACE].source_info.span; let output_span = self.body.local_decls[RETURN_PLACE].source_info.span;
self.equate_normalized_input_or_output(normalized_output_ty, mir_output_ty, output_span); self.equate_normalized_input_or_output(normalized_output_ty, mir_output_ty, output_span);
} }

View file

@ -31,7 +31,6 @@ mod trace;
/// performed before /// performed before
pub(super) fn generate<'a, 'tcx>( pub(super) fn generate<'a, 'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>, typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>,
location_map: &DenseLocationMap, location_map: &DenseLocationMap,
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
@ -51,23 +50,16 @@ pub(super) fn generate<'a, 'tcx>(
// We do record these regions in the polonius context, since they're used to differentiate // We do record these regions in the polonius context, since they're used to differentiate
// relevant and boring locals, which is a key distinction used later in diagnostics. // relevant and boring locals, which is a key distinction used later in diagnostics.
if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() { if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() {
let (_, boring_locals) = compute_relevant_live_locals(typeck.tcx(), &free_regions, body); let (_, boring_locals) =
compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body);
typeck.polonius_liveness.as_mut().unwrap().boring_nll_locals = typeck.polonius_liveness.as_mut().unwrap().boring_nll_locals =
boring_locals.into_iter().collect(); boring_locals.into_iter().collect();
free_regions = typeck.universal_regions.universal_regions_iter().collect(); free_regions = typeck.universal_regions.universal_regions_iter().collect();
} }
let (relevant_live_locals, boring_locals) = let (relevant_live_locals, boring_locals) =
compute_relevant_live_locals(typeck.tcx(), &free_regions, body); compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body);
trace::trace( trace::trace(typeck, location_map, flow_inits, move_data, relevant_live_locals, boring_locals);
typeck,
body,
location_map,
flow_inits,
move_data,
relevant_live_locals,
boring_locals,
);
// Mark regions that should be live where they appear within rvalues or within a call: like // Mark regions that should be live where they appear within rvalues or within a call: like
// args, regions, and types. // args, regions, and types.
@ -76,7 +68,7 @@ pub(super) fn generate<'a, 'tcx>(
&mut typeck.constraints.liveness_constraints, &mut typeck.constraints.liveness_constraints,
&typeck.universal_regions, &typeck.universal_regions,
&mut typeck.polonius_liveness, &mut typeck.polonius_liveness,
body, typeck.body,
); );
} }

View file

@ -39,17 +39,15 @@ use crate::type_check::{NormalizeLocation, TypeChecker};
/// this respects `#[may_dangle]` annotations). /// this respects `#[may_dangle]` annotations).
pub(super) fn trace<'a, 'tcx>( pub(super) fn trace<'a, 'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>, typeck: &mut TypeChecker<'_, 'tcx>,
body: &Body<'tcx>,
location_map: &DenseLocationMap, location_map: &DenseLocationMap,
flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>, flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
relevant_live_locals: Vec<Local>, relevant_live_locals: Vec<Local>,
boring_locals: Vec<Local>, boring_locals: Vec<Local>,
) { ) {
let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, body); let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, typeck.body);
let cx = LivenessContext { let cx = LivenessContext {
typeck, typeck,
body,
flow_inits, flow_inits,
location_map, location_map,
local_use_map, local_use_map,
@ -69,14 +67,13 @@ pub(super) fn trace<'a, 'tcx>(
/// Contextual state for the type-liveness coroutine. /// Contextual state for the type-liveness coroutine.
struct LivenessContext<'a, 'typeck, 'b, 'tcx> { struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
/// Current type-checker, giving us our inference context etc. /// Current type-checker, giving us our inference context etc.
///
/// This also stores the body we're currently analyzing.
typeck: &'a mut TypeChecker<'typeck, 'tcx>, typeck: &'a mut TypeChecker<'typeck, 'tcx>,
/// Defines the `PointIndex` mapping /// Defines the `PointIndex` mapping
location_map: &'a DenseLocationMap, location_map: &'a DenseLocationMap,
/// MIR we are analyzing.
body: &'a Body<'tcx>,
/// Mapping to/from the various indices used for initialization tracking. /// Mapping to/from the various indices used for initialization tracking.
move_data: &'a MoveData<'tcx>, move_data: &'a MoveData<'tcx>,
@ -139,7 +136,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
self.compute_use_live_points_for(local); self.compute_use_live_points_for(local);
self.compute_drop_live_points_for(local); self.compute_drop_live_points_for(local);
let local_ty = self.cx.body.local_decls[local].ty; let local_ty = self.cx.body().local_decls[local].ty;
if !self.use_live_at.is_empty() { if !self.use_live_at.is_empty() {
self.cx.add_use_live_facts_for(local_ty, &self.use_live_at); self.cx.add_use_live_facts_for(local_ty, &self.use_live_at);
@ -164,8 +161,8 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
/// and can therefore safely be dropped. /// and can therefore safely be dropped.
fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) { fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) {
for local in boring_locals { for local in boring_locals {
let local_ty = self.cx.body.local_decls[local].ty; let local_ty = self.cx.body().local_decls[local].ty;
let local_span = self.cx.body.local_decls[local].source_info.span; let local_span = self.cx.body().local_decls[local].source_info.span;
let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({ let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
let typeck = &self.cx.typeck; let typeck = &self.cx.typeck;
move || LivenessContext::compute_drop_data(typeck, local_ty, local_span) move || LivenessContext::compute_drop_data(typeck, local_ty, local_span)
@ -173,7 +170,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
drop_data.dropck_result.report_overflows( drop_data.dropck_result.report_overflows(
self.cx.typeck.infcx.tcx, self.cx.typeck.infcx.tcx,
self.cx.body.local_decls[local].source_info.span, self.cx.typeck.body.local_decls[local].source_info.span,
local_ty, local_ty,
); );
} }
@ -202,7 +199,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
.var_dropped_at .var_dropped_at
.iter() .iter()
.filter_map(|&(local, location_index)| { .filter_map(|&(local, location_index)| {
let local_ty = self.cx.body.local_decls[local].ty; let local_ty = self.cx.body().local_decls[local].ty;
if relevant_live_locals.contains(&local) || !local_ty.has_free_regions() { if relevant_live_locals.contains(&local) || !local_ty.has_free_regions() {
return None; return None;
} }
@ -278,9 +275,9 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
let block = self.cx.location_map.to_location(block_start).block; let block = self.cx.location_map.to_location(block_start).block;
self.stack.extend( self.stack.extend(
self.cx.body.basic_blocks.predecessors()[block] self.cx.body().basic_blocks.predecessors()[block]
.iter() .iter()
.map(|&pred_bb| self.cx.body.terminator_loc(pred_bb)) .map(|&pred_bb| self.cx.body().terminator_loc(pred_bb))
.map(|pred_loc| self.cx.location_map.point_from_location(pred_loc)), .map(|pred_loc| self.cx.location_map.point_from_location(pred_loc)),
); );
} }
@ -305,7 +302,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
// Find the drops where `local` is initialized. // Find the drops where `local` is initialized.
for drop_point in self.cx.local_use_map.drops(local) { for drop_point in self.cx.local_use_map.drops(local) {
let location = self.cx.location_map.to_location(drop_point); let location = self.cx.location_map.to_location(drop_point);
debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,); debug_assert_eq!(self.cx.body().terminator_loc(location.block), location,);
if self.cx.initialized_at_terminator(location.block, mpi) if self.cx.initialized_at_terminator(location.block, mpi)
&& self.drop_live_at.insert(drop_point) && self.drop_live_at.insert(drop_point)
@ -351,7 +348,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
// block. One of them may be either a definition or use // block. One of them may be either a definition or use
// live point. // live point.
let term_location = self.cx.location_map.to_location(term_point); let term_location = self.cx.location_map.to_location(term_point);
debug_assert_eq!(self.cx.body.terminator_loc(term_location.block), term_location,); debug_assert_eq!(self.cx.body().terminator_loc(term_location.block), term_location,);
let block = term_location.block; let block = term_location.block;
let entry_point = self.cx.location_map.entry_point(term_location.block); let entry_point = self.cx.location_map.entry_point(term_location.block);
for p in (entry_point..term_point).rev() { for p in (entry_point..term_point).rev() {
@ -376,7 +373,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
} }
} }
let body = self.cx.body; let body = self.cx.typeck.body;
for &pred_block in body.basic_blocks.predecessors()[block].iter() { for &pred_block in body.basic_blocks.predecessors()[block].iter() {
debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,); debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,);
@ -403,7 +400,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
continue; continue;
} }
let pred_term_loc = self.cx.body.terminator_loc(pred_block); let pred_term_loc = self.cx.body().terminator_loc(pred_block);
let pred_term_point = self.cx.location_map.point_from_location(pred_term_loc); let pred_term_point = self.cx.location_map.point_from_location(pred_term_loc);
// If the terminator of this predecessor either *assigns* // If the terminator of this predecessor either *assigns*
@ -463,6 +460,9 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
} }
impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> { impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
fn body(&self) -> &Body<'tcx> {
self.typeck.body
}
/// Returns `true` if the local variable (or some part of it) is initialized at the current /// Returns `true` if the local variable (or some part of it) is initialized at the current
/// cursor position. Callers should call one of the `seek` methods immediately before to point /// cursor position. Callers should call one of the `seek` methods immediately before to point
/// the cursor to the desired location. /// the cursor to the desired location.
@ -481,7 +481,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
/// DROP of some local variable will have an effect -- note that /// DROP of some local variable will have an effect -- note that
/// drops, as they may unwind, are always terminators. /// drops, as they may unwind, are always terminators.
fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool { fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
self.flow_inits.seek_before_primary_effect(self.body.terminator_loc(block)); self.flow_inits.seek_before_primary_effect(self.body().terminator_loc(block));
self.initialized_at_curr_loc(mpi) self.initialized_at_curr_loc(mpi)
} }
@ -491,7 +491,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
/// **Warning:** Does not account for the result of `Call` /// **Warning:** Does not account for the result of `Call`
/// instructions. /// instructions.
fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool { fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
self.flow_inits.seek_after_primary_effect(self.body.terminator_loc(block)); self.flow_inits.seek_after_primary_effect(self.body().terminator_loc(block));
self.initialized_at_curr_loc(mpi) self.initialized_at_curr_loc(mpi)
} }
@ -526,7 +526,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
values::pretty_print_points(self.location_map, live_at.iter()), values::pretty_print_points(self.location_map, live_at.iter()),
); );
let local_span = self.body.local_decls()[dropped_local].source_info.span; let local_span = self.body().local_decls()[dropped_local].source_info.span;
let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({ let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
let typeck = &self.typeck; let typeck = &self.typeck;
move || Self::compute_drop_data(typeck, dropped_ty, local_span) move || Self::compute_drop_data(typeck, dropped_ty, local_span)
@ -544,7 +544,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
drop_data.dropck_result.report_overflows( drop_data.dropck_result.report_overflows(
self.typeck.infcx.tcx, self.typeck.infcx.tcx,
self.body.source_info(*drop_locations.first().unwrap()).span, self.typeck.body.source_info(*drop_locations.first().unwrap()).span,
dropped_ty, dropped_ty,
); );

View file

@ -174,11 +174,11 @@ pub(crate) fn type_check<'a, 'tcx>(
let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span }; let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span };
verifier.visit_body(body); verifier.visit_body(body);
typeck.typeck_mir(body); typeck.typeck_mir();
typeck.equate_inputs_and_outputs(body, &normalized_inputs_and_output); typeck.equate_inputs_and_outputs(&normalized_inputs_and_output);
typeck.check_signature_annotation(body); typeck.check_signature_annotation();
liveness::generate(&mut typeck, body, &location_map, flow_inits, move_data); liveness::generate(&mut typeck, &location_map, flow_inits, move_data);
let opaque_type_values = let opaque_type_values =
opaque_types::take_opaques_and_register_member_constraints(&mut typeck); opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
@ -485,6 +485,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn visit_body(&mut self, body: &Body<'tcx>) { fn visit_body(&mut self, body: &Body<'tcx>) {
debug_assert!(std::ptr::eq(self.typeck.body, body));
// We intentionally do not recurse into `body.required_consts` or // We intentionally do not recurse into `body.required_consts` or
// `body.mentioned_items` here as the MIR at this phase should still // `body.mentioned_items` here as the MIR at this phase should still
// refer to all items and we don't want to check them multiple times. // refer to all items and we don't want to check them multiple times.
@ -542,7 +543,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
self.visit_body(promoted_body); self.visit_body(promoted_body);
self.typeck.typeck_mir(promoted_body); self.typeck.typeck_mir();
self.typeck.body = parent_body; self.typeck.body = parent_body;
// Merge the outlives constraints back in, at the given location. // Merge the outlives constraints back in, at the given location.
@ -892,8 +893,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.infcx.tcx self.infcx.tcx
} }
#[instrument(skip(self, body), level = "debug")] #[instrument(skip(self), level = "debug")]
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) { fn check_stmt(&mut self, stmt: &Statement<'tcx>, location: Location) {
let tcx = self.tcx(); let tcx = self.tcx();
debug!("stmt kind: {:?}", stmt.kind); debug!("stmt kind: {:?}", stmt.kind);
match &stmt.kind { match &stmt.kind {
@ -916,11 +917,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
Some(l) Some(l)
if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) => if matches!(
self.body.local_decls[l].local_info(),
LocalInfo::AggregateTemp
) =>
{ {
ConstraintCategory::Usage ConstraintCategory::Usage
} }
Some(l) if !body.local_decls[l].is_user_variable() => { Some(l) if !self.body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring ConstraintCategory::Boring
} }
_ => ConstraintCategory::Assignment, _ => ConstraintCategory::Assignment,
@ -928,14 +932,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
debug!( debug!(
"assignment category: {:?} {:?}", "assignment category: {:?} {:?}",
category, category,
place.as_local().map(|l| &body.local_decls[l]) place.as_local().map(|l| &self.body.local_decls[l])
); );
let place_ty = place.ty(body, tcx).ty; let place_ty = place.ty(self.body, tcx).ty;
debug!(?place_ty); debug!(?place_ty);
let place_ty = self.normalize(place_ty, location); let place_ty = self.normalize(place_ty, location);
debug!("place_ty normalized: {:?}", place_ty); debug!("place_ty normalized: {:?}", place_ty);
let rv_ty = rv.ty(body, tcx); let rv_ty = rv.ty(self.body, tcx);
debug!(?rv_ty); debug!(?rv_ty);
let rv_ty = self.normalize(rv_ty, location); let rv_ty = self.normalize(rv_ty, location);
debug!("normalized rv_ty: {:?}", rv_ty); debug!("normalized rv_ty: {:?}", rv_ty);
@ -972,7 +976,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
self.check_rvalue(body, rv, location); self.check_rvalue(rv, location);
if !self.unsized_feature_enabled() { if !self.unsized_feature_enabled() {
let trait_ref = ty::TraitRef::new( let trait_ref = ty::TraitRef::new(
tcx, tcx,
@ -987,7 +991,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
StatementKind::AscribeUserType(box (place, projection), variance) => { StatementKind::AscribeUserType(box (place, projection), variance) => {
let place_ty = place.ty(body, tcx).ty; let place_ty = place.ty(self.body, tcx).ty;
if let Err(terr) = self.relate_type_and_user_type( if let Err(terr) = self.relate_type_and_user_type(
place_ty, place_ty,
*variance, *variance,
@ -1029,13 +1033,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
#[instrument(skip(self, body, term_location), level = "debug")] #[instrument(skip(self, term_location), level = "debug")]
fn check_terminator( fn check_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
&mut self,
body: &Body<'tcx>,
term: &Terminator<'tcx>,
term_location: Location,
) {
let tcx = self.tcx(); let tcx = self.tcx();
debug!("terminator kind: {:?}", term.kind); debug!("terminator kind: {:?}", term.kind);
match &term.kind { match &term.kind {
@ -1055,7 +1054,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
TerminatorKind::SwitchInt { discr, .. } => { TerminatorKind::SwitchInt { discr, .. } => {
self.check_operand(discr, term_location); self.check_operand(discr, term_location);
let switch_ty = discr.ty(body, tcx); let switch_ty = discr.ty(self.body, tcx);
if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() { if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty); span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
} }
@ -1074,7 +1073,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.check_operand(&arg.node, term_location); self.check_operand(&arg.node, term_location);
} }
let func_ty = func.ty(body, tcx); let func_ty = func.ty(self.body, tcx);
debug!("func_ty.kind: {:?}", func_ty.kind()); debug!("func_ty.kind: {:?}", func_ty.kind());
let sig = match func_ty.kind() { let sig = match func_ty.kind() {
@ -1142,7 +1141,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
if let TerminatorKind::Call { destination, target, .. } = term.kind { if let TerminatorKind::Call { destination, target, .. } = term.kind {
self.check_call_dest(body, term, &sig, destination, target, term_location); self.check_call_dest(term, &sig, destination, target, term_location);
} }
// The ordinary liveness rules will ensure that all // The ordinary liveness rules will ensure that all
@ -1157,21 +1156,21 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.constraints.liveness_constraints.add_location(region_vid, term_location); self.constraints.liveness_constraints.add_location(region_vid, term_location);
} }
self.check_call_inputs(body, term, func, &sig, args, term_location, call_source); self.check_call_inputs(term, func, &sig, args, term_location, call_source);
} }
TerminatorKind::Assert { cond, msg, .. } => { TerminatorKind::Assert { cond, msg, .. } => {
self.check_operand(cond, term_location); self.check_operand(cond, term_location);
let cond_ty = cond.ty(body, tcx); let cond_ty = cond.ty(self.body, tcx);
if cond_ty != tcx.types.bool { if cond_ty != tcx.types.bool {
span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty); span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
} }
if let AssertKind::BoundsCheck { len, index } = &**msg { if let AssertKind::BoundsCheck { len, index } = &**msg {
if len.ty(body, tcx) != tcx.types.usize { if len.ty(self.body, tcx) != tcx.types.usize {
span_mirbug!(self, len, "bounds-check length non-usize {:?}", len) span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
} }
if index.ty(body, tcx) != tcx.types.usize { if index.ty(self.body, tcx) != tcx.types.usize {
span_mirbug!(self, index, "bounds-check index non-usize {:?}", index) span_mirbug!(self, index, "bounds-check index non-usize {:?}", index)
} }
} }
@ -1179,10 +1178,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
TerminatorKind::Yield { value, resume_arg, .. } => { TerminatorKind::Yield { value, resume_arg, .. } => {
self.check_operand(value, term_location); self.check_operand(value, term_location);
match body.yield_ty() { match self.body.yield_ty() {
None => span_mirbug!(self, term, "yield in non-coroutine"), None => span_mirbug!(self, term, "yield in non-coroutine"),
Some(ty) => { Some(ty) => {
let value_ty = value.ty(body, tcx); let value_ty = value.ty(self.body, tcx);
if let Err(terr) = self.sub_types( if let Err(terr) = self.sub_types(
value_ty, value_ty,
ty, ty,
@ -1201,10 +1200,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
match body.resume_ty() { match self.body.resume_ty() {
None => span_mirbug!(self, term, "yield in non-coroutine"), None => span_mirbug!(self, term, "yield in non-coroutine"),
Some(ty) => { Some(ty) => {
let resume_ty = resume_arg.ty(body, tcx); let resume_ty = resume_arg.ty(self.body, tcx);
if let Err(terr) = self.sub_types( if let Err(terr) = self.sub_types(
ty, ty,
resume_ty.ty, resume_ty.ty,
@ -1228,7 +1227,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn check_call_dest( fn check_call_dest(
&mut self, &mut self,
body: &Body<'tcx>,
term: &Terminator<'tcx>, term: &Terminator<'tcx>,
sig: &ty::FnSig<'tcx>, sig: &ty::FnSig<'tcx>,
destination: Place<'tcx>, destination: Place<'tcx>,
@ -1238,7 +1236,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let tcx = self.tcx(); let tcx = self.tcx();
match target { match target {
Some(_) => { Some(_) => {
let dest_ty = destination.ty(body, tcx).ty; let dest_ty = destination.ty(self.body, tcx).ty;
let dest_ty = self.normalize(dest_ty, term_location); let dest_ty = self.normalize(dest_ty, term_location);
let category = match destination.as_local() { let category = match destination.as_local() {
Some(RETURN_PLACE) => { Some(RETURN_PLACE) => {
@ -1254,7 +1252,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::Return(ReturnConstraint::Normal) ConstraintCategory::Return(ReturnConstraint::Normal)
} }
} }
Some(l) if !body.local_decls[l].is_user_variable() => { Some(l) if !self.body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring ConstraintCategory::Boring
} }
// The return type of a call is interesting for diagnostics. // The return type of a call is interesting for diagnostics.
@ -1295,10 +1293,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
#[instrument(level = "debug", skip(self, body, term, func, term_location, call_source))] #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
fn check_call_inputs( fn check_call_inputs(
&mut self, &mut self,
body: &Body<'tcx>,
term: &Terminator<'tcx>, term: &Terminator<'tcx>,
func: &Operand<'tcx>, func: &Operand<'tcx>,
sig: &ty::FnSig<'tcx>, sig: &ty::FnSig<'tcx>,
@ -1310,7 +1307,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span_mirbug!(self, term, "call to {:?} with wrong # of args", sig); span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
} }
let func_ty = func.ty(body, self.infcx.tcx); let func_ty = func.ty(self.body, self.infcx.tcx);
if let ty::FnDef(def_id, _) = *func_ty.kind() { if let ty::FnDef(def_id, _) = *func_ty.kind() {
// Some of the SIMD intrinsics are special: they need a particular argument to be a // Some of the SIMD intrinsics are special: they need a particular argument to be a
// constant. (Eventually this should use const-generics, but those are not up for the // constant. (Eventually this should use const-generics, but those are not up for the
@ -1334,7 +1331,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
debug!(?func_ty); debug!(?func_ty);
for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() { for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
let op_arg_ty = op_arg.node.ty(body, self.tcx()); let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
let op_arg_ty = self.normalize(op_arg_ty, term_location); let op_arg_ty = self.normalize(op_arg_ty, term_location);
let category = if call_source.from_hir_call() { let category = if call_source.from_hir_call() {
@ -1358,16 +1355,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
fn check_iscleanup(&mut self, body: &Body<'tcx>, block_data: &BasicBlockData<'tcx>) { fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
let is_cleanup = block_data.is_cleanup; let is_cleanup = block_data.is_cleanup;
self.last_span = block_data.terminator().source_info.span; self.last_span = block_data.terminator().source_info.span;
match block_data.terminator().kind { match block_data.terminator().kind {
TerminatorKind::Goto { target } => { TerminatorKind::Goto { target } => {
self.assert_iscleanup(body, block_data, target, is_cleanup) self.assert_iscleanup(block_data, target, is_cleanup)
} }
TerminatorKind::SwitchInt { ref targets, .. } => { TerminatorKind::SwitchInt { ref targets, .. } => {
for target in targets.all_targets() { for target in targets.all_targets() {
self.assert_iscleanup(body, block_data, *target, is_cleanup); self.assert_iscleanup(block_data, *target, is_cleanup);
} }
} }
TerminatorKind::UnwindResume => { TerminatorKind::UnwindResume => {
@ -1399,55 +1396,48 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if is_cleanup { if is_cleanup {
span_mirbug!(self, block_data, "yield in cleanup block") span_mirbug!(self, block_data, "yield in cleanup block")
} }
self.assert_iscleanup(body, block_data, resume, is_cleanup); self.assert_iscleanup(block_data, resume, is_cleanup);
if let Some(drop) = drop { if let Some(drop) = drop {
self.assert_iscleanup(body, block_data, drop, is_cleanup); self.assert_iscleanup(block_data, drop, is_cleanup);
} }
} }
TerminatorKind::Unreachable => {} TerminatorKind::Unreachable => {}
TerminatorKind::Drop { target, unwind, .. } TerminatorKind::Drop { target, unwind, .. }
| TerminatorKind::Assert { target, unwind, .. } => { | TerminatorKind::Assert { target, unwind, .. } => {
self.assert_iscleanup(body, block_data, target, is_cleanup); self.assert_iscleanup(block_data, target, is_cleanup);
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
} }
TerminatorKind::Call { ref target, unwind, .. } => { TerminatorKind::Call { ref target, unwind, .. } => {
if let &Some(target) = target { if let &Some(target) = target {
self.assert_iscleanup(body, block_data, target, is_cleanup); self.assert_iscleanup(block_data, target, is_cleanup);
} }
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
} }
TerminatorKind::FalseEdge { real_target, imaginary_target } => { TerminatorKind::FalseEdge { real_target, imaginary_target } => {
self.assert_iscleanup(body, block_data, real_target, is_cleanup); self.assert_iscleanup(block_data, real_target, is_cleanup);
self.assert_iscleanup(body, block_data, imaginary_target, is_cleanup); self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
} }
TerminatorKind::FalseUnwind { real_target, unwind } => { TerminatorKind::FalseUnwind { real_target, unwind } => {
self.assert_iscleanup(body, block_data, real_target, is_cleanup); self.assert_iscleanup(block_data, real_target, is_cleanup);
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
} }
TerminatorKind::InlineAsm { ref targets, unwind, .. } => { TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
for &target in targets { for &target in targets {
self.assert_iscleanup(body, block_data, target, is_cleanup); self.assert_iscleanup(block_data, target, is_cleanup);
} }
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup); self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
} }
} }
} }
fn assert_iscleanup( fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
&mut self, if self.body[bb].is_cleanup != iscleanuppad {
body: &Body<'tcx>,
ctxt: &dyn fmt::Debug,
bb: BasicBlock,
iscleanuppad: bool,
) {
if body[bb].is_cleanup != iscleanuppad {
span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad); span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
} }
} }
fn assert_iscleanup_unwind( fn assert_iscleanup_unwind(
&mut self, &mut self,
body: &Body<'tcx>,
ctxt: &dyn fmt::Debug, ctxt: &dyn fmt::Debug,
unwind: UnwindAction, unwind: UnwindAction,
is_cleanup: bool, is_cleanup: bool,
@ -1457,7 +1447,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if is_cleanup { if is_cleanup {
span_mirbug!(self, ctxt, "unwind on cleanup block") span_mirbug!(self, ctxt, "unwind on cleanup block")
} }
self.assert_iscleanup(body, ctxt, unwind, true); self.assert_iscleanup(ctxt, unwind, true);
} }
UnwindAction::Continue => { UnwindAction::Continue => {
if is_cleanup { if is_cleanup {
@ -1468,8 +1458,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) { fn check_local(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
match body.local_kind(local) { match self.body.local_kind(local) {
LocalKind::ReturnPointer | LocalKind::Arg => { LocalKind::ReturnPointer | LocalKind::Arg => {
// return values of normal functions are required to be // return values of normal functions are required to be
// sized by typeck, but return values of ADT constructors are // sized by typeck, but return values of ADT constructors are
@ -1598,23 +1588,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
#[instrument(skip(self, body), level = "debug")] #[instrument(skip(self), level = "debug")]
fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
let tcx = self.tcx(); let tcx = self.tcx();
let span = body.source_info(location).span; let span = self.body.source_info(location).span;
match rvalue { match rvalue {
Rvalue::Aggregate(ak, ops) => { Rvalue::Aggregate(ak, ops) => {
for op in ops { for op in ops {
self.check_operand(op, location); self.check_operand(op, location);
} }
self.check_aggregate_rvalue(body, rvalue, ak, ops, location) self.check_aggregate_rvalue(rvalue, ak, ops, location)
} }
Rvalue::Repeat(operand, len) => { Rvalue::Repeat(operand, len) => {
self.check_operand(operand, location); self.check_operand(operand, location);
let array_ty = rvalue.ty(body.local_decls(), tcx); let array_ty = rvalue.ty(self.body.local_decls(), tcx);
self.prove_predicate( self.prove_predicate(
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())), ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
Locations::Single(location), Locations::Single(location),
@ -1633,7 +1623,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
Operand::Move(place) => { Operand::Move(place) => {
// Make sure that repeated elements implement `Copy`. // Make sure that repeated elements implement `Copy`.
let ty = place.ty(body, tcx).ty; let ty = place.ty(self.body, tcx).ty;
let trait_ref = ty::TraitRef::new( let trait_ref = ty::TraitRef::new(
tcx, tcx,
tcx.require_lang_item(LangItem::Copy, Some(span)), tcx.require_lang_item(LangItem::Copy, Some(span)),
@ -1688,7 +1678,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
match *cast_kind { match *cast_kind {
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => { CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
let is_implicit_coercion = coercion_source == CoercionSource::Implicit; let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
let src_ty = op.ty(body, tcx); let src_ty = op.ty(self.body, tcx);
let mut src_sig = src_ty.fn_sig(tcx); let mut src_sig = src_ty.fn_sig(tcx);
if let ty::FnDef(def_id, _) = src_ty.kind() if let ty::FnDef(def_id, _) = src_ty.kind()
&& let ty::FnPtr(_, target_hdr) = *ty.kind() && let ty::FnPtr(_, target_hdr) = *ty.kind()
@ -1697,7 +1687,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
&& let Some(safe_sig) = tcx.adjust_target_feature_sig( && let Some(safe_sig) = tcx.adjust_target_feature_sig(
*def_id, *def_id,
src_sig, src_sig,
body.source.def_id(), self.body.source.def_id(),
) )
{ {
src_sig = safe_sig; src_sig = safe_sig;
@ -1790,7 +1780,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
PointerCoercion::ClosureFnPointer(safety), PointerCoercion::ClosureFnPointer(safety),
coercion_source, coercion_source,
) => { ) => {
let sig = match op.ty(body, tcx).kind() { let sig = match op.ty(self.body, tcx).kind() {
ty::Closure(_, args) => args.as_closure().sig(), ty::Closure(_, args) => args.as_closure().sig(),
_ => bug!(), _ => bug!(),
}; };
@ -1819,7 +1809,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
PointerCoercion::UnsafeFnPointer, PointerCoercion::UnsafeFnPointer,
coercion_source, coercion_source,
) => { ) => {
let fn_sig = op.ty(body, tcx).fn_sig(tcx); let fn_sig = op.ty(self.body, tcx).fn_sig(tcx);
// The type that we see in the fcx is like // The type that we see in the fcx is like
// `foo::<'a, 'b>`, where `foo` is the path to a // `foo::<'a, 'b>`, where `foo` is the path to a
@ -1853,7 +1843,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let trait_ref = ty::TraitRef::new( let trait_ref = ty::TraitRef::new(
tcx, tcx,
tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)), tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
[op.ty(body, tcx), ty], [op.ty(self.body, tcx), ty],
); );
let is_implicit_coercion = coercion_source == CoercionSource::Implicit; let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
@ -1879,7 +1869,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
_ => panic!("Invalid dyn* cast_ty"), _ => panic!("Invalid dyn* cast_ty"),
}; };
let self_ty = op.ty(body, tcx); let self_ty = op.ty(self.body, tcx);
let is_implicit_coercion = coercion_source == CoercionSource::Implicit; let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
self.prove_predicates( self.prove_predicates(
@ -1906,7 +1896,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
PointerCoercion::MutToConstPointer, PointerCoercion::MutToConstPointer,
coercion_source, coercion_source,
) => { ) => {
let ty::RawPtr(ty_from, hir::Mutability::Mut) = op.ty(body, tcx).kind() let ty::RawPtr(ty_from, hir::Mutability::Mut) =
op.ty(self.body, tcx).kind()
else { else {
span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,); span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
return; return;
@ -1934,7 +1925,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => { CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let opt_ty_elem_mut = match ty_from.kind() { let opt_ty_elem_mut = match ty_from.kind() {
ty::RawPtr(array_ty, array_mut) => match array_ty.kind() { ty::RawPtr(array_ty, array_mut) => match array_ty.kind() {
@ -1997,7 +1988,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
CastKind::PointerExposeProvenance => { CastKind::PointerExposeProvenance => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
@ -2015,7 +2006,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
CastKind::PointerWithExposedProvenance => { CastKind::PointerWithExposedProvenance => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
@ -2032,7 +2023,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
CastKind::IntToInt => { CastKind::IntToInt => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
@ -2049,7 +2040,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
CastKind::IntToFloat => { CastKind::IntToFloat => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
@ -2066,7 +2057,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
CastKind::FloatToInt => { CastKind::FloatToInt => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
@ -2083,7 +2074,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
CastKind::FloatToFloat => { CastKind::FloatToFloat => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
@ -2100,7 +2091,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
CastKind::FnPtrToPtr => { CastKind::FnPtrToPtr => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
@ -2117,7 +2108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
} }
CastKind::PtrToPtr => { CastKind::PtrToPtr => {
let ty_from = op.ty(body, tcx); let ty_from = op.ty(self.body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty); let cast_ty_to = CastTy::from_ty(*ty);
match (cast_ty_from, cast_ty_to) { match (cast_ty_from, cast_ty_to) {
@ -2193,7 +2184,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
} }
Rvalue::Ref(region, _borrow_kind, borrowed_place) => { Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
self.add_reborrow_constraint(body, location, *region, borrowed_place); self.add_reborrow_constraint(location, *region, borrowed_place);
} }
Rvalue::BinaryOp( Rvalue::BinaryOp(
@ -2203,12 +2194,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.check_operand(left, location); self.check_operand(left, location);
self.check_operand(right, location); self.check_operand(right, location);
let ty_left = left.ty(body, tcx); let ty_left = left.ty(self.body, tcx);
match ty_left.kind() { match ty_left.kind() {
// Types with regions are comparable if they have a common super-type. // Types with regions are comparable if they have a common super-type.
ty::RawPtr(_, _) | ty::FnPtr(..) => { ty::RawPtr(_, _) | ty::FnPtr(..) => {
let ty_right = right.ty(body, tcx); let ty_right = right.ty(self.body, tcx);
let common_ty = self.infcx.next_ty_var(body.source_info(location).span); let common_ty =
self.infcx.next_ty_var(self.body.source_info(location).span);
self.sub_types( self.sub_types(
ty_left, ty_left,
common_ty, common_ty,
@ -2237,7 +2229,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// For types with no regions we can just check that the // For types with no regions we can just check that the
// both operands have the same type. // both operands have the same type.
ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_) ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_)
if ty_left == right.ty(body, tcx) => {} if ty_left == right.ty(self.body, tcx) => {}
// Other types are compared by trait methods, not by // Other types are compared by trait methods, not by
// `Rvalue::BinaryOp`. // `Rvalue::BinaryOp`.
_ => span_mirbug!( _ => span_mirbug!(
@ -2245,7 +2237,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
rvalue, rvalue,
"unexpected comparison types {:?} and {:?}", "unexpected comparison types {:?} and {:?}",
ty_left, ty_left,
right.ty(body, tcx) right.ty(self.body, tcx)
), ),
} }
} }
@ -2326,7 +2318,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn check_aggregate_rvalue( fn check_aggregate_rvalue(
&mut self, &mut self,
body: &Body<'tcx>,
rvalue: &Rvalue<'tcx>, rvalue: &Rvalue<'tcx>,
aggregate_kind: &AggregateKind<'tcx>, aggregate_kind: &AggregateKind<'tcx>,
operands: &IndexSlice<FieldIdx, Operand<'tcx>>, operands: &IndexSlice<FieldIdx, Operand<'tcx>>,
@ -2359,7 +2350,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
continue; continue;
} }
}; };
let operand_ty = operand.ty(body, tcx); let operand_ty = operand.ty(self.body, tcx);
let operand_ty = self.normalize(operand_ty, location); let operand_ty = self.normalize(operand_ty, location);
if let Err(terr) = self.sub_types( if let Err(terr) = self.sub_types(
@ -2389,7 +2380,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// - `borrowed_place`: the place `P` being borrowed /// - `borrowed_place`: the place `P` being borrowed
fn add_reborrow_constraint( fn add_reborrow_constraint(
&mut self, &mut self,
body: &Body<'tcx>,
location: Location, location: Location,
borrow_region: ty::Region<'tcx>, borrow_region: ty::Region<'tcx>,
borrowed_place: &Place<'tcx>, borrowed_place: &Place<'tcx>,
@ -2428,7 +2418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let def = self.body.source.def_id().expect_local(); let def = self.body.source.def_id().expect_local();
let upvars = tcx.closure_captures(def); let upvars = tcx.closure_captures(def);
let field = let field =
path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), body); path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), self.body);
let category = if let Some(field) = field { let category = if let Some(field) = field {
ConstraintCategory::ClosureUpvar(field) ConstraintCategory::ClosureUpvar(field)
} else { } else {
@ -2440,7 +2430,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
match elem { match elem {
ProjectionElem::Deref => { ProjectionElem::Deref => {
let base_ty = base.ty(body, tcx).ty; let base_ty = base.ty(self.body, tcx).ty;
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty); debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
match base_ty.kind() { match base_ty.kind() {
@ -2449,7 +2439,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
sup: ref_region.as_var(), sup: ref_region.as_var(),
sub: borrow_region.as_var(), sub: borrow_region.as_var(),
locations: location.to_locations(), locations: location.to_locations(),
span: location.to_locations().span(body), span: location.to_locations().span(self.body),
category, category,
variance_info: ty::VarianceDiagInfo::default(), variance_info: ty::VarianceDiagInfo::default(),
from_closure: false, from_closure: false,
@ -2634,27 +2624,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
tcx.predicates_of(def_id).instantiate(tcx, args) tcx.predicates_of(def_id).instantiate(tcx, args)
} }
#[instrument(skip(self, body), level = "debug")] #[instrument(skip(self), level = "debug")]
fn typeck_mir(&mut self, body: &Body<'tcx>) { fn typeck_mir(&mut self) {
self.last_span = body.span; self.last_span = self.body.span;
debug!(?body.span); debug!(?self.body.span);
for (local, local_decl) in body.local_decls.iter_enumerated() { for (local, local_decl) in self.body.local_decls.iter_enumerated() {
self.check_local(body, local, local_decl); self.check_local(local, local_decl);
} }
for (block, block_data) in body.basic_blocks.iter_enumerated() { for (block, block_data) in self.body.basic_blocks.iter_enumerated() {
let mut location = Location { block, statement_index: 0 }; let mut location = Location { block, statement_index: 0 };
for stmt in &block_data.statements { for stmt in &block_data.statements {
if !stmt.source_info.span.is_dummy() { if !stmt.source_info.span.is_dummy() {
self.last_span = stmt.source_info.span; self.last_span = stmt.source_info.span;
} }
self.check_stmt(body, stmt, location); self.check_stmt(stmt, location);
location.statement_index += 1; location.statement_index += 1;
} }
self.check_terminator(body, block_data.terminator(), location); self.check_terminator(block_data.terminator(), location);
self.check_iscleanup(body, block_data); self.check_iscleanup(block_data);
} }
} }
} }