Turn top-level comments into module docs in MIR visitor

This commit is contained in:
Camelid 2020-11-15 12:36:28 -08:00
parent 603ab5bd6e
commit c82a258ad4

View File

@ -1,70 +1,70 @@
//! # 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.
use crate::mir::*;
use crate::ty::subst::SubstsRef;
use crate::ty::{CanonicalUserTypeAnnotation, Ty};
use rustc_span::Span;
// # 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.
macro_rules! make_mir_visitor {
($visitor_trait_name:ident, $($mutability:ident)?) => {
pub trait $visitor_trait_name<'tcx> {