/// Returns `true` if a type that impls this closure kind
/// must also implement `other`.
pub fn extends(self, other: ty::ClosureKind) -> bool {
- match (self, other) {
- (ClosureKind::Fn, ClosureKind::Fn) => true,
- (ClosureKind::Fn, ClosureKind::FnMut) => true,
- (ClosureKind::Fn, ClosureKind::FnOnce) => true,
- (ClosureKind::FnMut, ClosureKind::FnMut) => true,
- (ClosureKind::FnMut, ClosureKind::FnOnce) => true,
- (ClosureKind::FnOnce, ClosureKind::FnOnce) => true,
- _ => false,
- }
+ matches!(
+ (self, other),
+ (ClosureKind::Fn, ClosureKind::Fn)
+ | (ClosureKind::Fn, ClosureKind::FnMut)
+ | (ClosureKind::Fn, ClosureKind::FnOnce)
+ | (ClosureKind::FnMut, ClosureKind::FnMut)
+ | (ClosureKind::FnMut, ClosureKind::FnOnce)
+ | (ClosureKind::FnOnce, ClosureKind::FnOnce)
+ )
}
/// Returns the representative scalar type for this closure kind.
pub fn opt_associated_item(self, def_id: DefId) -> Option<&'tcx AssocItem> {
let is_associated_item = if let Some(def_id) = def_id.as_local() {
- match self.hir().get(self.hir().local_def_id_to_hir_id(def_id)) {
- Node::TraitItem(_) | Node::ImplItem(_) => true,
- _ => false,
- }
+ matches!(
+ self.hir().get(self.hir().local_def_id_to_hir_id(def_id)),
+ Node::TraitItem(_) | Node::ImplItem(_)
+ )
} else {
- match self.def_kind(def_id) {
- DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => true,
- _ => false,
- }
+ matches!(
+ self.def_kind(def_id),
+ DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy
+ )
};
is_associated_item.then(|| self.associated_item(def_id))
/// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair.
pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> {
match instance {
- ty::InstanceDef::Item(def) => {
- if let Some((did, param_did)) = def.as_const_arg() {
- self.optimized_mir_of_const_arg((did, param_did))
- } else {
- self.optimized_mir(def.did)
- }
- }
+ ty::InstanceDef::Item(def) => self.optimized_mir_opt_const_arg(def),
ty::InstanceDef::VtableShim(..)
| ty::InstanceDef::ReifyShim(..)
| ty::InstanceDef::Intrinsic(..)
.hygienic_eq(def_name.span.ctxt(), self.expansion_that_defined(def_parent_def_id))
}
- fn expansion_that_defined(self, scope: DefId) -> ExpnId {
+ pub fn expansion_that_defined(self, scope: DefId) -> ExpnId {
match scope.as_local() {
+ // Parsing and expansion aren't incremental, so we don't
+ // need to go through a query for the same-crate case.
Some(scope) => self.hir().definitions().expansion_that_defined(scope),
- None => ExpnId::root(),
+ None => self.expn_that_defined(scope),
}
}
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::steal::Steal;
-use rustc_middle::ty::{self, InstanceDef, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_span::{Span, Symbol};
use std::borrow::Cow;
pub mod unreachable_prop;
pub mod validate;
+pub use rustc_middle::mir::MirSource;
+
pub(crate) fn provide(providers: &mut Providers) {
self::check_unsafety::provide(providers);
*providers = Providers {
set
}
-/// Where a specific `mir::Body` comes from.
-#[derive(Debug, Copy, Clone)]
-pub struct MirSource<'tcx> {
- pub instance: InstanceDef<'tcx>,
-
- /// If `Some`, this is a promoted rvalue within the parent function.
- pub promoted: Option<Promoted>,
-}
-
-impl<'tcx> MirSource<'tcx> {
- pub fn item(def_id: DefId) -> Self {
- MirSource {
- instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)),
- promoted: None,
- }
- }
-
- pub fn with_opt_param(self) -> ty::WithOptConstParam<DefId> {
- self.instance.with_opt_param()
- }
-
- #[inline]
- pub fn def_id(&self) -> DefId {
- self.instance.def_id()
- }
-}
-
/// Generates a default name for the pass based on the name of the
/// type `T`.
pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
default_name::<Self>()
}
- fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>);
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
}
pub fn run_passes(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
- instance: InstanceDef<'tcx>,
- promoted: Option<Promoted>,
mir_phase: MirPhase,
passes: &[&[&dyn MirPass<'tcx>]],
) {
let phase_index = mir_phase.phase_index();
- let source = MirSource { instance, promoted };
let validate = tcx.sess.opts.debugging_opts.validate_mir;
if body.phase >= mir_phase {
if validate {
validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase }
- .run_pass(tcx, source, body);
+ .run_pass(tcx, body);
}
let mut index = 0;
tcx,
&format_args!("{:03}-{:03}", phase_index, index),
&pass.name(),
- source,
body,
is_after,
);
};
run_hooks(body, index, false);
- pass.run_pass(tcx, source, body);
+ pass.run_pass(tcx, body);
run_hooks(body, index, true);
if validate {
when: format!("after {} in phase {:?}", pass.name(), mir_phase),
mir_phase,
}
- .run_pass(tcx, source, body);
+ .run_pass(tcx, body);
}
index += 1;
if mir_phase == MirPhase::Optimization {
validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase }
- .run_pass(tcx, source, body);
+ .run_pass(tcx, body);
}
}
return Default::default();
}
- let ccx = check_consts::ConstCx {
- body,
- tcx,
- def_id: def.did,
- const_kind,
- param_env: tcx.param_env(def.did),
- };
+ let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def.did) };
let mut validator = check_consts::validation::Validator::new(&ccx);
validator.check_body();
let mut body = tcx.mir_built(def).steal();
- util::dump_mir(
- tcx,
- None,
- "mir_map",
- &0,
- MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None },
- &body,
- |_, _| Ok(()),
- );
+ util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(()));
run_passes(
tcx,
&mut body,
- InstanceDef::Item(def.to_global()),
- None,
MirPhase::Const,
&[&[
// MIR-level lints.
// this point, before we steal the mir-const result.
// Also this means promotion can rely on all const checks having been done.
let _ = tcx.mir_const_qualif_opt_const_arg(def);
- let _ = if let Some(param_did) = def.const_param_did {
- tcx.mir_abstract_const_of_const_arg((def.did, param_did))
- } else {
- tcx.mir_abstract_const(def.did.to_def_id())
- };
+ let _ = tcx.mir_abstract_const_opt_const_arg(def.to_global());
let mut body = tcx.mir_const(def).steal();
let mut required_consts = Vec::new();
&[]
};
- run_passes(
- tcx,
- &mut body,
- InstanceDef::Item(def.to_global()),
- None,
- MirPhase::ConstPromotion,
- &[promote, opt_coverage],
- );
+ run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]);
let promoted = promote_pass.promoted_fragments.into_inner();
(tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
let (body, _) = tcx.mir_promoted(def);
let mut body = body.steal();
- run_post_borrowck_cleanup_passes(tcx, &mut body, def.did, None);
- check_consts::post_drop_elaboration::check_live_drops(tcx, def.did, &body);
+ run_post_borrowck_cleanup_passes(tcx, &mut body);
+ check_consts::post_drop_elaboration::check_live_drops(tcx, &body);
tcx.alloc_steal_mir(body)
}
/// After this series of passes, no lifetime analysis based on borrowing can be done.
-fn run_post_borrowck_cleanup_passes<'tcx>(
- tcx: TyCtxt<'tcx>,
- body: &mut Body<'tcx>,
- def_id: LocalDefId,
- promoted: Option<Promoted>,
-) {
- debug!("post_borrowck_cleanup({:?})", def_id);
+fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+ debug!("post_borrowck_cleanup({:?})", body.source.def_id());
let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[
// Remove all things only needed by analysis
&deaggregator::Deaggregator,
];
- run_passes(
- tcx,
- body,
- InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())),
- promoted,
- MirPhase::DropLowering,
- &[post_borrowck_cleanup],
- );
+ run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]);
}
-fn run_optimization_passes<'tcx>(
- tcx: TyCtxt<'tcx>,
- body: &mut Body<'tcx>,
- def_id: LocalDefId,
- promoted: Option<Promoted>,
-) {
+fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level;
// Lowering generator control-flow and variables has to happen before we do anything else
run_passes(
tcx,
body,
- InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())),
- promoted,
MirPhase::GeneratorLowering,
&[
if mir_opt_level > 0 {
run_passes(
tcx,
body,
- InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())),
- promoted,
MirPhase::Optimization,
&[
if mir_opt_level > 0 { optimizations } else { no_optimizations },
}
let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal();
- run_optimization_passes(tcx, &mut body, def.did, None);
+ run_optimization_passes(tcx, &mut body);
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
let (_, promoted) = tcx.mir_promoted(def);
let mut promoted = promoted.steal();
- for (p, mut body) in promoted.iter_enumerated_mut() {
- run_post_borrowck_cleanup_passes(tcx, &mut body, def.did, Some(p));
- run_optimization_passes(tcx, &mut body, def.did, Some(p));
+ for body in &mut promoted {
+ run_post_borrowck_cleanup_passes(tcx, body);
+ run_optimization_passes(tcx, body);
}
debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");