impl<T> WithOptConstParam<T> {
/// Creates a new `WithOptConstParam` setting `const_param_did` to `None`.
+ #[inline(always)]
pub fn unknown(did: T) -> WithOptConstParam<T> {
WithOptConstParam { did, const_param_did: None }
}
}
impl WithOptConstParam<LocalDefId> {
+ /// Returns `Some((did, param_did))` if `def_id` is a const argument,
+ /// `None` otherwise.
+ #[inline(always)]
+ pub fn try_lookup(did: LocalDefId, tcx: TyCtxt<'_>) -> Option<(LocalDefId, DefId)> {
+ tcx.opt_const_param_of(did).map(|param_did| (did, param_did))
+ }
+
+ /// In case `self` is unknown but `self.did` is a const argument, this returns
+ /// a `WithOptConstParam` with the correct `const_param_did`.
+ #[inline(always)]
+ pub fn try_upgrade(self, tcx: TyCtxt<'_>) -> Option<WithOptConstParam<LocalDefId>> {
+ if self.const_param_did.is_none() {
+ if let const_param_did @ Some(_) = tcx.opt_const_param_of(self.did) {
+ return Some(WithOptConstParam { did: self.did, const_param_did });
+ }
+ }
+
+ None
+ }
+
pub fn to_global(self) -> WithOptConstParam<DefId> {
WithOptConstParam { did: self.did.to_def_id(), const_param_did: self.const_param_did }
}
pub fn provide(providers: &mut Providers) {
*providers = Providers {
- mir_borrowck: |tcx, did| mir_borrowck(tcx, ty::WithOptConstParam::unknown(did)),
+ mir_borrowck: |tcx, did| {
+ if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
+ tcx.mir_borrowck_const_arg(def)
+ } else {
+ mir_borrowck(tcx, ty::WithOptConstParam::unknown(did))
+ }
+ },
mir_borrowck_const_arg: |tcx, (did, param_did)| {
mir_borrowck(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
},
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) -> &'tcx BorrowCheckResult<'tcx> {
- if def.const_param_did.is_none() {
- if let Some(param_did) = tcx.opt_const_param_of(def.did) {
- return tcx.mir_borrowck_const_arg((def.did, param_did));
- }
- }
-
let (input_body, promoted) = tcx.mir_validated(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
unsafety_check_result: |tcx, def_id| {
- unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
+ if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
+ tcx.unsafety_check_result_for_const_arg(def)
+ } else {
+ unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
+ }
},
unsafety_check_result_for_const_arg: |tcx, (did, param_did)| {
unsafety_check_result(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) -> &'tcx UnsafetyCheckResult {
- if def.const_param_did.is_none() {
- if let Some(param_did) = tcx.opt_const_param_of(def.did) {
- return tcx.unsafety_check_result_for_const_arg((def.did, param_did));
- }
- }
-
debug!("unsafety_violations({:?})", def);
// N.B., this borrow is valid because all the consumers of
*providers = Providers {
mir_keys,
mir_const,
- mir_const_qualif: |tcx, did| {
- mir_const_qualif(tcx, ty::WithOptConstParam::unknown(did.expect_local()))
+ mir_const_qualif: |tcx, def_id| {
+ let def_id = def_id.expect_local();
+ if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
+ tcx.mir_const_qualif_const_arg(def)
+ } else {
+ mir_const_qualif(tcx, ty::WithOptConstParam::unknown(def_id))
+ }
},
mir_const_qualif_const_arg: |tcx, (did, param_did)| {
mir_const_qualif(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
optimized_mir_of_const_arg,
is_mir_available,
promoted_mir: |tcx, def_id| {
- promoted_mir(tcx, ty::WithOptConstParam::unknown(def_id.expect_local()))
+ let def_id = def_id.expect_local();
+ if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
+ tcx.promoted_mir_of_const_arg(def)
+ } else {
+ promoted_mir(tcx, ty::WithOptConstParam::unknown(def_id))
+ }
},
promoted_mir_of_const_arg: |tcx, (did, param_did)| {
promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
}
fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
- if def.const_param_did.is_none() {
- if let Some(param_did) = tcx.opt_const_param_of(def.did) {
- return tcx.mir_const_qualif_const_arg((def.did, param_did));
- }
- }
-
let const_kind = tcx.hir().body_const_context(def.did);
// No need to const-check a non-const `fn`.
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) -> &'tcx Steal<Body<'tcx>> {
- if def.const_param_did.is_none() {
- if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
- return tcx.mir_const(ty::WithOptConstParam { const_param_did, ..def });
- }
+ if let Some(def) = def.try_upgrade(tcx) {
+ return tcx.mir_const(def);
}
// Unsafety check uses the raw mir, so make sure it is run.
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) -> (&'tcx Steal<Body<'tcx>>, &'tcx Steal<IndexVec<Promoted, Body<'tcx>>>) {
- if def.const_param_did.is_none() {
- if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
- return tcx.mir_validated(ty::WithOptConstParam { const_param_did, ..def });
- }
+ if let Some(def) = def.try_upgrade(tcx) {
+ return tcx.mir_validated(def);
}
// Ensure that we compute the `mir_const_qualif` for constants at
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) -> &'tcx Steal<Body<'tcx>> {
- if def.const_param_did.is_none() {
- if let const_param_did @ Some(_) = tcx.opt_const_param_of(def.did) {
- return tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam {
- const_param_did,
- ..def
- });
- }
+ if let Some(def) = def.try_upgrade(tcx) {
+ return tcx.mir_drops_elaborated_and_const_checked(def);
}
// (Mir-)Borrowck uses `mir_validated`, so we have to force it to
fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> {
let did = did.expect_local();
- if let Some(param_did) = tcx.opt_const_param_of(did) {
- tcx.optimized_mir_of_const_arg((did, param_did))
+ if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) {
+ tcx.optimized_mir_of_const_arg(def)
} else {
tcx.arena.alloc(inner_optimized_mir(tcx, ty::WithOptConstParam::unknown(did)))
}
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) -> &'tcx IndexVec<Promoted, Body<'tcx>> {
- if def.const_param_did.is_none() {
- if let Some(param_did) = tcx.opt_const_param_of(def.did) {
- return tcx.promoted_mir_of_const_arg((def.did, param_did));
- }
- }
-
if tcx.is_constructor(def.did.to_def_id()) {
return tcx.arena.alloc(IndexVec::new());
}