mv utility methods into separate module
This commit is contained in:
parent
45f441a7b4
commit
6aa611a84c
6 changed files with 72 additions and 65 deletions
|
@ -23,7 +23,7 @@ use super::{
|
|||
MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, PointerArithmetic, Provenance,
|
||||
Scalar, StackPopJump,
|
||||
};
|
||||
use crate::transform::validate;
|
||||
use crate::util;
|
||||
|
||||
pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
|
||||
/// Stores the `Machine` instance.
|
||||
|
@ -355,7 +355,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
|
|||
// all normal lifetimes are erased, higher-ranked types with their
|
||||
// late-bound lifetimes are still around and can lead to type
|
||||
// differences.
|
||||
if validate::is_subtype(tcx, param_env, src.ty, dest.ty) {
|
||||
if util::is_subtype(tcx, param_env, src.ty, dest.ty) {
|
||||
// Make sure the layout is equal, too -- just to be safe. Miri really
|
||||
// needs layout equality. For performance reason we skip this check when
|
||||
// the types are equal. Equal types *can* have different layouts when
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::mir::interpret::Scalar;
|
||||
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
|
||||
use rustc_middle::mir::visit::{PlaceContext, Visitor};
|
||||
|
@ -18,7 +16,6 @@ use rustc_mir_dataflow::impls::MaybeStorageLive;
|
|||
use rustc_mir_dataflow::storage::always_storage_live_locals;
|
||||
use rustc_mir_dataflow::{Analysis, ResultsCursor};
|
||||
use rustc_target::abi::{Size, VariantIdx};
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
enum EdgeKind {
|
||||
|
@ -71,55 +68,6 @@ impl<'tcx> MirPass<'tcx> for Validator {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns whether the two types are equal up to subtyping.
|
||||
///
|
||||
/// This is used in case we don't know the expected subtyping direction
|
||||
/// and still want to check whether anything is broken.
|
||||
pub fn is_equal_up_to_subtyping<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
src: Ty<'tcx>,
|
||||
dest: Ty<'tcx>,
|
||||
) -> bool {
|
||||
// Fast path.
|
||||
if src == dest {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for subtyping in either direction.
|
||||
is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src)
|
||||
}
|
||||
|
||||
pub fn is_subtype<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
src: Ty<'tcx>,
|
||||
dest: Ty<'tcx>,
|
||||
) -> bool {
|
||||
if src == dest {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut builder =
|
||||
tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
|
||||
let infcx = builder.build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let cause = ObligationCause::dummy();
|
||||
let src = ocx.normalize(cause.clone(), param_env, src);
|
||||
let dest = ocx.normalize(cause.clone(), param_env, dest);
|
||||
let Ok(infer_ok) = infcx.at(&cause, param_env).sub(src, dest) else {
|
||||
return false;
|
||||
};
|
||||
let () = ocx.register_infer_ok_obligations(infer_ok);
|
||||
let errors = ocx.select_all_or_error();
|
||||
// With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
|
||||
// we would get unification errors because we're unable to look into opaque types,
|
||||
// even if they're constrained in our current function.
|
||||
//
|
||||
// It seems very unlikely that this hides any bugs.
|
||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||
errors.is_empty()
|
||||
}
|
||||
struct TypeChecker<'a, 'tcx> {
|
||||
when: &'a str,
|
||||
body: &'a Body<'tcx>,
|
||||
|
@ -195,7 +143,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
return true;
|
||||
}
|
||||
|
||||
is_subtype(self.tcx, self.param_env, src, dest)
|
||||
crate::util::is_subtype(self.tcx, self.param_env, src, dest)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
60
compiler/rustc_const_eval/src/util/compare_types.rs
Normal file
60
compiler/rustc_const_eval/src/util/compare_types.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
//! Routines to check for relations between fully inferred types.
|
||||
//!
|
||||
//! FIXME: Move this to a more general place. The utility of this extends to
|
||||
//! other areas of the compiler as well.
|
||||
|
||||
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
|
||||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
|
||||
use rustc_trait_selection::traits::ObligationCtxt;
|
||||
|
||||
/// Returns whether the two types are equal up to subtyping.
|
||||
///
|
||||
/// This is used in case we don't know the expected subtyping direction
|
||||
/// and still want to check whether anything is broken.
|
||||
pub fn is_equal_up_to_subtyping<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
src: Ty<'tcx>,
|
||||
dest: Ty<'tcx>,
|
||||
) -> bool {
|
||||
// Fast path.
|
||||
if src == dest {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for subtyping in either direction.
|
||||
is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src)
|
||||
}
|
||||
|
||||
/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
|
||||
pub fn is_subtype<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
src: Ty<'tcx>,
|
||||
dest: Ty<'tcx>,
|
||||
) -> bool {
|
||||
if src == dest {
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut builder =
|
||||
tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
|
||||
let infcx = builder.build();
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let cause = ObligationCause::dummy();
|
||||
let src = ocx.normalize(cause.clone(), param_env, src);
|
||||
let dest = ocx.normalize(cause.clone(), param_env, dest);
|
||||
let Ok(infer_ok) = infcx.at(&cause, param_env).sub(src, dest) else {
|
||||
return false;
|
||||
};
|
||||
let () = ocx.register_infer_ok_obligations(infer_ok);
|
||||
let errors = ocx.select_all_or_error();
|
||||
// With `Reveal::All`, opaque types get normalized away, with `Reveal::UserFacing`
|
||||
// we would get unification errors because we're unable to look into opaque types,
|
||||
// even if they're constrained in our current function.
|
||||
//
|
||||
// It seems very unlikely that this hides any bugs.
|
||||
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
|
||||
errors.is_empty()
|
||||
}
|
|
@ -2,6 +2,7 @@ pub mod aggregate;
|
|||
mod alignment;
|
||||
mod call_kind;
|
||||
pub mod collect_writes;
|
||||
mod compare_types;
|
||||
mod find_self_call;
|
||||
mod might_permit_raw_init;
|
||||
mod type_name;
|
||||
|
@ -9,6 +10,7 @@ mod type_name;
|
|||
pub use self::aggregate::expand_aggregate;
|
||||
pub use self::alignment::is_disaligned;
|
||||
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
|
||||
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
|
||||
pub use self::find_self_call::find_self_call;
|
||||
pub use self::might_permit_raw_init::might_permit_raw_init;
|
||||
pub use self::type_name::type_name;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue