2020-11-15 12:36:28 -08:00
|
|
|
//! # The MIR Visitor
|
|
|
|
//!
|
|
|
|
//! ## Overview
|
|
|
|
//!
|
|
|
|
//! There are two visitors, one for immutable and one for mutable references,
|
|
|
|
//! but both are generated by the following macro. The code is written according
|
|
|
|
//! to the following conventions:
|
|
|
|
//!
|
|
|
|
//! - introduce a `visit_foo` and a `super_foo` method for every MIR type
|
|
|
|
//! - `visit_foo`, by default, calls `super_foo`
|
|
|
|
//! - `super_foo`, by default, destructures the `foo` and calls `visit_foo`
|
|
|
|
//!
|
|
|
|
//! This allows you as a user to override `visit_foo` for types are
|
|
|
|
//! interested in, and invoke (within that method) call
|
|
|
|
//! `self.super_foo` to get the default behavior. Just as in an OO
|
|
|
|
//! language, you should never call `super` methods ordinarily except
|
|
|
|
//! in that circumstance.
|
|
|
|
//!
|
|
|
|
//! For the most part, we do not destructure things external to the
|
|
|
|
//! MIR, e.g., types, spans, etc, but simply visit them and stop. This
|
|
|
|
//! avoids duplication with other visitors like `TypeFoldable`.
|
|
|
|
//!
|
|
|
|
//! ## Updating
|
|
|
|
//!
|
|
|
|
//! The code is written in a very deliberate style intended to minimize
|
|
|
|
//! the chance of things being overlooked. You'll notice that we always
|
|
|
|
//! use pattern matching to reference fields and we ensure that all
|
|
|
|
//! matches are exhaustive.
|
|
|
|
//!
|
|
|
|
//! For example, the `super_basic_block_data` method begins like this:
|
|
|
|
//!
|
|
|
|
//! ```rust
|
|
|
|
//! fn super_basic_block_data(&mut self,
|
|
|
|
//! block: BasicBlock,
|
|
|
|
//! data: & $($mutability)? BasicBlockData<'tcx>) {
|
|
|
|
//! let BasicBlockData {
|
|
|
|
//! statements,
|
|
|
|
//! terminator,
|
|
|
|
//! is_cleanup: _
|
|
|
|
//! } = *data;
|
|
|
|
//!
|
|
|
|
//! for statement in statements {
|
|
|
|
//! self.visit_statement(block, statement);
|
|
|
|
//! }
|
|
|
|
//!
|
|
|
|
//! ...
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! Here we used `let BasicBlockData { <fields> } = *data` deliberately,
|
|
|
|
//! rather than writing `data.statements` in the body. This is because if one
|
|
|
|
//! adds a new field to `BasicBlockData`, one will be forced to revise this code,
|
|
|
|
//! and hence one will (hopefully) invoke the correct visit methods (if any).
|
|
|
|
//!
|
|
|
|
//! For this to work, ALL MATCHES MUST BE EXHAUSTIVE IN FIELDS AND VARIANTS.
|
|
|
|
//! That means you never write `..` to skip over fields, nor do you write `_`
|
|
|
|
//! to skip over variants in a `match`.
|
|
|
|
//!
|
|
|
|
//! The only place that `_` is acceptable is to match a field (or
|
|
|
|
//! variant argument) that does not require visiting, as in
|
|
|
|
//! `is_cleanup` above.
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
use crate::mir::*;
|
2019-02-09 22:11:53 +08:00
|
|
|
use crate::ty::subst::SubstsRef;
|
2019-10-03 21:30:26 +08:00
|
|
|
use crate::ty::{CanonicalUserTypeAnnotation, Ty};
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::Span;
|
2015-11-03 06:33:59 -05:00
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
macro_rules! make_mir_visitor {
|
2019-02-09 16:29:31 +00:00
|
|
|
($visitor_trait_name:ident, $($mutability:ident)?) => {
|
2016-01-07 05:49:46 -05:00
|
|
|
pub trait $visitor_trait_name<'tcx> {
|
|
|
|
// Override these, and call `self.super_xxx` to revert back to the
|
|
|
|
// default behavior.
|
2015-11-03 06:33:59 -05:00
|
|
|
|
2019-10-10 23:16:44 -04:00
|
|
|
fn visit_body(
|
|
|
|
&mut self,
|
2020-04-12 10:31:00 -07:00
|
|
|
body: &$($mutability)? Body<'tcx>,
|
2019-10-10 23:16:44 -04:00
|
|
|
) {
|
2019-11-06 12:00:46 -05:00
|
|
|
self.super_body(body);
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn visit_basic_block_data(&mut self,
|
|
|
|
block: BasicBlock,
|
2019-02-09 16:29:31 +00:00
|
|
|
data: & $($mutability)? BasicBlockData<'tcx>) {
|
2016-01-07 05:49:46 -05:00
|
|
|
self.super_basic_block_data(block, data);
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2018-05-28 14:16:09 +03:00
|
|
|
fn visit_source_scope_data(&mut self,
|
2020-02-08 21:31:09 +02:00
|
|
|
scope_data: & $($mutability)? SourceScopeData<'tcx>) {
|
2018-05-28 14:16:09 +03:00
|
|
|
self.super_source_scope_data(scope_data);
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn visit_statement(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
statement: & $($mutability)? Statement<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2019-04-22 21:07:14 +01:00
|
|
|
self.super_statement(statement, location);
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn visit_assign(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
place: & $($mutability)? Place<'tcx>,
|
|
|
|
rvalue: & $($mutability)? Rvalue<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2019-04-22 21:07:14 +01:00
|
|
|
self.super_assign(place, rvalue, location);
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn visit_terminator(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
terminator: & $($mutability)? Terminator<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2019-04-22 21:07:14 +01:00
|
|
|
self.super_terminator(terminator, location);
|
2015-10-26 14:35:18 -04:00
|
|
|
}
|
|
|
|
|
2016-05-25 08:39:32 +03:00
|
|
|
fn visit_assert_message(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
msg: & $($mutability)? AssertMessage<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
|
|
|
self.super_assert_message(msg, location);
|
2016-05-25 08:39:32 +03:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn visit_rvalue(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
rvalue: & $($mutability)? Rvalue<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
|
|
|
self.super_rvalue(rvalue, location);
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn visit_operand(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
operand: & $($mutability)? Operand<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
|
|
|
self.super_operand(operand, location);
|
2015-12-14 23:27:58 +02:00
|
|
|
}
|
2015-11-03 06:33:59 -05:00
|
|
|
|
2018-08-31 18:59:35 -04:00
|
|
|
fn visit_ascribe_user_ty(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
place: & $($mutability)? Place<'tcx>,
|
|
|
|
variance: & $($mutability)? ty::Variance,
|
2019-03-28 18:00:17 -07:00
|
|
|
user_ty: & $($mutability)? UserTypeProjection,
|
2018-08-31 18:59:35 -04:00
|
|
|
location: Location) {
|
2018-10-10 17:07:10 -04:00
|
|
|
self.super_ascribe_user_ty(place, variance, user_ty, location);
|
2018-02-23 20:52:05 +00:00
|
|
|
}
|
|
|
|
|
2020-08-15 04:42:13 -07:00
|
|
|
fn visit_coverage(&mut self,
|
|
|
|
coverage: & $($mutability)? Coverage,
|
|
|
|
location: Location) {
|
|
|
|
self.super_coverage(coverage, location);
|
|
|
|
}
|
|
|
|
|
2018-10-24 13:47:48 +02:00
|
|
|
fn visit_retag(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
kind: & $($mutability)? RetagKind,
|
|
|
|
place: & $($mutability)? Place<'tcx>,
|
2018-10-24 13:47:48 +02:00
|
|
|
location: Location) {
|
2018-12-11 19:54:38 +01:00
|
|
|
self.super_retag(kind, place, location);
|
2018-10-24 13:47:48 +02:00
|
|
|
}
|
|
|
|
|
2017-12-01 14:39:51 +02:00
|
|
|
fn visit_place(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
place: & $($mutability)? Place<'tcx>,
|
2019-04-24 19:41:43 +01:00
|
|
|
context: PlaceContext,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2017-12-01 14:39:51 +02:00
|
|
|
self.super_place(place, context, location);
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2019-10-08 12:16:26 -03:00
|
|
|
visit_place_fns!($($mutability)?);
|
2019-10-02 18:03:23 -03:00
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn visit_constant(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
constant: & $($mutability)? Constant<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
|
|
|
self.super_constant(constant, location);
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn visit_span(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
span: & $($mutability)? Span) {
|
2016-01-07 05:49:46 -05:00
|
|
|
self.super_span(span);
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2016-06-07 19:21:56 +03:00
|
|
|
fn visit_source_info(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
source_info: & $($mutability)? SourceInfo) {
|
2016-06-07 19:21:56 +03:00
|
|
|
self.super_source_info(source_info);
|
|
|
|
}
|
|
|
|
|
2016-03-24 06:12:19 -04:00
|
|
|
fn visit_ty(&mut self,
|
2019-04-25 22:54:19 +02:00
|
|
|
ty: $(& $mutability)? Ty<'tcx>,
|
2017-10-26 19:53:31 -04:00
|
|
|
_: TyContext) {
|
2016-03-24 06:12:19 -04:00
|
|
|
self.super_ty(ty);
|
|
|
|
}
|
|
|
|
|
2018-10-22 11:58:06 +02:00
|
|
|
fn visit_user_type_projection(
|
|
|
|
&mut self,
|
2019-03-28 18:00:17 -07:00
|
|
|
ty: & $($mutability)? UserTypeProjection,
|
2018-10-22 11:58:06 +02:00
|
|
|
) {
|
|
|
|
self.super_user_type_projection(ty);
|
|
|
|
}
|
|
|
|
|
2018-10-15 09:31:38 -04:00
|
|
|
fn visit_user_type_annotation(
|
|
|
|
&mut self,
|
2018-11-16 22:56:18 +01:00
|
|
|
index: UserTypeAnnotationIndex,
|
2019-02-09 16:29:31 +00:00
|
|
|
ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
|
2018-10-15 09:31:38 -04:00
|
|
|
) {
|
2018-11-16 22:56:18 +01:00
|
|
|
self.super_user_type_annotation(index, ty);
|
2018-08-09 06:18:00 -04:00
|
|
|
}
|
|
|
|
|
2017-08-04 11:25:13 +03:00
|
|
|
fn visit_region(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
region: & $($mutability)? ty::Region<'tcx>,
|
2017-08-04 11:25:13 +03:00
|
|
|
_: Location) {
|
|
|
|
self.super_region(region);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_const(&mut self,
|
2019-03-14 10:19:31 +01:00
|
|
|
constant: & $($mutability)? &'tcx ty::Const<'tcx>,
|
2017-08-04 11:25:13 +03:00
|
|
|
_: Location) {
|
|
|
|
self.super_const(constant);
|
|
|
|
}
|
|
|
|
|
2016-03-24 06:12:19 -04:00
|
|
|
fn visit_substs(&mut self,
|
2019-02-09 22:11:53 +08:00
|
|
|
substs: & $($mutability)? SubstsRef<'tcx>,
|
2017-07-18 22:31:38 -04:00
|
|
|
_: Location) {
|
2016-03-24 06:12:19 -04:00
|
|
|
self.super_substs(substs);
|
|
|
|
}
|
|
|
|
|
2016-09-25 01:38:27 +02:00
|
|
|
fn visit_local_decl(&mut self,
|
2017-10-26 19:53:31 -04:00
|
|
|
local: Local,
|
2019-02-09 16:29:31 +00:00
|
|
|
local_decl: & $($mutability)? LocalDecl<'tcx>) {
|
2017-10-26 19:53:31 -04:00
|
|
|
self.super_local_decl(local, local_decl);
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2018-05-16 18:58:54 +03:00
|
|
|
fn visit_var_debug_info(&mut self,
|
|
|
|
var_debug_info: & $($mutability)* VarDebugInfo<'tcx>) {
|
|
|
|
self.super_var_debug_info(var_debug_info);
|
|
|
|
}
|
|
|
|
|
2016-12-26 14:34:03 +01:00
|
|
|
fn visit_local(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
_local: & $($mutability)? Local,
|
2019-04-24 19:41:43 +01:00
|
|
|
_context: PlaceContext,
|
2017-09-03 19:14:31 +03:00
|
|
|
_location: Location) {
|
2016-12-26 14:34:03 +01:00
|
|
|
}
|
|
|
|
|
2018-05-28 14:16:09 +03:00
|
|
|
fn visit_source_scope(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
scope: & $($mutability)? SourceScope) {
|
2018-05-28 14:16:09 +03:00
|
|
|
self.super_source_scope(scope);
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
// The `super_xxx` methods comprise the default behavior and are
|
2016-02-09 11:52:39 -05:00
|
|
|
// not meant to be overridden.
|
2015-11-03 06:33:59 -05:00
|
|
|
|
2019-10-10 23:16:44 -04:00
|
|
|
fn super_body(
|
|
|
|
&mut self,
|
2020-04-12 10:31:00 -07:00
|
|
|
body: &$($mutability)? Body<'tcx>,
|
2019-10-10 23:16:44 -04:00
|
|
|
) {
|
2019-11-06 12:00:46 -05:00
|
|
|
let span = body.span;
|
2021-01-17 13:27:05 +01:00
|
|
|
if let Some(gen) = &$($mutability)? body.generator {
|
|
|
|
if let Some(yield_ty) = &$($mutability)? gen.yield_ty {
|
|
|
|
self.visit_ty(
|
|
|
|
yield_ty,
|
|
|
|
TyContext::YieldTy(SourceInfo::outermost(span))
|
|
|
|
);
|
|
|
|
}
|
2018-01-19 19:18:02 -03:00
|
|
|
}
|
|
|
|
|
2017-08-01 00:09:32 +03:00
|
|
|
// for best performance, we want to use an iterator rather
|
2019-06-03 18:26:48 -04:00
|
|
|
// than a for-loop, to avoid calling `body::Body::invalidate` for
|
2017-08-01 00:09:32 +03:00
|
|
|
// each basic block.
|
|
|
|
macro_rules! basic_blocks {
|
2019-11-06 12:00:46 -05:00
|
|
|
(mut) => (body.basic_blocks_mut().iter_enumerated_mut());
|
|
|
|
() => (body.basic_blocks().iter_enumerated());
|
2020-11-25 17:00:28 -05:00
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
for (bb, data) in basic_blocks!($($mutability)?) {
|
2017-08-01 00:09:32 +03:00
|
|
|
self.visit_basic_block_data(bb, data);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2016-03-24 06:12:19 -04:00
|
|
|
|
2019-06-03 18:26:48 -04:00
|
|
|
for scope in &$($mutability)? body.source_scopes {
|
2018-05-28 14:16:09 +03:00
|
|
|
self.visit_source_scope_data(scope);
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2020-05-06 10:30:11 +10:00
|
|
|
self.visit_ty(
|
|
|
|
&$($mutability)? body.return_ty(),
|
|
|
|
TyContext::ReturnTy(SourceInfo::outermost(body.span))
|
|
|
|
);
|
2016-03-24 06:12:19 -04:00
|
|
|
|
2019-06-03 18:26:48 -04:00
|
|
|
for local in body.local_decls.indices() {
|
|
|
|
self.visit_local_decl(local, & $($mutability)? body.local_decls[local]);
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2019-01-06 17:10:53 +00:00
|
|
|
macro_rules! type_annotations {
|
2019-06-03 18:26:48 -04:00
|
|
|
(mut) => (body.user_type_annotations.iter_enumerated_mut());
|
|
|
|
() => (body.user_type_annotations.iter_enumerated());
|
2020-11-25 17:00:28 -05:00
|
|
|
}
|
2019-01-06 17:10:53 +00:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
for (index, annotation) in type_annotations!($($mutability)?) {
|
2018-11-16 22:56:18 +01:00
|
|
|
self.visit_user_type_annotation(
|
|
|
|
index, annotation
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-05-16 18:58:54 +03:00
|
|
|
for var_debug_info in &$($mutability)? body.var_debug_info {
|
|
|
|
self.visit_var_debug_info(var_debug_info);
|
|
|
|
}
|
|
|
|
|
2019-06-03 18:26:48 -04:00
|
|
|
self.visit_span(&$($mutability)? body.span);
|
2020-04-06 17:49:49 -03:00
|
|
|
|
2020-04-22 11:16:06 -03:00
|
|
|
for const_ in &$($mutability)? body.required_consts {
|
2020-04-06 17:49:49 -03:00
|
|
|
let location = START_BLOCK.start_location();
|
|
|
|
self.visit_constant(const_, location);
|
|
|
|
}
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn super_basic_block_data(&mut self,
|
|
|
|
block: BasicBlock,
|
2019-02-09 16:29:31 +00:00
|
|
|
data: & $($mutability)? BasicBlockData<'tcx>) {
|
2016-03-24 06:12:19 -04:00
|
|
|
let BasicBlockData {
|
2019-02-09 16:29:31 +00:00
|
|
|
statements,
|
|
|
|
terminator,
|
2016-03-24 06:12:19 -04:00
|
|
|
is_cleanup: _
|
2019-02-09 16:29:31 +00:00
|
|
|
} = data;
|
2016-03-24 06:12:19 -04:00
|
|
|
|
2016-08-08 18:46:06 -07:00
|
|
|
let mut index = 0;
|
2016-03-24 06:12:19 -04:00
|
|
|
for statement in statements {
|
2020-12-29 22:02:47 +01:00
|
|
|
let location = Location { block, statement_index: index };
|
2019-04-22 21:07:14 +01:00
|
|
|
self.visit_statement(statement, location);
|
2016-08-08 18:46:06 -07:00
|
|
|
index += 1;
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
if let Some(terminator) = terminator {
|
2020-12-29 22:02:47 +01:00
|
|
|
let location = Location { block, statement_index: index };
|
2019-04-22 21:07:14 +01:00
|
|
|
self.visit_terminator(terminator, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
|
|
|
|
2020-02-08 21:31:09 +02:00
|
|
|
fn super_source_scope_data(
|
|
|
|
&mut self,
|
|
|
|
scope_data: & $($mutability)? SourceScopeData<'tcx>,
|
|
|
|
) {
|
2018-05-28 14:16:09 +03:00
|
|
|
let SourceScopeData {
|
2019-02-09 16:29:31 +00:00
|
|
|
span,
|
|
|
|
parent_scope,
|
2020-02-08 21:31:09 +02:00
|
|
|
inlined,
|
2020-09-21 06:52:37 +03:00
|
|
|
inlined_parent_scope,
|
2019-11-26 22:17:35 +02:00
|
|
|
local_data: _,
|
2019-02-09 16:29:31 +00:00
|
|
|
} = scope_data;
|
2016-03-24 06:12:19 -04:00
|
|
|
|
2016-04-06 17:17:12 +03:00
|
|
|
self.visit_span(span);
|
2019-02-09 16:29:31 +00:00
|
|
|
if let Some(parent_scope) = parent_scope {
|
2018-05-28 14:16:09 +03:00
|
|
|
self.visit_source_scope(parent_scope);
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
2020-02-08 21:31:09 +02:00
|
|
|
if let Some((callee, callsite_span)) = inlined {
|
|
|
|
let location = START_BLOCK.start_location();
|
|
|
|
|
|
|
|
self.visit_span(callsite_span);
|
|
|
|
|
|
|
|
let ty::Instance { def: callee_def, substs: callee_substs } = callee;
|
|
|
|
match callee_def {
|
|
|
|
ty::InstanceDef::Item(_def_id) => {}
|
|
|
|
|
|
|
|
ty::InstanceDef::Intrinsic(_def_id) |
|
|
|
|
ty::InstanceDef::VtableShim(_def_id) |
|
|
|
|
ty::InstanceDef::ReifyShim(_def_id) |
|
|
|
|
ty::InstanceDef::Virtual(_def_id, _) |
|
|
|
|
ty::InstanceDef::ClosureOnceShim { call_once: _def_id } |
|
|
|
|
ty::InstanceDef::DropGlue(_def_id, None) => {}
|
|
|
|
|
|
|
|
ty::InstanceDef::FnPtrShim(_def_id, ty) |
|
|
|
|
ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
|
|
|
|
ty::InstanceDef::CloneShim(_def_id, ty) => {
|
|
|
|
// FIXME(eddyb) use a better `TyContext` here.
|
|
|
|
self.visit_ty(ty, TyContext::Location(location));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.visit_substs(callee_substs, location);
|
|
|
|
}
|
2020-09-21 06:52:37 +03:00
|
|
|
if let Some(inlined_parent_scope) = inlined_parent_scope {
|
|
|
|
self.visit_source_scope(inlined_parent_scope);
|
|
|
|
}
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn super_statement(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
statement: & $($mutability)? Statement<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2016-03-24 06:12:19 -04:00
|
|
|
let Statement {
|
2019-02-09 16:29:31 +00:00
|
|
|
source_info,
|
|
|
|
kind,
|
|
|
|
} = statement;
|
2016-03-24 06:12:19 -04:00
|
|
|
|
2016-06-07 19:21:56 +03:00
|
|
|
self.visit_source_info(source_info);
|
2019-02-09 16:29:31 +00:00
|
|
|
match kind {
|
2019-09-11 16:05:45 -03:00
|
|
|
StatementKind::Assign(
|
|
|
|
box(ref $($mutability)? place, ref $($mutability)? rvalue)
|
|
|
|
) => {
|
2019-04-22 21:07:14 +01:00
|
|
|
self.visit_assign(place, rvalue, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2021-03-29 22:48:44 -04:00
|
|
|
StatementKind::FakeRead(box (_, place)) => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
|
|
|
|
location
|
|
|
|
);
|
2018-05-04 12:04:33 +02:00
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
StatementKind::SetDiscriminant { place, .. } => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Store),
|
|
|
|
location
|
|
|
|
);
|
2016-08-04 16:14:33 -07:00
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
StatementKind::StorageLive(local) => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_local(
|
|
|
|
local,
|
|
|
|
PlaceContext::NonUse(NonUseContext::StorageLive),
|
|
|
|
location
|
|
|
|
);
|
2016-08-14 06:34:14 +03:00
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
StatementKind::StorageDead(local) => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_local(
|
|
|
|
local,
|
|
|
|
PlaceContext::NonUse(NonUseContext::StorageDead),
|
|
|
|
location
|
|
|
|
);
|
2016-08-14 06:34:14 +03:00
|
|
|
}
|
2020-01-14 13:40:42 +00:00
|
|
|
StatementKind::LlvmInlineAsm(asm) => {
|
2019-04-02 20:07:09 +11:00
|
|
|
for output in & $($mutability)? asm.outputs[..] {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
output,
|
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput),
|
|
|
|
location
|
|
|
|
);
|
2017-02-15 21:21:36 +02:00
|
|
|
}
|
2019-04-02 20:07:09 +11:00
|
|
|
for (span, input) in & $($mutability)? asm.inputs[..] {
|
2018-10-15 00:00:53 +02:00
|
|
|
self.visit_span(span);
|
2017-02-15 21:21:36 +02:00
|
|
|
self.visit_operand(input, location);
|
|
|
|
}
|
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
StatementKind::Retag(kind, place) => {
|
2018-12-11 19:54:38 +01:00
|
|
|
self.visit_retag(kind, place, location);
|
2018-10-24 13:47:48 +02:00
|
|
|
}
|
2019-09-11 16:05:45 -03:00
|
|
|
StatementKind::AscribeUserType(
|
|
|
|
box(ref $($mutability)? place, ref $($mutability)? user_ty),
|
|
|
|
variance
|
|
|
|
) => {
|
2018-10-10 17:07:10 -04:00
|
|
|
self.visit_ascribe_user_ty(place, variance, user_ty, location);
|
2018-02-23 20:52:05 +00:00
|
|
|
}
|
2020-08-15 04:42:13 -07:00
|
|
|
StatementKind::Coverage(coverage) => {
|
|
|
|
self.visit_coverage(
|
|
|
|
coverage,
|
|
|
|
location
|
|
|
|
)
|
|
|
|
}
|
2020-10-03 20:57:47 +00:00
|
|
|
StatementKind::CopyNonOverlapping(box crate::mir::CopyNonOverlapping{
|
|
|
|
ref $($mutability)? src,
|
|
|
|
ref $($mutability)? dst,
|
2020-12-29 02:00:04 +00:00
|
|
|
ref $($mutability)? count,
|
2020-10-03 20:57:47 +00:00
|
|
|
}) => {
|
2020-12-29 02:00:04 +00:00
|
|
|
self.visit_operand(src, location);
|
|
|
|
self.visit_operand(dst, location);
|
|
|
|
self.visit_operand(count, location)
|
2020-10-03 20:57:47 +00:00
|
|
|
}
|
2016-09-15 18:17:58 -07:00
|
|
|
StatementKind::Nop => {}
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-11-03 06:33:59 -05:00
|
|
|
}
|
2015-12-08 14:07:25 -05:00
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn super_assign(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
place: &$($mutability)? Place<'tcx>,
|
|
|
|
rvalue: &$($mutability)? Rvalue<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Store),
|
|
|
|
location
|
|
|
|
);
|
2016-08-08 18:46:06 -07:00
|
|
|
self.visit_rvalue(rvalue, location);
|
2015-12-08 14:07:25 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn super_terminator(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
terminator: &$($mutability)? Terminator<'tcx>,
|
2020-06-10 10:03:26 +02:00
|
|
|
location: Location) {
|
2019-02-09 16:29:31 +00:00
|
|
|
let Terminator { source_info, kind } = terminator;
|
2016-03-24 06:12:19 -04:00
|
|
|
|
2016-06-07 19:21:56 +03:00
|
|
|
self.visit_source_info(source_info);
|
2019-02-09 16:29:31 +00:00
|
|
|
match kind {
|
2019-04-26 21:36:36 +01:00
|
|
|
TerminatorKind::Goto { .. } |
|
|
|
|
TerminatorKind::Resume |
|
|
|
|
TerminatorKind::Abort |
|
|
|
|
TerminatorKind::GeneratorDrop |
|
|
|
|
TerminatorKind::Unreachable |
|
2020-06-02 09:15:24 +02:00
|
|
|
TerminatorKind::FalseEdge { .. } |
|
2019-04-26 21:36:36 +01:00
|
|
|
TerminatorKind::FalseUnwind { .. } => {
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2020-05-09 16:08:04 +02:00
|
|
|
TerminatorKind::Return => {
|
|
|
|
// `return` logically moves from the return place `_0`. Note that the place
|
|
|
|
// cannot be changed by any visitor, though.
|
|
|
|
let $($mutability)? local = RETURN_PLACE;
|
|
|
|
self.visit_local(
|
|
|
|
& $($mutability)? local,
|
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
|
2020-06-10 10:03:26 +02:00
|
|
|
location,
|
2020-05-09 16:08:04 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
assert_eq!(
|
|
|
|
local,
|
|
|
|
RETURN_PLACE,
|
|
|
|
"`MutVisitor` tried to mutate return place of `return` terminator"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
TerminatorKind::SwitchInt {
|
|
|
|
discr,
|
|
|
|
switch_ty,
|
2019-04-26 21:36:36 +01:00
|
|
|
targets: _
|
2019-02-09 16:29:31 +00:00
|
|
|
} => {
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_operand(discr, location);
|
|
|
|
self.visit_ty(switch_ty, TyContext::Location(location));
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
TerminatorKind::Drop {
|
2020-06-10 09:56:54 +02:00
|
|
|
place,
|
2019-04-26 21:36:36 +01:00
|
|
|
target: _,
|
|
|
|
unwind: _,
|
2019-02-09 16:29:31 +00:00
|
|
|
} => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
2020-06-10 09:56:54 +02:00
|
|
|
place,
|
2018-10-26 13:22:45 +02:00
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Drop),
|
2020-06-10 10:03:26 +02:00
|
|
|
location
|
2018-10-26 13:22:45 +02:00
|
|
|
);
|
2016-05-17 01:06:52 +03:00
|
|
|
}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
TerminatorKind::DropAndReplace {
|
2020-06-10 09:56:54 +02:00
|
|
|
place,
|
2019-02-09 16:29:31 +00:00
|
|
|
value,
|
2019-04-26 21:36:36 +01:00
|
|
|
target: _,
|
|
|
|
unwind: _,
|
2019-02-09 16:29:31 +00:00
|
|
|
} => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
2020-06-10 09:56:54 +02:00
|
|
|
place,
|
2018-10-26 13:22:45 +02:00
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Drop),
|
2020-06-10 10:03:26 +02:00
|
|
|
location
|
2018-10-26 13:22:45 +02:00
|
|
|
);
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_operand(value, location);
|
2016-01-30 00:18:47 +02:00
|
|
|
}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
TerminatorKind::Call {
|
|
|
|
func,
|
|
|
|
args,
|
|
|
|
destination,
|
2019-04-26 21:36:36 +01:00
|
|
|
cleanup: _,
|
2019-02-09 16:29:31 +00:00
|
|
|
from_hir_call: _,
|
2020-06-09 15:34:23 -04:00
|
|
|
fn_span: _
|
2019-02-09 16:29:31 +00:00
|
|
|
} => {
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_operand(func, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
for arg in args {
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_operand(arg, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2019-04-26 21:36:36 +01:00
|
|
|
if let Some((destination, _)) = destination {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
destination,
|
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Call),
|
2020-06-10 10:03:26 +02:00
|
|
|
location
|
2018-10-26 13:22:45 +02:00
|
|
|
);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
|
|
|
}
|
2016-05-25 08:39:32 +03:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
TerminatorKind::Assert {
|
|
|
|
cond,
|
|
|
|
expected: _,
|
|
|
|
msg,
|
2019-04-26 21:36:36 +01:00
|
|
|
target: _,
|
|
|
|
cleanup: _,
|
2019-02-09 16:29:31 +00:00
|
|
|
} => {
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_operand(cond, location);
|
|
|
|
self.visit_assert_message(msg, location);
|
2016-05-25 08:39:32 +03:00
|
|
|
}
|
2016-12-26 14:34:03 +01:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
TerminatorKind::Yield {
|
|
|
|
value,
|
2019-04-26 21:36:36 +01:00
|
|
|
resume: _,
|
2020-01-25 02:30:46 +01:00
|
|
|
resume_arg,
|
2019-04-26 21:36:36 +01:00
|
|
|
drop: _,
|
2019-02-09 16:29:31 +00:00
|
|
|
} => {
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_operand(value, location);
|
2020-01-25 02:30:46 +01:00
|
|
|
self.visit_place(
|
|
|
|
resume_arg,
|
2020-04-02 10:54:24 -07:00
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Yield),
|
2020-06-10 10:03:26 +02:00
|
|
|
location,
|
2020-01-25 02:30:46 +01:00
|
|
|
);
|
2016-12-26 14:34:03 +01:00
|
|
|
}
|
|
|
|
|
2020-02-14 18:17:50 +00:00
|
|
|
TerminatorKind::InlineAsm {
|
|
|
|
template: _,
|
|
|
|
operands,
|
|
|
|
options: _,
|
2020-05-26 20:07:59 +01:00
|
|
|
line_spans: _,
|
2020-02-14 18:17:50 +00:00
|
|
|
destination: _,
|
|
|
|
} => {
|
|
|
|
for op in operands {
|
|
|
|
match op {
|
2021-04-06 05:50:55 +01:00
|
|
|
InlineAsmOperand::In { value, .. } => {
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_operand(value, location);
|
2020-02-14 18:17:50 +00:00
|
|
|
}
|
2021-08-16 17:30:23 +02:00
|
|
|
InlineAsmOperand::Out { place: Some(place), .. } => {
|
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Store),
|
|
|
|
location,
|
|
|
|
);
|
2020-02-14 18:17:50 +00:00
|
|
|
}
|
|
|
|
InlineAsmOperand::InOut { in_value, out_place, .. } => {
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_operand(in_value, location);
|
2020-02-14 18:17:50 +00:00
|
|
|
if let Some(out_place) = out_place {
|
|
|
|
self.visit_place(
|
|
|
|
out_place,
|
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Store),
|
2020-06-10 10:03:26 +02:00
|
|
|
location,
|
2020-02-14 18:17:50 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-04-06 05:50:55 +01:00
|
|
|
InlineAsmOperand::Const { value }
|
|
|
|
| InlineAsmOperand::SymFn { value } => {
|
2020-06-10 10:03:26 +02:00
|
|
|
self.visit_constant(value, location);
|
2020-02-14 18:17:50 +00:00
|
|
|
}
|
2021-08-16 17:30:23 +02:00
|
|
|
InlineAsmOperand::Out { place: None, .. }
|
|
|
|
| InlineAsmOperand::SymStatic { def_id: _ } => {}
|
2020-02-14 18:17:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-05-25 08:39:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn super_assert_message(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
msg: & $($mutability)? AssertMessage<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2020-02-12 19:40:31 +01:00
|
|
|
use crate::mir::AssertKind::*;
|
2019-07-24 10:24:55 +02:00
|
|
|
match msg {
|
|
|
|
BoundsCheck { len, index } => {
|
|
|
|
self.visit_operand(len, location);
|
|
|
|
self.visit_operand(index, location);
|
|
|
|
}
|
2020-06-19 18:57:15 +02:00
|
|
|
Overflow(_, l, r) => {
|
|
|
|
self.visit_operand(l, location);
|
|
|
|
self.visit_operand(r, location);
|
|
|
|
}
|
|
|
|
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
|
|
|
|
self.visit_operand(op, location);
|
|
|
|
}
|
2019-11-26 00:30:07 +00:00
|
|
|
ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
|
2019-07-24 10:24:55 +02:00
|
|
|
// Nothing to visit
|
|
|
|
}
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn super_rvalue(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
rvalue: & $($mutability)? Rvalue<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2019-02-09 16:29:31 +00:00
|
|
|
match rvalue {
|
|
|
|
Rvalue::Use(operand) => {
|
2016-08-08 18:46:06 -07:00
|
|
|
self.visit_operand(operand, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
Rvalue::Repeat(value, _) => {
|
2016-08-08 18:46:06 -07:00
|
|
|
self.visit_operand(value, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2020-05-02 21:44:25 +02:00
|
|
|
Rvalue::ThreadLocalRef(_) => {}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
Rvalue::Ref(r, bk, path) => {
|
2017-08-04 11:25:13 +03:00
|
|
|
self.visit_region(r, location);
|
2018-10-26 13:22:45 +02:00
|
|
|
let ctx = match bk {
|
|
|
|
BorrowKind::Shared => PlaceContext::NonMutatingUse(
|
2019-04-24 19:41:43 +01:00
|
|
|
NonMutatingUseContext::SharedBorrow
|
2018-10-26 13:22:45 +02:00
|
|
|
),
|
|
|
|
BorrowKind::Shallow => PlaceContext::NonMutatingUse(
|
2019-04-24 19:41:43 +01:00
|
|
|
NonMutatingUseContext::ShallowBorrow
|
2018-10-26 13:22:45 +02:00
|
|
|
),
|
|
|
|
BorrowKind::Unique => PlaceContext::NonMutatingUse(
|
2019-04-24 19:41:43 +01:00
|
|
|
NonMutatingUseContext::UniqueBorrow
|
2018-10-26 13:22:45 +02:00
|
|
|
),
|
|
|
|
BorrowKind::Mut { .. } =>
|
2019-04-24 19:41:43 +01:00
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Borrow),
|
2018-10-26 13:22:45 +02:00
|
|
|
};
|
|
|
|
self.visit_place(path, ctx, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2018-12-23 19:00:58 +00:00
|
|
|
Rvalue::AddressOf(m, path) => {
|
|
|
|
let ctx = match m {
|
|
|
|
Mutability::Mut => PlaceContext::MutatingUse(
|
|
|
|
MutatingUseContext::AddressOf
|
|
|
|
),
|
|
|
|
Mutability::Not => PlaceContext::NonMutatingUse(
|
|
|
|
NonMutatingUseContext::AddressOf
|
|
|
|
),
|
|
|
|
};
|
|
|
|
self.visit_place(path, ctx, location);
|
|
|
|
}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
Rvalue::Len(path) => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
path,
|
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
|
|
|
|
location
|
|
|
|
);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
Rvalue::Cast(_cast_kind, operand, ty) => {
|
2016-08-08 18:46:06 -07:00
|
|
|
self.visit_operand(operand, location);
|
2017-10-26 19:53:31 -04:00
|
|
|
self.visit_ty(ty, TyContext::Location(location));
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2021-03-05 09:32:47 +00:00
|
|
|
Rvalue::BinaryOp(_bin_op, box(lhs, rhs))
|
|
|
|
| Rvalue::CheckedBinaryOp(_bin_op, box(lhs, rhs)) => {
|
2016-08-08 18:46:06 -07:00
|
|
|
self.visit_operand(lhs, location);
|
|
|
|
self.visit_operand(rhs, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
Rvalue::UnaryOp(_un_op, op) => {
|
2016-08-08 18:46:06 -07:00
|
|
|
self.visit_operand(op, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
Rvalue::Discriminant(place) => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect),
|
|
|
|
location
|
|
|
|
);
|
2017-01-31 01:10:54 +02:00
|
|
|
}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
Rvalue::NullaryOp(_op, ty) => {
|
2017-10-26 19:53:31 -04:00
|
|
|
self.visit_ty(ty, TyContext::Location(location));
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
Rvalue::Aggregate(kind, operands) => {
|
|
|
|
let kind = &$($mutability)? **kind;
|
|
|
|
match kind {
|
|
|
|
AggregateKind::Array(ty) => {
|
2017-10-26 19:53:31 -04:00
|
|
|
self.visit_ty(ty, TyContext::Location(location));
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
AggregateKind::Tuple => {
|
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
AggregateKind::Adt(
|
|
|
|
_adt_def,
|
|
|
|
_variant_index,
|
|
|
|
substs,
|
|
|
|
_user_substs,
|
|
|
|
_active_field_index
|
|
|
|
) => {
|
2017-07-18 22:31:38 -04:00
|
|
|
self.visit_substs(substs, location);
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
AggregateKind::Closure(
|
2019-04-26 21:36:36 +01:00
|
|
|
_,
|
2019-02-09 16:29:31 +00:00
|
|
|
closure_substs
|
|
|
|
) => {
|
2019-09-26 17:30:44 +00:00
|
|
|
self.visit_substs(closure_substs, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
AggregateKind::Generator(
|
2019-04-26 21:36:36 +01:00
|
|
|
_,
|
2019-02-09 16:29:31 +00:00
|
|
|
generator_substs,
|
|
|
|
_movability,
|
|
|
|
) => {
|
2019-10-03 21:30:26 +08:00
|
|
|
self.visit_substs(generator_substs, location);
|
2016-12-26 14:34:03 +01:00
|
|
|
}
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
|
|
|
|
2016-03-24 06:12:19 -04:00
|
|
|
for operand in operands {
|
2016-08-08 18:46:06 -07:00
|
|
|
self.visit_operand(operand, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn super_operand(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
operand: & $($mutability)? Operand<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2019-02-09 16:29:31 +00:00
|
|
|
match operand {
|
|
|
|
Operand::Copy(place) => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
|
|
|
location
|
|
|
|
);
|
2017-11-17 17:19:57 +02:00
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
Operand::Move(place) => {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move),
|
|
|
|
location
|
|
|
|
);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2019-02-09 16:29:31 +00:00
|
|
|
Operand::Constant(constant) => {
|
2016-08-08 18:46:06 -07:00
|
|
|
self.visit_constant(constant, location);
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-31 18:59:35 -04:00
|
|
|
fn super_ascribe_user_ty(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
place: & $($mutability)? Place<'tcx>,
|
|
|
|
_variance: & $($mutability)? ty::Variance,
|
2019-03-28 18:00:17 -07:00
|
|
|
user_ty: & $($mutability)? UserTypeProjection,
|
2018-08-31 18:59:35 -04:00
|
|
|
location: Location) {
|
2018-10-26 13:22:45 +02:00
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::NonUse(NonUseContext::AscribeUserTy),
|
|
|
|
location
|
|
|
|
);
|
2018-10-22 11:58:06 +02:00
|
|
|
self.visit_user_type_projection(user_ty);
|
2018-02-23 20:52:05 +00:00
|
|
|
}
|
|
|
|
|
2020-08-15 04:42:13 -07:00
|
|
|
fn super_coverage(&mut self,
|
Updates to experimental coverage counter injection
This is a combination of 18 commits.
Commit #2:
Additional examples and some small improvements.
Commit #3:
fixed mir-opt non-mir extensions and spanview title elements
Corrected a fairly recent assumption in runtest.rs that all MIR dump
files end in .mir. (It was appending .mir to the graphviz .dot and
spanview .html file names when generating blessed output files. That
also left outdated files in the baseline alongside the files with the
incorrect names, which I've now removed.)
Updated spanview HTML title elements to match their content, replacing a
hardcoded and incorrect name that was left in accidentally when
originally submitted.
Commit #4:
added more test examples
also improved Makefiles with support for non-zero exit status and to
force validation of tests unless a specific test overrides it with a
specific comment.
Commit #5:
Fixed rare issues after testing on real-world crate
Commit #6:
Addressed PR feedback, and removed temporary -Zexperimental-coverage
-Zinstrument-coverage once again supports the latest capabilities of
LLVM instrprof coverage instrumentation.
Also fixed a bug in spanview.
Commit #7:
Fix closure handling, add tests for closures and inner items
And cleaned up other tests for consistency, and to make it more clear
where spans start/end by breaking up lines.
Commit #8:
renamed "typical" test results "expected"
Now that the `llvm-cov show` tests are improved to normally expect
matching actuals, and to allow individual tests to override that
expectation.
Commit #9:
test coverage of inline generic struct function
Commit #10:
Addressed review feedback
* Removed unnecessary Unreachable filter.
* Replaced a match wildcard with remining variants.
* Added more comments to help clarify the role of successors() in the
CFG traversal
Commit #11:
refactoring based on feedback
* refactored `fn coverage_spans()`.
* changed the way I expand an empty coverage span to improve performance
* fixed a typo that I had accidently left in, in visit.rs
Commit #12:
Optimized use of SourceMap and SourceFile
Commit #13:
Fixed a regression, and synched with upstream
Some generated test file names changed due to some new change upstream.
Commit #14:
Stripping out crate disambiguators from demangled names
These can vary depending on the test platform.
Commit #15:
Ignore llvm-cov show diff on test with generics, expand IO error message
Tests with generics produce llvm-cov show results with demangled names
that can include an unstable "crate disambiguator" (hex value). The
value changes when run in the Rust CI Windows environment. I added a sed
filter to strip them out (in a prior commit), but sed also appears to
fail in the same environment. Until I can figure out a workaround, I'm
just going to ignore this specific test result. I added a FIXME to
follow up later, but it's not that critical.
I also saw an error with Windows GNU, but the IO error did not
specify a path for the directory or file that triggered the error. I
updated the error messages to provide more info for next, time but also
noticed some other tests with similar steps did not fail. Looks
spurious.
Commit #16:
Modify rust-demangler to strip disambiguators by default
Commit #17:
Remove std::process::exit from coverage tests
Due to Issue #77553, programs that call std::process::exit() do not
generate coverage results on Windows MSVC.
Commit #18:
fix: test file paths exceeding Windows max path len
2020-09-01 16:15:17 -07:00
|
|
|
_coverage: & $($mutability)? Coverage,
|
2020-08-15 04:42:13 -07:00
|
|
|
_location: Location) {
|
|
|
|
}
|
|
|
|
|
2018-10-24 13:47:48 +02:00
|
|
|
fn super_retag(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
_kind: & $($mutability)? RetagKind,
|
|
|
|
place: & $($mutability)? Place<'tcx>,
|
2018-10-24 13:47:48 +02:00
|
|
|
location: Location) {
|
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Retag),
|
|
|
|
location,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-09-25 01:38:27 +02:00
|
|
|
fn super_local_decl(&mut self,
|
2017-10-26 19:53:31 -04:00
|
|
|
local: Local,
|
2019-02-09 16:29:31 +00:00
|
|
|
local_decl: & $($mutability)? LocalDecl<'tcx>) {
|
2016-09-25 01:38:27 +02:00
|
|
|
let LocalDecl {
|
2016-03-24 06:12:19 -04:00
|
|
|
mutability: _,
|
2019-02-09 16:29:31 +00:00
|
|
|
ty,
|
|
|
|
user_ty,
|
|
|
|
source_info,
|
2018-05-29 17:37:24 +03:00
|
|
|
internal: _,
|
2019-11-18 23:04:06 +00:00
|
|
|
local_info: _,
|
2018-09-22 00:51:48 +02:00
|
|
|
is_block_tail: _,
|
2019-02-09 16:29:31 +00:00
|
|
|
} = local_decl;
|
2016-03-24 06:12:19 -04:00
|
|
|
|
2017-10-26 19:53:31 -04:00
|
|
|
self.visit_ty(ty, TyContext::LocalDecl {
|
|
|
|
local,
|
2018-05-29 21:31:33 +03:00
|
|
|
source_info: *source_info,
|
2017-10-26 19:53:31 -04:00
|
|
|
});
|
2020-05-06 12:41:15 +10:00
|
|
|
if let Some(user_ty) = user_ty {
|
|
|
|
for (user_ty, _) in & $($mutability)? user_ty.contents {
|
|
|
|
self.visit_user_type_projection(user_ty);
|
|
|
|
}
|
2018-09-10 10:54:31 -04:00
|
|
|
}
|
2018-05-29 21:31:33 +03:00
|
|
|
self.visit_source_info(source_info);
|
2018-05-16 18:58:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn super_var_debug_info(&mut self,
|
|
|
|
var_debug_info: & $($mutability)? VarDebugInfo<'tcx>) {
|
|
|
|
let VarDebugInfo {
|
|
|
|
name: _,
|
|
|
|
source_info,
|
2020-05-30 15:02:32 -04:00
|
|
|
value,
|
2018-05-16 18:58:54 +03:00
|
|
|
} = var_debug_info;
|
|
|
|
|
|
|
|
self.visit_source_info(source_info);
|
|
|
|
let location = START_BLOCK.start_location();
|
2020-05-30 15:02:32 -04:00
|
|
|
match value {
|
|
|
|
VarDebugInfoContents::Const(c) => self.visit_constant(c, location),
|
|
|
|
VarDebugInfoContents::Place(place) =>
|
|
|
|
self.visit_place(
|
|
|
|
place,
|
|
|
|
PlaceContext::NonUse(NonUseContext::VarDebugInfo),
|
|
|
|
location
|
|
|
|
),
|
|
|
|
}
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2018-05-28 14:16:09 +03:00
|
|
|
fn super_source_scope(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
_scope: & $($mutability)? SourceScope) {
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
fn super_constant(&mut self,
|
2019-02-09 16:29:31 +00:00
|
|
|
constant: & $($mutability)? Constant<'tcx>,
|
2016-08-08 18:46:06 -07:00
|
|
|
location: Location) {
|
2016-03-25 13:10:32 -04:00
|
|
|
let Constant {
|
2019-02-09 16:29:31 +00:00
|
|
|
span,
|
|
|
|
user_ty,
|
|
|
|
literal,
|
|
|
|
} = constant;
|
2016-03-25 13:10:32 -04:00
|
|
|
|
|
|
|
self.visit_span(span);
|
2018-08-09 06:18:00 -04:00
|
|
|
drop(user_ty); // no visit method for this
|
2021-03-08 16:18:03 +00:00
|
|
|
match literal {
|
2021-03-15 11:23:44 +00:00
|
|
|
ConstantKind::Ty(ct) => self.visit_const(ct, location),
|
|
|
|
ConstantKind::Val(_, t) => self.visit_ty(t, TyContext::Location(location)),
|
2021-03-08 16:18:03 +00:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
fn super_span(&mut self, _span: & $($mutability)? Span) {
|
2015-12-08 14:09:16 -05:00
|
|
|
}
|
2016-03-24 06:12:19 -04:00
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
fn super_source_info(&mut self, source_info: & $($mutability)? SourceInfo) {
|
2016-06-07 19:21:56 +03:00
|
|
|
let SourceInfo {
|
2019-02-09 16:29:31 +00:00
|
|
|
span,
|
|
|
|
scope,
|
|
|
|
} = source_info;
|
2016-06-07 19:21:56 +03:00
|
|
|
|
|
|
|
self.visit_span(span);
|
2018-05-28 14:16:09 +03:00
|
|
|
self.visit_source_scope(scope);
|
2016-06-07 19:21:56 +03:00
|
|
|
}
|
|
|
|
|
2018-10-22 11:58:06 +02:00
|
|
|
fn super_user_type_projection(
|
|
|
|
&mut self,
|
2019-03-28 18:00:17 -07:00
|
|
|
_ty: & $($mutability)? UserTypeProjection,
|
2018-10-22 11:58:06 +02:00
|
|
|
) {
|
|
|
|
}
|
|
|
|
|
2018-10-15 09:31:38 -04:00
|
|
|
fn super_user_type_annotation(
|
|
|
|
&mut self,
|
2018-11-16 22:56:18 +01:00
|
|
|
_index: UserTypeAnnotationIndex,
|
2019-02-09 16:29:31 +00:00
|
|
|
ty: & $($mutability)? CanonicalUserTypeAnnotation<'tcx>,
|
2018-10-15 09:31:38 -04:00
|
|
|
) {
|
2019-02-09 16:29:31 +00:00
|
|
|
self.visit_span(& $($mutability)? ty.span);
|
|
|
|
self.visit_ty(& $($mutability)? ty.inferred_ty, TyContext::UserTy(ty.span));
|
2018-08-09 06:18:00 -04:00
|
|
|
}
|
|
|
|
|
2019-04-25 22:54:19 +02:00
|
|
|
fn super_ty(&mut self, _ty: $(& $mutability)? Ty<'tcx>) {
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2019-02-09 16:29:31 +00:00
|
|
|
fn super_region(&mut self, _region: & $($mutability)? ty::Region<'tcx>) {
|
2017-08-04 11:25:13 +03:00
|
|
|
}
|
|
|
|
|
2019-03-14 10:19:31 +01:00
|
|
|
fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) {
|
2017-08-04 11:25:13 +03:00
|
|
|
}
|
|
|
|
|
2019-02-09 22:11:53 +08:00
|
|
|
fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
|
2016-03-24 06:12:19 -04:00
|
|
|
}
|
|
|
|
|
2016-09-15 18:18:40 -07:00
|
|
|
// Convenience methods
|
2019-10-04 00:55:28 -04:00
|
|
|
|
2019-10-10 23:16:44 -04:00
|
|
|
fn visit_location(
|
|
|
|
&mut self,
|
2020-04-12 10:31:00 -07:00
|
|
|
body: &$($mutability)? Body<'tcx>,
|
2019-10-10 23:16:44 -04:00
|
|
|
location: Location
|
|
|
|
) {
|
2020-04-12 10:31:00 -07:00
|
|
|
macro_rules! basic_blocks {
|
|
|
|
(mut) => (body.basic_blocks_mut());
|
|
|
|
() => (body.basic_blocks());
|
2020-11-25 17:00:28 -05:00
|
|
|
}
|
2020-04-12 10:31:00 -07:00
|
|
|
let basic_block = & $($mutability)? basic_blocks!($($mutability)?)[location.block];
|
2019-10-04 00:55:28 -04:00
|
|
|
if basic_block.statements.len() == location.statement_index {
|
|
|
|
if let Some(ref $($mutability)? terminator) = basic_block.terminator {
|
|
|
|
self.visit_terminator(terminator, location)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let statement = & $($mutability)?
|
|
|
|
basic_block.statements[location.statement_index];
|
|
|
|
self.visit_statement(statement, location)
|
2016-09-15 18:18:40 -07:00
|
|
|
}
|
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
}
|
|
|
|
}
|
2016-01-07 05:49:46 -05:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2019-10-08 12:16:26 -03:00
|
|
|
macro_rules! visit_place_fns {
|
2020-04-11 01:39:50 +02:00
|
|
|
(mut) => {
|
2019-10-20 16:11:04 -04:00
|
|
|
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;
|
|
|
|
|
2019-10-08 12:16:26 -03:00
|
|
|
fn super_place(
|
|
|
|
&mut self,
|
2019-10-08 15:33:19 -03:00
|
|
|
place: &mut Place<'tcx>,
|
|
|
|
context: PlaceContext,
|
|
|
|
location: Location,
|
2019-10-08 12:16:26 -03:00
|
|
|
) {
|
2020-04-21 17:11:00 -03:00
|
|
|
self.visit_local(&mut place.local, context, location);
|
2019-10-08 15:33:19 -03:00
|
|
|
|
2020-04-11 01:39:50 +02:00
|
|
|
if let Some(new_projection) = self.process_projection(&place.projection, location) {
|
2019-10-20 16:11:04 -04:00
|
|
|
place.projection = self.tcx().intern_place_elems(&new_projection);
|
2019-10-08 23:46:14 -03:00
|
|
|
}
|
2019-10-08 15:33:19 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn process_projection(
|
|
|
|
&mut self,
|
2019-10-08 23:46:14 -03:00
|
|
|
projection: &'a [PlaceElem<'tcx>],
|
2020-04-11 01:39:50 +02:00
|
|
|
location: Location,
|
2019-10-20 16:11:04 -04:00
|
|
|
) -> Option<Vec<PlaceElem<'tcx>>> {
|
2019-10-08 23:46:14 -03:00
|
|
|
let mut projection = Cow::Borrowed(projection);
|
2019-10-08 15:33:19 -03:00
|
|
|
|
2019-10-08 23:46:14 -03:00
|
|
|
for i in 0..projection.len() {
|
2020-05-23 12:02:54 +02:00
|
|
|
if let Some(&elem) = projection.get(i) {
|
2020-04-11 01:39:50 +02:00
|
|
|
if let Some(elem) = self.process_projection_elem(elem, location) {
|
2019-10-20 16:11:04 -04:00
|
|
|
// This converts the borrowed projection into `Cow::Owned(_)` and returns a
|
|
|
|
// clone of the projection so we can mutate and reintern later.
|
2019-10-08 23:46:14 -03:00
|
|
|
let vec = projection.to_mut();
|
|
|
|
vec[i] = elem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
match projection {
|
|
|
|
Cow::Borrowed(_) => None,
|
2019-10-20 16:11:04 -04:00
|
|
|
Cow::Owned(vec) => Some(vec),
|
2019-10-08 23:46:14 -03:00
|
|
|
}
|
2019-10-08 15:33:19 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn process_projection_elem(
|
|
|
|
&mut self,
|
2020-05-23 12:02:54 +02:00
|
|
|
elem: PlaceElem<'tcx>,
|
2020-04-11 01:39:50 +02:00
|
|
|
location: Location,
|
2019-10-08 23:46:14 -03:00
|
|
|
) -> Option<PlaceElem<'tcx>> {
|
2020-04-11 01:39:50 +02:00
|
|
|
match elem {
|
|
|
|
PlaceElem::Index(local) => {
|
2020-05-23 12:02:54 +02:00
|
|
|
let mut new_local = local;
|
2020-04-11 01:39:50 +02:00
|
|
|
self.visit_local(
|
|
|
|
&mut new_local,
|
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
|
|
|
location,
|
|
|
|
);
|
|
|
|
|
2020-05-23 12:02:54 +02:00
|
|
|
if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
|
2020-04-11 01:39:50 +02:00
|
|
|
}
|
|
|
|
PlaceElem::Deref
|
|
|
|
| PlaceElem::Field(..)
|
|
|
|
| PlaceElem::ConstantIndex { .. }
|
|
|
|
| PlaceElem::Subslice { .. }
|
|
|
|
| PlaceElem::Downcast(..) => None,
|
|
|
|
}
|
2019-10-08 12:16:26 -03:00
|
|
|
}
|
2020-04-11 01:39:50 +02:00
|
|
|
};
|
2019-10-08 12:16:26 -03:00
|
|
|
|
2020-04-11 01:39:50 +02:00
|
|
|
() => {
|
2019-10-08 12:16:26 -03:00
|
|
|
fn visit_projection(
|
|
|
|
&mut self,
|
2021-02-16 14:20:36 +05:30
|
|
|
place_ref: PlaceRef<'tcx>,
|
2019-10-08 12:16:26 -03:00
|
|
|
context: PlaceContext,
|
|
|
|
location: Location,
|
|
|
|
) {
|
2021-02-20 16:46:05 +05:30
|
|
|
self.super_projection(place_ref, context, location);
|
2019-10-08 12:16:26 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_projection_elem(
|
|
|
|
&mut self,
|
2020-03-06 18:22:17 -03:00
|
|
|
local: Local,
|
2019-10-08 12:16:26 -03:00
|
|
|
proj_base: &[PlaceElem<'tcx>],
|
2020-05-23 12:02:54 +02:00
|
|
|
elem: PlaceElem<'tcx>,
|
2019-10-08 12:16:26 -03:00
|
|
|
context: PlaceContext,
|
|
|
|
location: Location,
|
|
|
|
) {
|
2019-12-11 16:50:03 -03:00
|
|
|
self.super_projection_elem(local, proj_base, elem, context, location);
|
2019-10-08 12:16:26 -03:00
|
|
|
}
|
|
|
|
|
2020-04-11 01:39:50 +02:00
|
|
|
fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
2019-10-08 12:16:26 -03:00
|
|
|
let mut context = context;
|
|
|
|
|
|
|
|
if !place.projection.is_empty() {
|
2020-11-15 12:58:34 -08:00
|
|
|
if context.is_use() {
|
2020-11-22 17:33:06 -08:00
|
|
|
// ^ Only change the context if it is a real use, not a "use" in debuginfo.
|
2020-11-15 12:58:34 -08:00
|
|
|
context = if context.is_mutating_use() {
|
|
|
|
PlaceContext::MutatingUse(MutatingUseContext::Projection)
|
|
|
|
} else {
|
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
|
|
|
|
};
|
|
|
|
}
|
2019-10-08 12:16:26 -03:00
|
|
|
}
|
|
|
|
|
2020-04-21 17:11:00 -03:00
|
|
|
self.visit_local(&place.local, context, location);
|
2019-10-08 12:16:26 -03:00
|
|
|
|
2021-02-16 14:20:36 +05:30
|
|
|
self.visit_projection(place.as_ref(), context, location);
|
2019-10-08 12:16:26 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
fn super_projection(
|
|
|
|
&mut self,
|
2021-02-20 16:46:05 +05:30
|
|
|
place_ref: PlaceRef<'tcx>,
|
2019-10-08 12:16:26 -03:00
|
|
|
context: PlaceContext,
|
|
|
|
location: Location,
|
|
|
|
) {
|
2021-02-20 16:46:05 +05:30
|
|
|
// FIXME: Use PlaceRef::iter_projections, once that exists.
|
|
|
|
let mut cursor = place_ref.projection;
|
2020-05-23 12:02:54 +02:00
|
|
|
while let &[ref proj_base @ .., elem] = cursor {
|
2019-10-08 12:16:26 -03:00
|
|
|
cursor = proj_base;
|
2021-02-20 16:46:05 +05:30
|
|
|
self.visit_projection_elem(place_ref.local, cursor, elem, context, location);
|
2019-10-08 12:16:26 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn super_projection_elem(
|
|
|
|
&mut self,
|
2020-03-06 18:22:17 -03:00
|
|
|
_local: Local,
|
2019-10-08 12:16:26 -03:00
|
|
|
_proj_base: &[PlaceElem<'tcx>],
|
2020-05-23 12:02:54 +02:00
|
|
|
elem: PlaceElem<'tcx>,
|
2019-10-08 12:16:26 -03:00
|
|
|
_context: PlaceContext,
|
|
|
|
location: Location,
|
|
|
|
) {
|
|
|
|
match elem {
|
|
|
|
ProjectionElem::Field(_field, ty) => {
|
|
|
|
self.visit_ty(ty, TyContext::Location(location));
|
|
|
|
}
|
|
|
|
ProjectionElem::Index(local) => {
|
|
|
|
self.visit_local(
|
2020-05-23 12:02:54 +02:00
|
|
|
&local,
|
2019-10-08 12:16:26 -03:00
|
|
|
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
|
2020-04-11 01:39:50 +02:00
|
|
|
location,
|
2019-10-08 12:16:26 -03:00
|
|
|
);
|
|
|
|
}
|
2020-04-11 01:39:50 +02:00
|
|
|
ProjectionElem::Deref
|
|
|
|
| ProjectionElem::Subslice { from: _, to: _, from_end: _ }
|
|
|
|
| ProjectionElem::ConstantIndex { offset: _, min_length: _, from_end: _ }
|
|
|
|
| ProjectionElem::Downcast(_, _) => {}
|
2019-10-08 12:16:26 -03:00
|
|
|
}
|
|
|
|
}
|
2020-04-11 01:39:50 +02:00
|
|
|
};
|
2019-10-08 12:16:26 -03:00
|
|
|
}
|
|
|
|
|
2016-01-07 05:49:46 -05:00
|
|
|
make_mir_visitor!(Visitor,);
|
2019-12-22 17:42:04 -05:00
|
|
|
make_mir_visitor!(MutVisitor, mut);
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2017-12-12 11:59:09 -03:00
|
|
|
pub trait MirVisitable<'tcx> {
|
|
|
|
fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> MirVisitable<'tcx> for Statement<'tcx> {
|
2019-12-22 17:42:04 -05:00
|
|
|
fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
|
2019-04-22 21:07:14 +01:00
|
|
|
visitor.visit_statement(self, location)
|
2017-12-12 11:59:09 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> MirVisitable<'tcx> for Terminator<'tcx> {
|
2019-12-22 17:42:04 -05:00
|
|
|
fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
|
2019-04-22 21:07:14 +01:00
|
|
|
visitor.visit_terminator(self, location)
|
2017-12-12 11:59:09 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> MirVisitable<'tcx> for Option<Terminator<'tcx>> {
|
2019-12-22 17:42:04 -05:00
|
|
|
fn apply(&self, location: Location, visitor: &mut dyn Visitor<'tcx>) {
|
2019-04-22 21:07:14 +01:00
|
|
|
visitor.visit_terminator(self.as_ref().unwrap(), location)
|
2017-12-12 11:59:09 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-26 19:53:31 -04:00
|
|
|
/// Extra information passed to `visit_ty` and friends to give context
|
|
|
|
/// about where the type etc appears.
|
2019-10-20 15:54:53 +11:00
|
|
|
#[derive(Debug)]
|
2017-10-26 19:53:31 -04:00
|
|
|
pub enum TyContext {
|
|
|
|
LocalDecl {
|
|
|
|
/// The index of the local variable we are visiting.
|
|
|
|
local: Local,
|
|
|
|
|
|
|
|
/// The source location where this local variable was declared.
|
|
|
|
source_info: SourceInfo,
|
|
|
|
},
|
|
|
|
|
2019-01-12 14:55:23 +00:00
|
|
|
/// The inferred type of a user type annotation.
|
|
|
|
UserTy(Span),
|
|
|
|
|
2017-11-07 04:30:06 -05:00
|
|
|
/// The return type of the function.
|
|
|
|
ReturnTy(SourceInfo),
|
2017-10-26 19:53:31 -04:00
|
|
|
|
2018-01-19 19:18:02 -03:00
|
|
|
YieldTy(SourceInfo),
|
|
|
|
|
2017-11-07 04:30:06 -05:00
|
|
|
/// A type found at some location.
|
|
|
|
Location(Location),
|
2017-07-18 22:31:38 -04:00
|
|
|
}
|
|
|
|
|
2016-08-16 04:59:50 +03:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2019-04-24 19:41:43 +01:00
|
|
|
pub enum NonMutatingUseContext {
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Being inspected in some way, like loading a len.
|
|
|
|
Inspect,
|
|
|
|
/// Consumed as part of an operand.
|
|
|
|
Copy,
|
|
|
|
/// Consumed as part of an operand.
|
|
|
|
Move,
|
|
|
|
/// Shared borrow.
|
2019-04-24 19:41:43 +01:00
|
|
|
SharedBorrow,
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Shallow borrow.
|
2019-04-24 19:41:43 +01:00
|
|
|
ShallowBorrow,
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Unique borrow.
|
2019-04-24 19:41:43 +01:00
|
|
|
UniqueBorrow,
|
2018-12-23 19:00:58 +00:00
|
|
|
/// AddressOf for *const pointer.
|
|
|
|
AddressOf,
|
2018-11-27 02:59:49 +00:00
|
|
|
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
|
2018-10-26 13:22:45 +02:00
|
|
|
/// For example, the projection `x.y` is not marked as a mutation in these cases:
|
|
|
|
///
|
|
|
|
/// z = x.y;
|
|
|
|
/// f(&x.y);
|
|
|
|
///
|
|
|
|
Projection,
|
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2018-10-26 13:22:45 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2019-04-24 19:41:43 +01:00
|
|
|
pub enum MutatingUseContext {
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Appears as LHS of an assignment.
|
|
|
|
Store,
|
|
|
|
/// Can often be treated as a `Store`, but needs to be separate because
|
|
|
|
/// ASM is allowed to read outputs as well, so a `Store`-`AsmOutput` sequence
|
|
|
|
/// cannot be simplified the way a `Store`-`Store` can be.
|
2017-12-19 17:05:14 -05:00
|
|
|
AsmOutput,
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Destination of a call.
|
2016-04-04 19:21:27 +12:00
|
|
|
Call,
|
2020-04-02 10:54:24 -07:00
|
|
|
/// Destination of a yield.
|
|
|
|
Yield,
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Being dropped.
|
2016-01-07 05:49:46 -05:00
|
|
|
Drop,
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Mutable borrow.
|
2019-04-24 19:41:43 +01:00
|
|
|
Borrow,
|
2018-12-23 19:00:58 +00:00
|
|
|
/// AddressOf for *mut pointer.
|
|
|
|
AddressOf,
|
2018-11-27 02:59:49 +00:00
|
|
|
/// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
|
2018-10-26 13:22:45 +02:00
|
|
|
/// For example, the projection `x.y` is marked as a mutation in these cases:
|
|
|
|
///
|
|
|
|
/// x.y = ...;
|
|
|
|
/// f(&mut x.y);
|
|
|
|
///
|
|
|
|
Projection,
|
2018-11-06 11:04:10 +01:00
|
|
|
/// Retagging, a "Stacked Borrows" shadow state operation
|
2018-10-24 11:47:17 +02:00
|
|
|
Retag,
|
2018-10-26 13:22:45 +02:00
|
|
|
}
|
2015-12-08 14:09:16 -05:00
|
|
|
|
2018-10-26 13:22:45 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub enum NonUseContext {
|
|
|
|
/// Starting a storage live range.
|
2016-08-14 06:34:14 +03:00
|
|
|
StorageLive,
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Ending a storage live range.
|
2016-08-14 06:34:14 +03:00
|
|
|
StorageDead,
|
2018-10-26 13:22:45 +02:00
|
|
|
/// User type annotation assertions for NLL.
|
|
|
|
AscribeUserTy,
|
2021-08-22 18:15:49 +02:00
|
|
|
/// The data of a user variable, for debug info.
|
2018-05-16 18:58:54 +03:00
|
|
|
VarDebugInfo,
|
2015-12-08 14:09:16 -05:00
|
|
|
}
|
2016-09-15 18:18:40 -07:00
|
|
|
|
2018-10-26 13:22:45 +02:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2019-04-24 19:41:43 +01:00
|
|
|
pub enum PlaceContext {
|
|
|
|
NonMutatingUse(NonMutatingUseContext),
|
|
|
|
MutatingUse(MutatingUseContext),
|
2018-10-26 13:22:45 +02:00
|
|
|
NonUse(NonUseContext),
|
|
|
|
}
|
|
|
|
|
2019-06-11 12:21:38 +03:00
|
|
|
impl PlaceContext {
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Returns `true` if this place context represents a drop.
|
2021-02-26 00:00:00 +00:00
|
|
|
#[inline]
|
2016-09-15 18:18:40 -07:00
|
|
|
pub fn is_drop(&self) -> bool {
|
2020-09-21 04:53:44 +02:00
|
|
|
matches!(self, PlaceContext::MutatingUse(MutatingUseContext::Drop))
|
2018-10-26 13:22:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns `true` if this place context represents a borrow.
|
|
|
|
pub fn is_borrow(&self) -> bool {
|
2020-09-21 04:53:44 +02:00
|
|
|
matches!(
|
|
|
|
self,
|
2020-04-16 17:38:52 -07:00
|
|
|
PlaceContext::NonMutatingUse(
|
|
|
|
NonMutatingUseContext::SharedBorrow
|
2020-09-21 04:53:44 +02:00
|
|
|
| NonMutatingUseContext::ShallowBorrow
|
|
|
|
| NonMutatingUseContext::UniqueBorrow
|
|
|
|
) | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
|
|
|
|
)
|
2016-09-15 18:18:40 -07:00
|
|
|
}
|
|
|
|
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Returns `true` if this place context represents a storage live or storage dead marker.
|
2021-02-26 00:00:00 +00:00
|
|
|
#[inline]
|
2016-09-15 18:18:40 -07:00
|
|
|
pub fn is_storage_marker(&self) -> bool {
|
2020-09-21 04:53:44 +02:00
|
|
|
matches!(
|
|
|
|
self,
|
|
|
|
PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead)
|
|
|
|
)
|
2016-09-15 18:18:40 -07:00
|
|
|
}
|
|
|
|
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Returns `true` if this place context represents a use that potentially changes the value.
|
2021-02-26 00:00:00 +00:00
|
|
|
#[inline]
|
2016-09-15 18:18:40 -07:00
|
|
|
pub fn is_mutating_use(&self) -> bool {
|
2020-09-21 04:53:44 +02:00
|
|
|
matches!(self, PlaceContext::MutatingUse(..))
|
2016-09-15 18:18:40 -07:00
|
|
|
}
|
|
|
|
|
2018-10-26 13:22:45 +02:00
|
|
|
/// Returns `true` if this place context represents a use.
|
2021-02-26 00:00:00 +00:00
|
|
|
#[inline]
|
2016-09-15 18:18:40 -07:00
|
|
|
pub fn is_use(&self) -> bool {
|
2020-09-21 04:53:44 +02:00
|
|
|
!matches!(self, PlaceContext::NonUse(..))
|
2018-10-26 13:22:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns `true` if this place context represents an assignment statement.
|
|
|
|
pub fn is_place_assignment(&self) -> bool {
|
2020-09-21 04:53:44 +02:00
|
|
|
matches!(
|
|
|
|
self,
|
2020-04-16 17:38:52 -07:00
|
|
|
PlaceContext::MutatingUse(
|
|
|
|
MutatingUseContext::Store
|
2020-09-21 04:53:44 +02:00
|
|
|
| MutatingUseContext::Call
|
|
|
|
| MutatingUseContext::AsmOutput,
|
|
|
|
)
|
|
|
|
)
|
2016-09-15 18:18:40 -07:00
|
|
|
}
|
|
|
|
}
|