mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
commit
547598b67e
@ -121,24 +121,24 @@ rustc_index::newtype_index! {
|
||||
/// `BorrowIndex`, and maps each such index to a `BorrowData`
|
||||
/// describing the borrow. These indexes are used for representing the
|
||||
/// borrows in compact bitvectors.
|
||||
pub struct Borrows<'a, 'tcx> {
|
||||
pub struct Borrows<'mir, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'a Body<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
borrow_set: &'mir BorrowSet<'tcx>,
|
||||
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
|
||||
}
|
||||
|
||||
struct OutOfScopePrecomputer<'a, 'tcx> {
|
||||
struct OutOfScopePrecomputer<'mir, 'tcx> {
|
||||
visited: BitSet<mir::BasicBlock>,
|
||||
visit_stack: Vec<mir::BasicBlock>,
|
||||
body: &'a Body<'tcx>,
|
||||
regioncx: &'a RegionInferenceContext<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
regioncx: &'mir RegionInferenceContext<'tcx>,
|
||||
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> {
|
||||
fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self {
|
||||
impl<'mir, 'tcx> OutOfScopePrecomputer<'mir, 'tcx> {
|
||||
fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self {
|
||||
OutOfScopePrecomputer {
|
||||
visited: BitSet::new_empty(body.basic_blocks.len()),
|
||||
visit_stack: vec![],
|
||||
@ -241,17 +241,17 @@ pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
|
||||
prec.borrows_out_of_scope_at_location
|
||||
}
|
||||
|
||||
struct PoloniusOutOfScopePrecomputer<'a, 'tcx> {
|
||||
struct PoloniusOutOfScopePrecomputer<'mir, 'tcx> {
|
||||
visited: BitSet<mir::BasicBlock>,
|
||||
visit_stack: Vec<mir::BasicBlock>,
|
||||
body: &'a Body<'tcx>,
|
||||
regioncx: &'a RegionInferenceContext<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
regioncx: &'mir RegionInferenceContext<'tcx>,
|
||||
|
||||
loans_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> PoloniusOutOfScopePrecomputer<'a, 'tcx> {
|
||||
fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self {
|
||||
impl<'mir, 'tcx> PoloniusOutOfScopePrecomputer<'mir, 'tcx> {
|
||||
fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self {
|
||||
Self {
|
||||
visited: BitSet::new_empty(body.basic_blocks.len()),
|
||||
visit_stack: vec![],
|
||||
@ -404,12 +404,12 @@ impl<'tcx> PoloniusOutOfScopePrecomputer<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Borrows<'a, 'tcx> {
|
||||
impl<'mir, 'tcx> Borrows<'mir, 'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'a Body<'tcx>,
|
||||
regioncx: &'a RegionInferenceContext<'tcx>,
|
||||
borrow_set: &'a BorrowSet<'tcx>,
|
||||
body: &'mir Body<'tcx>,
|
||||
regioncx: &'mir RegionInferenceContext<'tcx>,
|
||||
borrow_set: &'mir BorrowSet<'tcx>,
|
||||
) -> Self {
|
||||
let mut borrows_out_of_scope_at_location =
|
||||
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set);
|
||||
|
@ -288,7 +288,7 @@ fn do_mir_borrowck<'tcx>(
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("borrowck")
|
||||
.iterate_to_fixpoint();
|
||||
let flow_ever_inits = EverInitializedPlaces::new(tcx, body, &mdpe)
|
||||
let flow_ever_inits = EverInitializedPlaces::new(body, &mdpe)
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("borrowck")
|
||||
.iterate_to_fixpoint();
|
||||
|
@ -27,7 +27,7 @@ fn main() {
|
||||
args.push(codegen_backend_arg);
|
||||
}
|
||||
if !passed_args.iter().any(|arg| {
|
||||
arg == "--sysroot" || arg.to_str().map(|s| s.starts_with("--sysroot=")) == Some(true)
|
||||
arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot="))
|
||||
}) {
|
||||
args.push(OsString::from("--sysroot"));
|
||||
args.push(OsString::from(sysroot.to_str().unwrap()));
|
||||
|
@ -27,7 +27,7 @@ fn main() {
|
||||
args.push(codegen_backend_arg);
|
||||
}
|
||||
if !passed_args.iter().any(|arg| {
|
||||
arg == "--sysroot" || arg.to_str().map(|s| s.starts_with("--sysroot=")) == Some(true)
|
||||
arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot="))
|
||||
}) {
|
||||
args.push(OsString::from("--sysroot"));
|
||||
args.push(OsString::from(sysroot.to_str().unwrap()));
|
||||
|
@ -135,7 +135,7 @@ pub(crate) fn matches_codepattern(a: &str, b: &str) -> bool {
|
||||
|
||||
/// Advances the given peekable `Iterator` until it reaches a non-whitespace character.
|
||||
fn scan_for_non_ws_or_end<I: Iterator<Item = char>>(iter: &mut Peekable<I>) {
|
||||
while iter.peek().copied().map(rustc_lexer::is_whitespace) == Some(true) {
|
||||
while iter.peek().copied().is_some_and(rustc_lexer::is_whitespace) {
|
||||
iter.next();
|
||||
}
|
||||
}
|
||||
|
@ -1674,10 +1674,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
|
||||
|
||||
// Check that the self types can be related.
|
||||
// FIXME(inherent_associated_types): Should we use `eq` here? Method probing uses
|
||||
// `sup` for this situtation, too. What for? To constrain inference variables?
|
||||
if ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err()
|
||||
{
|
||||
if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2293,12 +2293,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let clone_trait =
|
||||
self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span));
|
||||
if args.is_empty()
|
||||
&& self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map(
|
||||
|did| {
|
||||
&& self
|
||||
.typeck_results
|
||||
.borrow()
|
||||
.type_dependent_def_id(expr.hir_id)
|
||||
.is_some_and(|did| {
|
||||
let ai = self.tcx.associated_item(did);
|
||||
ai.trait_container(self.tcx) == Some(clone_trait)
|
||||
},
|
||||
) == Some(true)
|
||||
})
|
||||
&& segment.ident.name == sym::clone
|
||||
{
|
||||
// If this expression had a clone call when suggesting borrowing
|
||||
|
@ -161,7 +161,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
|
||||
&& self
|
||||
.tcx()
|
||||
.opt_associated_item(scope_def_id.to_def_id())
|
||||
.map(|i| i.fn_has_self_parameter)
|
||||
== Some(true)
|
||||
.is_some_and(|i| i.fn_has_self_parameter)
|
||||
}
|
||||
}
|
||||
|
@ -260,3 +260,85 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// EAGER RESOLUTION
|
||||
|
||||
/// Resolves ty, region, and const vars to their inferred values or their root vars.
|
||||
pub struct EagerResolver<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EagerResolver<'a, 'tcx> {
|
||||
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
|
||||
EagerResolver { infcx }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match *t.kind() {
|
||||
ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
|
||||
Ok(t) => t.fold_with(self),
|
||||
Err(_) => Ty::new_var(self.infcx.tcx, self.infcx.root_var(vid)),
|
||||
},
|
||||
ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid),
|
||||
ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid),
|
||||
_ => {
|
||||
if t.has_infer() {
|
||||
t.super_fold_with(self)
|
||||
} else {
|
||||
t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
match *r {
|
||||
ty::ReVar(vid) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(self.infcx.tcx, vid),
|
||||
_ => r,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
match c.kind() {
|
||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
||||
// FIXME: we need to fold the ty too, I think.
|
||||
match self.infcx.probe_const_var(vid) {
|
||||
Ok(c) => c.fold_with(self),
|
||||
Err(_) => {
|
||||
ty::Const::new_var(self.infcx.tcx, self.infcx.root_const_var(vid), c.ty())
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
|
||||
debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool);
|
||||
match self.infcx.probe_effect_var(vid) {
|
||||
Some(c) => c.as_const(self.infcx.tcx),
|
||||
None => ty::Const::new_infer(
|
||||
self.infcx.tcx,
|
||||
ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)),
|
||||
self.infcx.tcx.types.bool,
|
||||
),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if c.has_infer() {
|
||||
c.super_fold_with(self)
|
||||
} else {
|
||||
c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,17 +154,13 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
||||
|
||||
let infcx = cx.tcx.infer_ctxt().build();
|
||||
let suggest_display = is_str
|
||||
|| cx
|
||||
.tcx
|
||||
.get_diagnostic_item(sym::Display)
|
||||
.map(|t| infcx.type_implements_trait(t, [ty], cx.param_env).may_apply())
|
||||
== Some(true);
|
||||
|| cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| {
|
||||
infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
|
||||
});
|
||||
let suggest_debug = !suggest_display
|
||||
&& cx
|
||||
.tcx
|
||||
.get_diagnostic_item(sym::Debug)
|
||||
.map(|t| infcx.type_implements_trait(t, [ty], cx.param_env).may_apply())
|
||||
== Some(true);
|
||||
&& cx.tcx.get_diagnostic_item(sym::Debug).is_some_and(|t| {
|
||||
infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
|
||||
});
|
||||
|
||||
let suggest_panic_any = !is_str && panic == sym::std_panic_macro;
|
||||
|
||||
|
@ -8,6 +8,7 @@ use crate::ty::{
|
||||
};
|
||||
use crate::ty::{GenericArg, GenericArgKind};
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_apfloat::Float;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use rustc_hir as hir;
|
||||
@ -1477,10 +1478,12 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
||||
ty::Bool if int == ScalarInt::TRUE => p!("true"),
|
||||
// Float
|
||||
ty::Float(ty::FloatTy::F32) => {
|
||||
p!(write("{}f32", Single::try_from(int).unwrap()))
|
||||
let val = Single::try_from(int).unwrap();
|
||||
p!(write("{}{}f32", val, if val.is_finite() { "" } else { "_" }))
|
||||
}
|
||||
ty::Float(ty::FloatTy::F64) => {
|
||||
p!(write("{}f64", Double::try_from(int).unwrap()))
|
||||
let val = Double::try_from(int).unwrap();
|
||||
p!(write("{}{}f64", val, if val.is_finite() { "" } else { "_" }))
|
||||
}
|
||||
// Int
|
||||
ty::Uint(_) | ty::Int(_) => {
|
||||
|
@ -1,10 +1,8 @@
|
||||
use crate::elaborate_drops::DropFlagState;
|
||||
use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_target::abi::VariantIdx;
|
||||
|
||||
use super::indexes::MovePathIndex;
|
||||
use super::move_paths::{InitKind, LookupResult, MoveData};
|
||||
use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex};
|
||||
use super::MoveDataParamEnv;
|
||||
|
||||
pub fn move_path_children_matching<'tcx, F>(
|
||||
@ -30,8 +28,6 @@ where
|
||||
}
|
||||
|
||||
pub fn on_lookup_result_bits<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
lookup_result: LookupResult,
|
||||
each_child: F,
|
||||
@ -42,13 +38,11 @@ pub fn on_lookup_result_bits<'tcx, F>(
|
||||
LookupResult::Parent(..) => {
|
||||
// access to untracked value - do not touch children
|
||||
}
|
||||
LookupResult::Exact(e) => on_all_children_bits(tcx, body, move_data, e, each_child),
|
||||
LookupResult::Exact(e) => on_all_children_bits(move_data, e, each_child),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_all_children_bits<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
move_path_index: MovePathIndex,
|
||||
mut each_child: F,
|
||||
@ -56,8 +50,6 @@ pub fn on_all_children_bits<'tcx, F>(
|
||||
F: FnMut(MovePathIndex),
|
||||
{
|
||||
fn on_all_children_bits<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
move_path_index: MovePathIndex,
|
||||
each_child: &mut F,
|
||||
@ -68,15 +60,14 @@ pub fn on_all_children_bits<'tcx, F>(
|
||||
|
||||
let mut next_child_index = move_data.move_paths[move_path_index].first_child;
|
||||
while let Some(child_index) = next_child_index {
|
||||
on_all_children_bits(tcx, body, move_data, child_index, each_child);
|
||||
on_all_children_bits(move_data, child_index, each_child);
|
||||
next_child_index = move_data.move_paths[child_index].next_sibling;
|
||||
}
|
||||
}
|
||||
on_all_children_bits(tcx, body, move_data, move_path_index, &mut each_child);
|
||||
on_all_children_bits(move_data, move_path_index, &mut each_child);
|
||||
}
|
||||
|
||||
pub fn drop_flag_effects_for_function_entry<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
ctxt: &MoveDataParamEnv<'tcx>,
|
||||
mut callback: F,
|
||||
@ -87,14 +78,13 @@ pub fn drop_flag_effects_for_function_entry<'tcx, F>(
|
||||
for arg in body.args_iter() {
|
||||
let place = mir::Place::from(arg);
|
||||
let lookup_result = move_data.rev_lookup.find(place.as_ref());
|
||||
on_lookup_result_bits(tcx, body, move_data, lookup_result, |mpi| {
|
||||
on_lookup_result_bits(move_data, lookup_result, |mpi| {
|
||||
callback(mpi, DropFlagState::Present)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_flag_effects_for_location<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
ctxt: &MoveDataParamEnv<'tcx>,
|
||||
loc: Location,
|
||||
@ -110,7 +100,7 @@ pub fn drop_flag_effects_for_location<'tcx, F>(
|
||||
let path = mi.move_path_index(move_data);
|
||||
debug!("moving out of path {:?}", move_data.move_paths[path]);
|
||||
|
||||
on_all_children_bits(tcx, body, move_data, path, |mpi| callback(mpi, DropFlagState::Absent))
|
||||
on_all_children_bits(move_data, path, |mpi| callback(mpi, DropFlagState::Absent))
|
||||
}
|
||||
|
||||
// Drop does not count as a move but we should still consider the variable uninitialized.
|
||||
@ -118,24 +108,17 @@ pub fn drop_flag_effects_for_location<'tcx, F>(
|
||||
body.stmt_at(loc).right()
|
||||
{
|
||||
if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) {
|
||||
on_all_children_bits(tcx, body, move_data, mpi, |mpi| {
|
||||
callback(mpi, DropFlagState::Absent)
|
||||
})
|
||||
on_all_children_bits(move_data, mpi, |mpi| callback(mpi, DropFlagState::Absent))
|
||||
}
|
||||
}
|
||||
|
||||
debug!("drop_flag_effects: assignment for location({:?})", loc);
|
||||
|
||||
for_location_inits(tcx, body, move_data, loc, |mpi| callback(mpi, DropFlagState::Present));
|
||||
for_location_inits(move_data, loc, |mpi| callback(mpi, DropFlagState::Present));
|
||||
}
|
||||
|
||||
pub fn for_location_inits<'tcx, F>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
loc: Location,
|
||||
mut callback: F,
|
||||
) where
|
||||
fn for_location_inits<'tcx, F>(move_data: &MoveData<'tcx>, loc: Location, mut callback: F)
|
||||
where
|
||||
F: FnMut(MovePathIndex),
|
||||
{
|
||||
for ii in &move_data.init_loc_map[loc] {
|
||||
@ -144,7 +127,7 @@ pub fn for_location_inits<'tcx, F>(
|
||||
InitKind::Deep => {
|
||||
let path = init.path;
|
||||
|
||||
on_all_children_bits(tcx, body, move_data, path, &mut callback)
|
||||
on_all_children_bits(move_data, path, &mut callback)
|
||||
}
|
||||
InitKind::Shallow => {
|
||||
let mpi = init.path;
|
||||
@ -161,8 +144,6 @@ pub fn for_location_inits<'tcx, F>(
|
||||
/// NOTE: If there are no move paths corresponding to an inactive variant,
|
||||
/// `handle_inactive_variant` will not be called for that variant.
|
||||
pub(crate) fn on_all_inactive_variants<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &mir::Body<'tcx>,
|
||||
move_data: &MoveData<'tcx>,
|
||||
enum_place: mir::Place<'tcx>,
|
||||
active_variant: VariantIdx,
|
||||
@ -185,9 +166,7 @@ pub(crate) fn on_all_inactive_variants<'tcx>(
|
||||
};
|
||||
|
||||
if variant_idx != active_variant {
|
||||
on_all_children_bits(tcx, body, move_data, variant_mpi, |mpi| {
|
||||
handle_inactive_variant(mpi)
|
||||
});
|
||||
on_all_children_bits(move_data, variant_mpi, |mpi| handle_inactive_variant(mpi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ where
|
||||
}
|
||||
|
||||
/// Returns the underlying `Results`.
|
||||
pub fn results(&mut self) -> &Results<'tcx, A, R::EntrySets> {
|
||||
pub fn results(&self) -> &Results<'tcx, A, R::EntrySets> {
|
||||
self.results.borrow()
|
||||
}
|
||||
|
||||
@ -166,11 +166,6 @@ where
|
||||
&mut self.results.borrow_mut().analysis
|
||||
}
|
||||
|
||||
/// Returns both the dataflow state at the current location and the `Analysis`.
|
||||
pub fn get_with_analysis(&mut self) -> (&A::Domain, &mut A) {
|
||||
(&self.state, &mut self.results.borrow_mut().analysis)
|
||||
}
|
||||
|
||||
/// Resets the cursor to hold the entry set for the given basic block.
|
||||
///
|
||||
/// For forward dataflow analyses, this is the dataflow state prior to the first statement.
|
||||
|
@ -287,12 +287,12 @@ impl Direction for Backward {
|
||||
}
|
||||
}
|
||||
|
||||
struct BackwardSwitchIntEdgeEffectsApplier<'a, 'tcx, D, F> {
|
||||
body: &'a mir::Body<'tcx>,
|
||||
struct BackwardSwitchIntEdgeEffectsApplier<'mir, 'tcx, D, F> {
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
pred: BasicBlock,
|
||||
exit_state: &'a mut D,
|
||||
exit_state: &'mir mut D,
|
||||
bb: BasicBlock,
|
||||
propagate: &'a mut F,
|
||||
propagate: &'mir mut F,
|
||||
effects_applied: bool,
|
||||
}
|
||||
|
||||
@ -523,9 +523,9 @@ impl Direction for Forward {
|
||||
}
|
||||
}
|
||||
|
||||
struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> {
|
||||
exit_state: &'a mut D,
|
||||
targets: &'a SwitchTargets,
|
||||
struct ForwardSwitchIntEdgeEffectsApplier<'mir, D, F> {
|
||||
exit_state: &'mir mut D,
|
||||
targets: &'mir SwitchTargets,
|
||||
propagate: F,
|
||||
|
||||
effects_applied: bool,
|
||||
|
@ -128,12 +128,12 @@ where
|
||||
}
|
||||
|
||||
/// A solver for dataflow problems.
|
||||
pub struct Engine<'a, 'tcx, A>
|
||||
pub struct Engine<'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'a mir::Body<'tcx>,
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
entry_sets: IndexVec<BasicBlock, A::Domain>,
|
||||
pass_name: Option<&'static str>,
|
||||
analysis: A,
|
||||
@ -147,14 +147,14 @@ where
|
||||
apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A>
|
||||
impl<'mir, 'tcx, A, D, T> Engine<'mir, 'tcx, A>
|
||||
where
|
||||
A: GenKillAnalysis<'tcx, Idx = T, Domain = D>,
|
||||
D: Clone + JoinSemiLattice + GenKill<T> + BitSetExt<T>,
|
||||
T: Idx,
|
||||
{
|
||||
/// Creates a new `Engine` to solve a gen-kill dataflow problem.
|
||||
pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, mut analysis: A) -> Self {
|
||||
pub fn new_gen_kill(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, mut analysis: A) -> Self {
|
||||
// If there are no back-edges in the control-flow graph, we only ever need to apply the
|
||||
// transfer function for each block exactly once (assuming that we process blocks in RPO).
|
||||
//
|
||||
@ -186,7 +186,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, A, D> Engine<'a, 'tcx, A>
|
||||
impl<'mir, 'tcx, A, D> Engine<'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx, Domain = D>,
|
||||
D: Clone + JoinSemiLattice,
|
||||
@ -196,13 +196,13 @@ where
|
||||
///
|
||||
/// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for
|
||||
/// better performance.
|
||||
pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'a mir::Body<'tcx>, analysis: A) -> Self {
|
||||
pub fn new_generic(tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, analysis: A) -> Self {
|
||||
Self::new(tcx, body, analysis, None)
|
||||
}
|
||||
|
||||
fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'a mir::Body<'tcx>,
|
||||
body: &'mir mir::Body<'tcx>,
|
||||
analysis: A,
|
||||
apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
|
||||
) -> Self {
|
||||
@ -239,7 +239,6 @@ where
|
||||
tcx,
|
||||
apply_statement_trans_for_block,
|
||||
pass_name,
|
||||
..
|
||||
} = self;
|
||||
|
||||
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());
|
||||
|
@ -15,7 +15,7 @@ use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext};
|
||||
use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum OutputStyle {
|
||||
pub(crate) enum OutputStyle {
|
||||
AfterOnly,
|
||||
BeforeAndAfter,
|
||||
}
|
||||
@ -29,7 +29,7 @@ impl OutputStyle {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Formatter<'res, 'mir, 'tcx, A>
|
||||
pub(crate) struct Formatter<'res, 'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
@ -43,7 +43,7 @@ impl<'res, 'mir, 'tcx, A> Formatter<'res, 'mir, 'tcx, A>
|
||||
where
|
||||
A: Analysis<'tcx>,
|
||||
{
|
||||
pub fn new(
|
||||
pub(crate) fn new(
|
||||
body: &'mir Body<'tcx>,
|
||||
results: &'res mut Results<'tcx, A>,
|
||||
style: OutputStyle,
|
||||
@ -55,7 +55,7 @@ where
|
||||
|
||||
/// A pair of a basic block and an index into that basic blocks `successors`.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct CfgEdge {
|
||||
pub(crate) struct CfgEdge {
|
||||
source: BasicBlock,
|
||||
index: usize,
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ pub mod graphviz;
|
||||
pub mod lattice;
|
||||
mod visitor;
|
||||
|
||||
pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor};
|
||||
pub use self::cursor::{ResultsClonedCursor, ResultsCursor, ResultsRefCursor};
|
||||
pub use self::direction::{Backward, Direction, Forward};
|
||||
pub use self::engine::{Engine, EntrySets, Results, ResultsCloned};
|
||||
pub use self::lattice::{JoinSemiLattice, MaybeReachable};
|
||||
|
@ -72,7 +72,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
|
||||
) -> bool {
|
||||
if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
|
||||
let mut maybe_live = false;
|
||||
on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| {
|
||||
on_all_children_bits(self.move_data(), path, |child| {
|
||||
maybe_live |= state.contains(child);
|
||||
});
|
||||
!maybe_live
|
||||
@ -203,14 +203,13 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
|
||||
/// this data and `MaybeInitializedPlaces` yields the set of places
|
||||
/// that would require a dynamic drop-flag at that statement.
|
||||
pub struct DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'a Body<'tcx>,
|
||||
mdpe: &'a MoveDataParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
|
||||
DefinitelyInitializedPlaces { tcx, body, mdpe }
|
||||
pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
|
||||
DefinitelyInitializedPlaces { body, mdpe }
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,15 +249,13 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||
/// }
|
||||
/// ```
|
||||
pub struct EverInitializedPlaces<'a, 'tcx> {
|
||||
#[allow(dead_code)]
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &'a Body<'tcx>,
|
||||
mdpe: &'a MoveDataParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
|
||||
EverInitializedPlaces { tcx, body, mdpe }
|
||||
pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
|
||||
EverInitializedPlaces { body, mdpe }
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,7 +316,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
|
||||
*state =
|
||||
MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len()));
|
||||
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
||||
drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
state.gen(path);
|
||||
});
|
||||
@ -339,7 +336,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
});
|
||||
|
||||
@ -351,7 +348,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
| mir::Rvalue::AddressOf(_, place) = rvalue
|
||||
&& let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref())
|
||||
{
|
||||
on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| {
|
||||
on_all_children_bits(self.move_data(), mpi, |child| {
|
||||
trans.gen(child);
|
||||
})
|
||||
}
|
||||
@ -371,7 +368,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
{
|
||||
edges = TerminatorEdges::Single(target);
|
||||
}
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(state, path, s)
|
||||
});
|
||||
edges
|
||||
@ -387,8 +384,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
// when a call returns successfully, that means we need to set
|
||||
// the bits for that dest_place to 1 (initialized).
|
||||
on_lookup_result_bits(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.move_data(),
|
||||
self.move_data().rev_lookup.find(place.as_ref()),
|
||||
|mpi| {
|
||||
@ -432,8 +427,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
|
||||
// Kill all move paths that correspond to variants we know to be inactive along this
|
||||
// particular outgoing edge of a `SwitchInt`.
|
||||
drop_flag_effects::on_all_inactive_variants(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.move_data(),
|
||||
enum_place,
|
||||
variant,
|
||||
@ -458,7 +451,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
// set all bits to 1 (uninit) before gathering counter-evidence
|
||||
state.insert_all();
|
||||
|
||||
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
||||
drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
state.remove(path);
|
||||
});
|
||||
@ -478,7 +471,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
});
|
||||
|
||||
@ -492,7 +485,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) -> TerminatorEdges<'mir, 'tcx> {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
});
|
||||
if self.skip_unreachable_unwind.contains(location.block) {
|
||||
@ -514,8 +507,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
// when a call returns successfully, that means we need to set
|
||||
// the bits for that dest_place to 0 (initialized).
|
||||
on_lookup_result_bits(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.move_data(),
|
||||
self.move_data().rev_lookup.find(place.as_ref()),
|
||||
|mpi| {
|
||||
@ -563,8 +554,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
|
||||
// Mark all move paths that correspond to variants other than this one as maybe
|
||||
// uninitialized (in reality, they are *definitely* uninitialized).
|
||||
drop_flag_effects::on_all_inactive_variants(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.move_data(),
|
||||
enum_place,
|
||||
variant,
|
||||
@ -589,7 +578,7 @@ impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
|
||||
fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
|
||||
state.0.clear();
|
||||
|
||||
drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
|
||||
drop_flag_effects_for_function_entry(self.body, self.mdpe, |path, s| {
|
||||
assert!(s == DropFlagState::Present);
|
||||
state.0.insert(path);
|
||||
});
|
||||
@ -609,7 +598,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
||||
_statement: &mir::Statement<'tcx>,
|
||||
location: Location,
|
||||
) {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
})
|
||||
}
|
||||
@ -620,7 +609,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
||||
terminator: &'mir mir::Terminator<'tcx>,
|
||||
location: Location,
|
||||
) -> TerminatorEdges<'mir, 'tcx> {
|
||||
drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
|
||||
drop_flag_effects_for_location(self.body, self.mdpe, location, |path, s| {
|
||||
Self::update_bits(trans, path, s)
|
||||
});
|
||||
terminator.edges()
|
||||
@ -636,8 +625,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
|
||||
// when a call returns successfully, that means we need to set
|
||||
// the bits for that dest_place to 1 (initialized).
|
||||
on_lookup_result_bits(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.move_data(),
|
||||
self.move_data().rev_lookup.find(place.as_ref()),
|
||||
|mpi| {
|
||||
|
@ -23,7 +23,6 @@ use crate::{Analysis, AnalysisDomain, Backward, GenKill, GenKillAnalysis};
|
||||
/// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals
|
||||
/// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs
|
||||
/// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct MaybeLiveLocals;
|
||||
|
||||
impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals {
|
||||
|
@ -4,7 +4,6 @@
|
||||
#![feature(let_chains)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(trusted_step)]
|
||||
#![recursion_limit = "256"]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
@ -14,24 +13,19 @@ extern crate tracing;
|
||||
#[macro_use]
|
||||
extern crate rustc_middle;
|
||||
|
||||
use rustc_ast::MetaItem;
|
||||
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
|
||||
use rustc_fluent_macro::fluent_messages;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_middle::ty;
|
||||
|
||||
pub use self::drop_flag_effects::{
|
||||
drop_flag_effects_for_function_entry, drop_flag_effects_for_location,
|
||||
move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
|
||||
};
|
||||
pub use self::framework::{
|
||||
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward,
|
||||
CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice,
|
||||
MaybeReachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
|
||||
ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
|
||||
fmt, lattice, visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis,
|
||||
JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor,
|
||||
};
|
||||
|
||||
use self::framework::{Backward, CloneAnalysis, ResultsClonedCursor, SwitchIntEdgeEffects};
|
||||
use self::move_paths::MoveData;
|
||||
|
||||
pub mod debuginfo;
|
||||
@ -48,24 +42,7 @@ pub mod value_analysis;
|
||||
|
||||
fluent_messages! { "../messages.ftl" }
|
||||
|
||||
pub(crate) mod indexes {
|
||||
pub(crate) use super::move_paths::MovePathIndex;
|
||||
}
|
||||
|
||||
pub struct MoveDataParamEnv<'tcx> {
|
||||
pub move_data: MoveData<'tcx>,
|
||||
pub param_env: ty::ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
pub fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<MetaItem> {
|
||||
for attr in tcx.get_attrs(def_id, sym::rustc_mir) {
|
||||
let items = attr.meta_item_list();
|
||||
for item in items.iter().flat_map(|l| l.iter()) {
|
||||
match item.meta_item() {
|
||||
Some(mi) if mi.has_name(name) => return Some(mi.clone()),
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -1,11 +1,3 @@
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::Span;
|
||||
|
||||
use rustc_index::bit_set::ChunkedBitSet;
|
||||
use rustc_middle::mir::MirPass;
|
||||
use rustc_middle::mir::{self, Body, Local, Location};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
|
||||
use crate::errors::{
|
||||
PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary,
|
||||
PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation,
|
||||
@ -18,13 +10,33 @@ use crate::move_paths::{HasMoveData, MoveData};
|
||||
use crate::move_paths::{LookupResult, MovePathIndex};
|
||||
use crate::MoveDataParamEnv;
|
||||
use crate::{Analysis, JoinSemiLattice, ResultsCursor};
|
||||
use rustc_ast::MetaItem;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::bit_set::ChunkedBitSet;
|
||||
use rustc_middle::mir::MirPass;
|
||||
use rustc_middle::mir::{self, Body, Local, Location};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
pub struct SanityCheck;
|
||||
|
||||
fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<MetaItem> {
|
||||
for attr in tcx.get_attrs(def_id, sym::rustc_mir) {
|
||||
let items = attr.meta_item_list();
|
||||
for item in items.iter().flat_map(|l| l.iter()) {
|
||||
match item.meta_item() {
|
||||
Some(mi) if mi.has_name(name) => return Some(mi.clone()),
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first.
|
||||
impl<'tcx> MirPass<'tcx> for SanityCheck {
|
||||
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
use crate::has_rustc_mir_with;
|
||||
let def_id = body.source.def_id();
|
||||
if !tcx.has_attr(def_id, sym::rustc_mir) {
|
||||
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id));
|
||||
@ -54,7 +66,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck {
|
||||
}
|
||||
|
||||
if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() {
|
||||
let flow_def_inits = DefinitelyInitializedPlaces::new(tcx, body, &mdpe)
|
||||
let flow_def_inits = DefinitelyInitializedPlaces::new(body, &mdpe)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint();
|
||||
|
||||
@ -89,10 +101,8 @@ impl<'tcx> MirPass<'tcx> for SanityCheck {
|
||||
/// (If there are any calls to `rustc_peek` that do not match the
|
||||
/// expression form above, then that emits an error as well, but those
|
||||
/// errors are not intended to be used for unit tests.)
|
||||
pub fn sanity_check_via_rustc_peek<'tcx, A>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
mut cursor: ResultsCursor<'_, 'tcx, A>,
|
||||
) where
|
||||
fn sanity_check_via_rustc_peek<'tcx, A>(tcx: TyCtxt<'tcx>, mut cursor: ResultsCursor<'_, 'tcx, A>)
|
||||
where
|
||||
A: RustcPeekAt<'tcx>,
|
||||
{
|
||||
let def_id = cursor.body().source.def_id();
|
||||
@ -129,7 +139,8 @@ pub fn sanity_check_via_rustc_peek<'tcx, A>(
|
||||
) => {
|
||||
let loc = Location { block: bb, statement_index };
|
||||
cursor.seek_before_primary_effect(loc);
|
||||
let (state, analysis) = cursor.get_with_analysis();
|
||||
let state = cursor.get();
|
||||
let analysis = cursor.analysis();
|
||||
analysis.peek_at(tcx, *place, state, call);
|
||||
}
|
||||
|
||||
@ -173,7 +184,7 @@ impl PeekCallKind {
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct PeekCall {
|
||||
struct PeekCall {
|
||||
arg: Local,
|
||||
kind: PeekCallKind,
|
||||
span: Span,
|
||||
@ -221,7 +232,7 @@ impl PeekCall {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RustcPeekAt<'tcx>: Analysis<'tcx> {
|
||||
trait RustcPeekAt<'tcx>: Analysis<'tcx> {
|
||||
fn peek_at(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -3,13 +3,13 @@ use rustc_middle::mir::*;
|
||||
|
||||
/// Used for reverting changes made by `DerefSeparator`
|
||||
#[derive(Default, Debug)]
|
||||
pub struct UnDerefer<'tcx> {
|
||||
pub(crate) struct UnDerefer<'tcx> {
|
||||
deref_chains: FxHashMap<Local, Vec<PlaceRef<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> UnDerefer<'tcx> {
|
||||
#[inline]
|
||||
pub fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) {
|
||||
pub(crate) fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) {
|
||||
let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default();
|
||||
chain.push(reffed);
|
||||
self.deref_chains.insert(local, chain);
|
||||
@ -17,7 +17,7 @@ impl<'tcx> UnDerefer<'tcx> {
|
||||
|
||||
/// Returns the chain of places behind `DerefTemp` locals
|
||||
#[inline]
|
||||
pub fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] {
|
||||
pub(crate) fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] {
|
||||
self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default()
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ impl<'tcx> UnDerefer<'tcx> {
|
||||
///
|
||||
/// See [`PlaceRef::iter_projections`]
|
||||
#[inline]
|
||||
pub fn iter_projections(
|
||||
pub(crate) fn iter_projections(
|
||||
&self,
|
||||
place: PlaceRef<'tcx>,
|
||||
) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + '_ {
|
||||
|
@ -332,8 +332,6 @@ pub struct ValueAnalysisWrapper<T>(pub T);
|
||||
impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper<T> {
|
||||
type Domain = State<T::Value>;
|
||||
|
||||
type Direction = crate::Forward;
|
||||
|
||||
const NAME: &'static str = T::NAME;
|
||||
|
||||
fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain {
|
||||
@ -476,26 +474,10 @@ impl<V: Clone> State<V> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_reachable(&self) -> bool {
|
||||
fn is_reachable(&self) -> bool {
|
||||
matches!(&self.0, StateData::Reachable(_))
|
||||
}
|
||||
|
||||
pub fn mark_unreachable(&mut self) {
|
||||
self.0 = StateData::Unreachable;
|
||||
}
|
||||
|
||||
pub fn flood_all(&mut self)
|
||||
where
|
||||
V: HasTop,
|
||||
{
|
||||
self.flood_all_with(V::TOP)
|
||||
}
|
||||
|
||||
pub fn flood_all_with(&mut self, value: V) {
|
||||
let StateData::Reachable(values) = &mut self.0 else { return };
|
||||
values.raw.fill(value);
|
||||
}
|
||||
|
||||
/// Assign `value` to all places that are contained in `place` or may alias one.
|
||||
pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
|
||||
self.flood_with_tail_elem(place, None, map, value)
|
||||
@ -510,7 +492,7 @@ impl<V: Clone> State<V> {
|
||||
}
|
||||
|
||||
/// Assign `value` to the discriminant of `place` and all places that may alias it.
|
||||
pub fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
|
||||
fn flood_discr_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
|
||||
self.flood_with_tail_elem(place, Some(TrackElem::Discriminant), map, value)
|
||||
}
|
||||
|
||||
@ -546,7 +528,7 @@ impl<V: Clone> State<V> {
|
||||
/// This does nothing if the place is not tracked.
|
||||
///
|
||||
/// The target place must have been flooded before calling this method.
|
||||
pub fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) {
|
||||
fn insert_idx(&mut self, target: PlaceIndex, result: ValueOrPlace<V>, map: &Map) {
|
||||
match result {
|
||||
ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map),
|
||||
ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map),
|
||||
@ -910,18 +892,13 @@ impl Map {
|
||||
self.inner_values[root] = start..end;
|
||||
}
|
||||
|
||||
/// Returns the number of tracked places, i.e., those for which a value can be stored.
|
||||
pub fn tracked_places(&self) -> usize {
|
||||
self.value_count
|
||||
}
|
||||
|
||||
/// Applies a single projection element, yielding the corresponding child.
|
||||
pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> {
|
||||
self.projections.get(&(place, elem)).copied()
|
||||
}
|
||||
|
||||
/// Locates the given place, if it exists in the tree.
|
||||
pub fn find_extra(
|
||||
fn find_extra(
|
||||
&self,
|
||||
place: PlaceRef<'_>,
|
||||
extra: impl IntoIterator<Item = TrackElem>,
|
||||
@ -954,7 +931,7 @@ impl Map {
|
||||
}
|
||||
|
||||
/// Iterate over all direct children.
|
||||
pub fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> + '_ {
|
||||
fn children(&self, parent: PlaceIndex) -> impl Iterator<Item = PlaceIndex> + '_ {
|
||||
Children::new(self, parent)
|
||||
}
|
||||
|
||||
|
@ -668,36 +668,34 @@ fn locals_live_across_suspend_points<'tcx>(
|
||||
always_live_locals: &BitSet<Local>,
|
||||
movable: bool,
|
||||
) -> LivenessInfo {
|
||||
let body_ref: &Body<'_> = body;
|
||||
|
||||
// Calculate when MIR locals have live storage. This gives us an upper bound of their
|
||||
// lifetimes.
|
||||
let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals))
|
||||
.into_engine(tcx, body_ref)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(body_ref);
|
||||
.into_results_cursor(body);
|
||||
|
||||
// Calculate the MIR locals which have been previously
|
||||
// borrowed (even if they are still active).
|
||||
let borrowed_locals_results =
|
||||
MaybeBorrowedLocals.into_engine(tcx, body_ref).pass_name("coroutine").iterate_to_fixpoint();
|
||||
MaybeBorrowedLocals.into_engine(tcx, body).pass_name("coroutine").iterate_to_fixpoint();
|
||||
|
||||
let mut borrowed_locals_cursor = borrowed_locals_results.cloned_results_cursor(body_ref);
|
||||
let mut borrowed_locals_cursor = borrowed_locals_results.cloned_results_cursor(body);
|
||||
|
||||
// Calculate the MIR locals that we actually need to keep storage around
|
||||
// for.
|
||||
let mut requires_storage_results =
|
||||
MaybeRequiresStorage::new(borrowed_locals_results.cloned_results_cursor(body))
|
||||
.into_engine(tcx, body_ref)
|
||||
.into_engine(tcx, body)
|
||||
.iterate_to_fixpoint();
|
||||
let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body_ref);
|
||||
let mut requires_storage_cursor = requires_storage_results.as_results_cursor(body);
|
||||
|
||||
// Calculate the liveness of MIR locals ignoring borrows.
|
||||
let mut liveness = MaybeLiveLocals
|
||||
.into_engine(tcx, body_ref)
|
||||
.into_engine(tcx, body)
|
||||
.pass_name("coroutine")
|
||||
.iterate_to_fixpoint()
|
||||
.into_results_cursor(body_ref);
|
||||
.into_results_cursor(body);
|
||||
|
||||
let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks);
|
||||
let mut live_locals_at_suspension_points = Vec::new();
|
||||
@ -763,7 +761,7 @@ fn locals_live_across_suspend_points<'tcx>(
|
||||
.collect();
|
||||
|
||||
let storage_conflicts = compute_storage_conflicts(
|
||||
body_ref,
|
||||
body,
|
||||
&saved_locals,
|
||||
always_live_locals.clone(),
|
||||
requires_storage_results,
|
||||
|
@ -172,19 +172,13 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> {
|
||||
let mut some_live = false;
|
||||
let mut some_dead = false;
|
||||
let mut children_count = 0;
|
||||
on_all_children_bits(
|
||||
self.tcx(),
|
||||
self.body(),
|
||||
self.ctxt.move_data(),
|
||||
path,
|
||||
|child| {
|
||||
let (live, dead) = self.ctxt.init_data.maybe_live_dead(child);
|
||||
debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
|
||||
some_live |= live;
|
||||
some_dead |= dead;
|
||||
children_count += 1;
|
||||
},
|
||||
);
|
||||
on_all_children_bits(self.ctxt.move_data(), path, |child| {
|
||||
let (live, dead) = self.ctxt.init_data.maybe_live_dead(child);
|
||||
debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
|
||||
some_live |= live;
|
||||
some_dead |= dead;
|
||||
children_count += 1;
|
||||
});
|
||||
((some_live, some_dead), children_count != 1)
|
||||
}
|
||||
};
|
||||
@ -202,13 +196,9 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> {
|
||||
self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent);
|
||||
}
|
||||
DropFlagMode::Deep => {
|
||||
on_all_children_bits(
|
||||
self.tcx(),
|
||||
self.body(),
|
||||
self.ctxt.move_data(),
|
||||
path,
|
||||
|child| self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent),
|
||||
);
|
||||
on_all_children_bits(self.ctxt.move_data(), path, |child| {
|
||||
self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,10 +258,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
}
|
||||
|
||||
fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
|
||||
let tcx = self.tcx;
|
||||
let patch = &mut self.patch;
|
||||
debug!("create_drop_flag({:?})", self.body.span);
|
||||
self.drop_flags[index].get_or_insert_with(|| patch.new_temp(tcx.types.bool, span));
|
||||
self.drop_flags[index].get_or_insert_with(|| patch.new_temp(self.tcx.types.bool, span));
|
||||
}
|
||||
|
||||
fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
|
||||
@ -304,7 +293,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
match path {
|
||||
LookupResult::Exact(path) => {
|
||||
self.init_data.seek_before(self.body.terminator_loc(bb));
|
||||
on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| {
|
||||
on_all_children_bits(self.move_data(), path, |child| {
|
||||
let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child);
|
||||
debug!(
|
||||
"collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
|
||||
@ -444,7 +433,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
|
||||
let loc = Location { block: tgt, statement_index: 0 };
|
||||
let path = self.move_data().rev_lookup.find(destination.as_ref());
|
||||
on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| {
|
||||
on_lookup_result_bits(self.move_data(), path, |child| {
|
||||
self.set_drop_flag(loc, child, DropFlagState::Present)
|
||||
});
|
||||
}
|
||||
@ -453,14 +442,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
|
||||
fn drop_flags_for_args(&mut self) {
|
||||
let loc = Location::START;
|
||||
rustc_mir_dataflow::drop_flag_effects_for_function_entry(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.env,
|
||||
|path, ds| {
|
||||
self.set_drop_flag(loc, path, ds);
|
||||
},
|
||||
)
|
||||
rustc_mir_dataflow::drop_flag_effects_for_function_entry(self.body, self.env, |path, ds| {
|
||||
self.set_drop_flag(loc, path, ds);
|
||||
})
|
||||
}
|
||||
|
||||
fn drop_flags_for_locs(&mut self) {
|
||||
@ -492,7 +476,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
}
|
||||
let loc = Location { block: bb, statement_index: i };
|
||||
rustc_mir_dataflow::drop_flag_effects_for_location(
|
||||
self.tcx,
|
||||
self.body,
|
||||
self.env,
|
||||
loc,
|
||||
@ -515,7 +498,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
|
||||
|
||||
let loc = Location { block: bb, statement_index: data.statements.len() };
|
||||
let path = self.move_data().rev_lookup.find(destination.as_ref());
|
||||
on_lookup_result_bits(self.tcx, self.body, self.move_data(), path, |child| {
|
||||
on_lookup_result_bits(self.move_data(), path, |child| {
|
||||
self.set_drop_flag(loc, child, DropFlagState::Present)
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
|
||||
//! until stable MIR is complete.
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables, TablesWrapper};
|
||||
use crate::rustc_smir::{context::TablesWrapper, Stable, Tables};
|
||||
use rustc_data_structures::fx;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_middle::mir::interpret::AllocId;
|
||||
@ -181,7 +181,7 @@ where
|
||||
instances: IndexMap::default(),
|
||||
constants: IndexMap::default(),
|
||||
}));
|
||||
stable_mir::run(&tables, || init(&tables, f))
|
||||
stable_mir::compiler_interface::run(&tables, || init(&tables, f))
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
376
compiler/rustc_smir/src/rustc_smir/context.rs
Normal file
376
compiler/rustc_smir/src/rustc_smir/context.rs
Normal file
@ -0,0 +1,376 @@
|
||||
//! Implementation of `[stable_mir::compiler_interface::Context]` trait.
|
||||
//!
|
||||
//! This trait is currently the main interface between the Rust compiler,
|
||||
//! and the `stable_mir` crate.
|
||||
|
||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{GenericPredicates, Instance, ParamEnv, ScalarInt, ValTree};
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use stable_mir::compiler_interface::Context;
|
||||
use stable_mir::mir::alloc::GlobalAlloc;
|
||||
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
||||
use stable_mir::mir::Body;
|
||||
use stable_mir::ty::{
|
||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FnDef, GenericArgs, LineInfo,
|
||||
RigidTy, Span, TyKind,
|
||||
};
|
||||
use stable_mir::{self, Crate, CrateItem, Error, Filename, ItemKind, Symbol};
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::rustc_internal::{internal, RustcInternal};
|
||||
use crate::rustc_smir::builder::BodyBuilder;
|
||||
use crate::rustc_smir::{new_item_kind, smir_crate, Stable, Tables};
|
||||
|
||||
impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||
fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let tcx = tables.tcx;
|
||||
Some(tables.crate_item(tcx.entry_fn(())?.0))
|
||||
}
|
||||
|
||||
fn all_local_items(&self) -> stable_mir::CrateItems {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect()
|
||||
}
|
||||
|
||||
fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[item];
|
||||
tables.tcx.instance_mir(rustc_middle::ty::InstanceDef::Item(def_id)).stable(&mut tables)
|
||||
}
|
||||
|
||||
fn all_trait_decls(&self) -> stable_mir::TraitDecls {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
tables
|
||||
.tcx
|
||||
.traits(LOCAL_CRATE)
|
||||
.iter()
|
||||
.map(|trait_def_id| tables.trait_def(*trait_def_id))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[trait_def.0];
|
||||
let trait_def = tables.tcx.trait_def(def_id);
|
||||
trait_def.stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
tables
|
||||
.tcx
|
||||
.trait_impls_in_crate(LOCAL_CRATE)
|
||||
.iter()
|
||||
.map(|impl_def_id| tables.impl_def(*impl_def_id))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[impl_def.0];
|
||||
let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap();
|
||||
impl_trait.stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[def_id];
|
||||
let generics = tables.tcx.generics_of(def_id);
|
||||
generics.stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[def_id];
|
||||
let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
|
||||
stable_mir::ty::GenericPredicates {
|
||||
parent: parent.map(|did| tables.trait_def(did)),
|
||||
predicates: predicates
|
||||
.iter()
|
||||
.map(|(clause, span)| {
|
||||
(
|
||||
clause.as_predicate().kind().skip_binder().stable(&mut *tables),
|
||||
span.stable(&mut *tables),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn explicit_predicates_of(
|
||||
&self,
|
||||
def_id: stable_mir::DefId,
|
||||
) -> stable_mir::ty::GenericPredicates {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[def_id];
|
||||
let GenericPredicates { parent, predicates } = tables.tcx.explicit_predicates_of(def_id);
|
||||
stable_mir::ty::GenericPredicates {
|
||||
parent: parent.map(|did| tables.trait_def(did)),
|
||||
predicates: predicates
|
||||
.iter()
|
||||
.map(|(clause, span)| {
|
||||
(
|
||||
clause.as_predicate().kind().skip_binder().stable(&mut *tables),
|
||||
span.stable(&mut *tables),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn local_crate(&self) -> stable_mir::Crate {
|
||||
let tables = self.0.borrow();
|
||||
smir_crate(tables.tcx, LOCAL_CRATE)
|
||||
}
|
||||
|
||||
fn external_crates(&self) -> Vec<stable_mir::Crate> {
|
||||
let tables = self.0.borrow();
|
||||
tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
|
||||
}
|
||||
|
||||
fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
|
||||
let tables = self.0.borrow();
|
||||
let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
|
||||
.iter()
|
||||
.chain(tables.tcx.crates(()).iter())
|
||||
.map(|crate_num| {
|
||||
let crate_name = tables.tcx.crate_name(*crate_num).to_string();
|
||||
(name == crate_name).then(|| smir_crate(tables.tcx, *crate_num))
|
||||
})
|
||||
.into_iter()
|
||||
.filter_map(|c| c)
|
||||
.collect();
|
||||
crates
|
||||
}
|
||||
|
||||
fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol {
|
||||
let tables = self.0.borrow();
|
||||
if trimmed {
|
||||
with_forced_trimmed_paths!(tables.tcx.def_path_str(tables[def_id]))
|
||||
} else {
|
||||
with_no_trimmed_paths!(tables.tcx.def_path_str(tables[def_id]))
|
||||
}
|
||||
}
|
||||
|
||||
fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
|
||||
let tables = self.0.borrow();
|
||||
tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
|
||||
}
|
||||
|
||||
fn get_filename(&self, span: &Span) -> Filename {
|
||||
let tables = self.0.borrow();
|
||||
tables
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_filename(tables[*span])
|
||||
.display(rustc_span::FileNameDisplayPreference::Local)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
fn get_lines(&self, span: &Span) -> LineInfo {
|
||||
let tables = self.0.borrow();
|
||||
let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]);
|
||||
LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
|
||||
}
|
||||
|
||||
fn item_kind(&self, item: CrateItem) -> ItemKind {
|
||||
let tables = self.0.borrow();
|
||||
new_item_kind(tables.tcx.def_kind(tables[item.0]))
|
||||
}
|
||||
|
||||
fn is_foreign_item(&self, item: CrateItem) -> bool {
|
||||
let tables = self.0.borrow();
|
||||
tables.tcx.is_foreign_item(tables[item.0])
|
||||
}
|
||||
|
||||
fn adt_kind(&self, def: AdtDef) -> AdtKind {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
def.internal(&mut *tables).adt_kind().stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn adt_is_box(&self, def: AdtDef) -> bool {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
def.internal(&mut *tables).is_box()
|
||||
}
|
||||
|
||||
fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let mir_const = cnst.internal(&mut *tables);
|
||||
mir_const
|
||||
.try_eval_target_usize(tables.tcx, ParamEnv::empty())
|
||||
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
|
||||
}
|
||||
|
||||
fn usize_to_const(&self, val: u64) -> Result<Const, Error> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let ty = tables.tcx.types.usize;
|
||||
let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size;
|
||||
|
||||
let scalar = ScalarInt::try_from_uint(val, size).ok_or_else(|| {
|
||||
Error::new(format!("Value overflow: cannot convert `{val}` to usize."))
|
||||
})?;
|
||||
Ok(rustc_middle::ty::Const::new_value(tables.tcx, ValTree::from_scalar_int(scalar), ty)
|
||||
.stable(&mut *tables))
|
||||
}
|
||||
|
||||
fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let internal_kind = kind.internal(&mut *tables);
|
||||
tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
tables.tcx.type_of(item.internal(&mut *tables)).instantiate_identity().stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn const_literal(&self, cnst: &stable_mir::ty::Const) -> String {
|
||||
internal(cnst).to_string()
|
||||
}
|
||||
|
||||
fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
tables.types[ty].kind().stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn instance_body(&self, def: InstanceDef) -> Option<Body> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[def];
|
||||
tables
|
||||
.has_body(instance)
|
||||
.then(|| BodyBuilder::new(tables.tcx, instance).build(&mut *tables))
|
||||
}
|
||||
|
||||
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[def];
|
||||
instance.ty(tables.tcx, ParamEnv::empty()).stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables.instances[def].def_id();
|
||||
tables.create_def_id(def_id)
|
||||
}
|
||||
|
||||
fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
|
||||
let tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[instance];
|
||||
tables.tcx.symbol_name(instance).name.to_string()
|
||||
}
|
||||
|
||||
fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = tables[item.0];
|
||||
Instance::mono(tables.tcx, def_id).stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
|
||||
let tables = self.0.borrow();
|
||||
let def_id = tables[def_id];
|
||||
let generics = tables.tcx.generics_of(def_id);
|
||||
let result = generics.requires_monomorphization(tables.tcx);
|
||||
result
|
||||
}
|
||||
|
||||
fn resolve_instance(
|
||||
&self,
|
||||
def: stable_mir::ty::FnDef,
|
||||
args: &stable_mir::ty::GenericArgs,
|
||||
) -> Option<stable_mir::mir::mono::Instance> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = def.0.internal(&mut *tables);
|
||||
let args_ref = args.internal(&mut *tables);
|
||||
match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
|
||||
Ok(Some(instance)) => Some(instance.stable(&mut *tables)),
|
||||
Ok(None) | Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let internal_ty = ty.internal(&mut *tables);
|
||||
let instance = Instance::resolve_drop_in_place(tables.tcx, internal_ty);
|
||||
instance.stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn resolve_for_fn_ptr(
|
||||
&self,
|
||||
def: FnDef,
|
||||
args: &GenericArgs,
|
||||
) -> Option<stable_mir::mir::mono::Instance> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = def.0.internal(&mut *tables);
|
||||
let args_ref = args.internal(&mut *tables);
|
||||
Instance::resolve_for_fn_ptr(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref)
|
||||
.stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn resolve_closure(
|
||||
&self,
|
||||
def: ClosureDef,
|
||||
args: &GenericArgs,
|
||||
kind: ClosureKind,
|
||||
) -> Option<stable_mir::mir::mono::Instance> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = def.0.internal(&mut *tables);
|
||||
let args_ref = args.internal(&mut *tables);
|
||||
let closure_kind = kind.internal(&mut *tables);
|
||||
Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind).stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let def_id = def.0.internal(&mut *tables);
|
||||
tables.tcx.eval_static_initializer(def_id).stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let alloc_id = alloc.internal(&mut *tables);
|
||||
tables.tcx.global_alloc(alloc_id).stable(&mut *tables)
|
||||
}
|
||||
|
||||
fn vtable_allocation(
|
||||
&self,
|
||||
global_alloc: &GlobalAlloc,
|
||||
) -> Option<stable_mir::mir::alloc::AllocId> {
|
||||
let mut tables = self.0.borrow_mut();
|
||||
let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { return None };
|
||||
let alloc_id = tables
|
||||
.tcx
|
||||
.vtable_allocation((ty.internal(&mut *tables), trait_ref.internal(&mut *tables)));
|
||||
Some(alloc_id.stable(&mut *tables))
|
||||
}
|
||||
|
||||
fn krate(&self, def_id: stable_mir::DefId) -> Crate {
|
||||
let tables = self.0.borrow();
|
||||
smir_crate(tables.tcx, tables[def_id].krate)
|
||||
}
|
||||
|
||||
/// Retrieve the instance name for diagnostic messages.
|
||||
///
|
||||
/// This will return the specialized name, e.g., `Vec<char>::new`.
|
||||
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
|
||||
let tables = self.0.borrow_mut();
|
||||
let instance = tables.instances[def];
|
||||
if trimmed {
|
||||
with_forced_trimmed_paths!(
|
||||
tables.tcx.def_path_str_with_args(instance.def_id(), instance.args)
|
||||
)
|
||||
} else {
|
||||
with_no_trimmed_paths!(
|
||||
tables.tcx.def_path_str_with_args(instance.def_id(), instance.args)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);
|
745
compiler/rustc_smir/src/rustc_smir/convert/mir.rs
Normal file
745
compiler/rustc_smir/src/rustc_smir/convert/mir.rs
Normal file
@ -0,0 +1,745 @@
|
||||
//! Conversion of internal Rust compiler `mir` items to stable ones.
|
||||
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::alloc_range;
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
use stable_mir::mir::alloc::GlobalAlloc;
|
||||
use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment};
|
||||
use stable_mir::ty::{Allocation, Const, ConstantKind};
|
||||
use stable_mir::{opaque, Error};
|
||||
|
||||
use crate::rustc_smir::{alloc, Stable, Tables};
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
|
||||
type T = stable_mir::mir::Body;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::mir::Body::new(
|
||||
self.basic_blocks
|
||||
.iter()
|
||||
.map(|block| stable_mir::mir::BasicBlock {
|
||||
terminator: block.terminator().stable(tables),
|
||||
statements: block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|statement| statement.stable(tables))
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
self.local_decls
|
||||
.iter()
|
||||
.map(|decl| stable_mir::mir::LocalDecl {
|
||||
ty: decl.ty.stable(tables),
|
||||
span: decl.source_info.span.stable(tables),
|
||||
mutability: decl.mutability.stable(tables),
|
||||
})
|
||||
.collect(),
|
||||
self.arg_count,
|
||||
self.var_debug_info.iter().map(|info| info.stable(tables)).collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
|
||||
type T = stable_mir::mir::VarDebugInfo;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::mir::VarDebugInfo {
|
||||
name: self.name.to_string(),
|
||||
source_info: self.source_info.stable(tables),
|
||||
composite: self.composite.as_ref().map(|composite| composite.stable(tables)),
|
||||
value: self.value.stable(tables),
|
||||
argument_index: self.argument_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
|
||||
type T = stable_mir::mir::Statement;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::SourceInfo {
|
||||
type T = stable_mir::mir::SourceInfo;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::mir::SourceInfo { span: self.span.stable(tables), scope: self.scope.into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
|
||||
type T = stable_mir::mir::VarDebugInfoFragment;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
VarDebugInfoFragment {
|
||||
ty: self.ty.stable(tables),
|
||||
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
|
||||
type T = stable_mir::mir::VarDebugInfoContents;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
mir::VarDebugInfoContents::Place(place) => {
|
||||
stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables))
|
||||
}
|
||||
mir::VarDebugInfoContents::Const(const_operand) => {
|
||||
let op = ConstOperand {
|
||||
span: const_operand.span.stable(tables),
|
||||
user_ty: const_operand.user_ty.map(|index| index.as_usize()),
|
||||
const_: const_operand.const_.stable(tables),
|
||||
};
|
||||
stable_mir::mir::VarDebugInfoContents::Const(op)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
|
||||
type T = stable_mir::mir::StatementKind;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign(
|
||||
assign.0.stable(tables),
|
||||
assign.1.stable(tables),
|
||||
),
|
||||
mir::StatementKind::FakeRead(fake_read_place) => {
|
||||
stable_mir::mir::StatementKind::FakeRead(
|
||||
fake_read_place.0.stable(tables),
|
||||
fake_read_place.1.stable(tables),
|
||||
)
|
||||
}
|
||||
mir::StatementKind::SetDiscriminant { place, variant_index } => {
|
||||
stable_mir::mir::StatementKind::SetDiscriminant {
|
||||
place: place.as_ref().stable(tables),
|
||||
variant_index: variant_index.stable(tables),
|
||||
}
|
||||
}
|
||||
mir::StatementKind::Deinit(place) => {
|
||||
stable_mir::mir::StatementKind::Deinit(place.stable(tables))
|
||||
}
|
||||
|
||||
mir::StatementKind::StorageLive(place) => {
|
||||
stable_mir::mir::StatementKind::StorageLive(place.stable(tables))
|
||||
}
|
||||
|
||||
mir::StatementKind::StorageDead(place) => {
|
||||
stable_mir::mir::StatementKind::StorageDead(place.stable(tables))
|
||||
}
|
||||
mir::StatementKind::Retag(retag, place) => {
|
||||
stable_mir::mir::StatementKind::Retag(retag.stable(tables), place.stable(tables))
|
||||
}
|
||||
mir::StatementKind::PlaceMention(place) => {
|
||||
stable_mir::mir::StatementKind::PlaceMention(place.stable(tables))
|
||||
}
|
||||
mir::StatementKind::AscribeUserType(place_projection, variance) => {
|
||||
stable_mir::mir::StatementKind::AscribeUserType {
|
||||
place: place_projection.as_ref().0.stable(tables),
|
||||
projections: place_projection.as_ref().1.stable(tables),
|
||||
variance: variance.stable(tables),
|
||||
}
|
||||
}
|
||||
mir::StatementKind::Coverage(coverage) => {
|
||||
stable_mir::mir::StatementKind::Coverage(opaque(coverage))
|
||||
}
|
||||
mir::StatementKind::Intrinsic(intrinstic) => {
|
||||
stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables))
|
||||
}
|
||||
mir::StatementKind::ConstEvalCounter => {
|
||||
stable_mir::mir::StatementKind::ConstEvalCounter
|
||||
}
|
||||
mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
|
||||
type T = stable_mir::mir::Rvalue;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::Rvalue::*;
|
||||
match self {
|
||||
Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
|
||||
Repeat(op, len) => {
|
||||
let len = len.stable(tables);
|
||||
stable_mir::mir::Rvalue::Repeat(op.stable(tables), len)
|
||||
}
|
||||
Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
|
||||
region.stable(tables),
|
||||
kind.stable(tables),
|
||||
place.stable(tables),
|
||||
),
|
||||
ThreadLocalRef(def_id) => {
|
||||
stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id))
|
||||
}
|
||||
AddressOf(mutability, place) => {
|
||||
stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables))
|
||||
}
|
||||
Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)),
|
||||
Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast(
|
||||
cast_kind.stable(tables),
|
||||
op.stable(tables),
|
||||
ty.stable(tables),
|
||||
),
|
||||
BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp(
|
||||
bin_op.stable(tables),
|
||||
ops.0.stable(tables),
|
||||
ops.1.stable(tables),
|
||||
),
|
||||
CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
|
||||
bin_op.stable(tables),
|
||||
ops.0.stable(tables),
|
||||
ops.1.stable(tables),
|
||||
),
|
||||
NullaryOp(null_op, ty) => {
|
||||
stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), ty.stable(tables))
|
||||
}
|
||||
UnaryOp(un_op, op) => {
|
||||
stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables))
|
||||
}
|
||||
Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables)),
|
||||
Aggregate(agg_kind, operands) => {
|
||||
let operands = operands.iter().map(|op| op.stable(tables)).collect();
|
||||
stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables), operands)
|
||||
}
|
||||
ShallowInitBox(op, ty) => {
|
||||
stable_mir::mir::Rvalue::ShallowInitBox(op.stable(tables), ty.stable(tables))
|
||||
}
|
||||
CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Mutability {
|
||||
type T = stable_mir::mir::Mutability;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_hir::Mutability::*;
|
||||
match *self {
|
||||
Not => stable_mir::mir::Mutability::Not,
|
||||
Mut => stable_mir::mir::Mutability::Mut,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::BorrowKind {
|
||||
type T = stable_mir::mir::BorrowKind;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::BorrowKind::*;
|
||||
match *self {
|
||||
Shared => stable_mir::mir::BorrowKind::Shared,
|
||||
Fake => stable_mir::mir::BorrowKind::Fake,
|
||||
Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
|
||||
type T = stable_mir::mir::MutBorrowKind;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::MutBorrowKind::*;
|
||||
match *self {
|
||||
Default => stable_mir::mir::MutBorrowKind::Default,
|
||||
TwoPhaseBorrow => stable_mir::mir::MutBorrowKind::TwoPhaseBorrow,
|
||||
ClosureCapture => stable_mir::mir::MutBorrowKind::ClosureCapture,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
|
||||
type T = stable_mir::mir::NullOp;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::NullOp::*;
|
||||
match self {
|
||||
SizeOf => stable_mir::mir::NullOp::SizeOf,
|
||||
AlignOf => stable_mir::mir::NullOp::AlignOf,
|
||||
OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf(
|
||||
indices.iter().map(|idx| idx.stable(tables)).collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::CastKind {
|
||||
type T = stable_mir::mir::CastKind;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::CastKind::*;
|
||||
match self {
|
||||
PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress,
|
||||
PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress,
|
||||
PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
|
||||
DynStar => stable_mir::mir::CastKind::DynStar,
|
||||
IntToInt => stable_mir::mir::CastKind::IntToInt,
|
||||
FloatToInt => stable_mir::mir::CastKind::FloatToInt,
|
||||
FloatToFloat => stable_mir::mir::CastKind::FloatToFloat,
|
||||
IntToFloat => stable_mir::mir::CastKind::IntToFloat,
|
||||
PtrToPtr => stable_mir::mir::CastKind::PtrToPtr,
|
||||
FnPtrToPtr => stable_mir::mir::CastKind::FnPtrToPtr,
|
||||
Transmute => stable_mir::mir::CastKind::Transmute,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
|
||||
type T = stable_mir::mir::FakeReadCause;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::FakeReadCause::*;
|
||||
match self {
|
||||
ForMatchGuard => stable_mir::mir::FakeReadCause::ForMatchGuard,
|
||||
ForMatchedPlace(local_def_id) => {
|
||||
stable_mir::mir::FakeReadCause::ForMatchedPlace(opaque(local_def_id))
|
||||
}
|
||||
ForGuardBinding => stable_mir::mir::FakeReadCause::ForGuardBinding,
|
||||
ForLet(local_def_id) => stable_mir::mir::FakeReadCause::ForLet(opaque(local_def_id)),
|
||||
ForIndex => stable_mir::mir::FakeReadCause::ForIndex,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
|
||||
type T = stable_mir::mir::Operand;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::Operand::*;
|
||||
match self {
|
||||
Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)),
|
||||
Move(place) => stable_mir::mir::Operand::Move(place.stable(tables)),
|
||||
Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
|
||||
type T = stable_mir::mir::Constant;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::mir::Constant {
|
||||
span: self.span.stable(tables),
|
||||
user_ty: self.user_ty.map(|u| u.as_usize()).or(None),
|
||||
literal: self.const_.stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
|
||||
type T = stable_mir::mir::Place;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
stable_mir::mir::Place {
|
||||
local: self.local.as_usize(),
|
||||
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
|
||||
type T = stable_mir::mir::ProjectionElem;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::ProjectionElem::*;
|
||||
match self {
|
||||
Deref => stable_mir::mir::ProjectionElem::Deref,
|
||||
Field(idx, ty) => {
|
||||
stable_mir::mir::ProjectionElem::Field(idx.stable(tables), ty.stable(tables))
|
||||
}
|
||||
Index(local) => stable_mir::mir::ProjectionElem::Index(local.stable(tables)),
|
||||
ConstantIndex { offset, min_length, from_end } => {
|
||||
stable_mir::mir::ProjectionElem::ConstantIndex {
|
||||
offset: *offset,
|
||||
min_length: *min_length,
|
||||
from_end: *from_end,
|
||||
}
|
||||
}
|
||||
Subslice { from, to, from_end } => stable_mir::mir::ProjectionElem::Subslice {
|
||||
from: *from,
|
||||
to: *to,
|
||||
from_end: *from_end,
|
||||
},
|
||||
// MIR includes an `Option<Symbol>` argument for `Downcast` that is the name of the
|
||||
// variant, used for printing MIR. However this information should also be accessible
|
||||
// via a lookup using the `VariantIdx`. The `Option<Symbol>` argument is therefore
|
||||
// dropped when converting to Stable MIR. A brief justification for this decision can be
|
||||
// found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486
|
||||
Downcast(_, idx) => stable_mir::mir::ProjectionElem::Downcast(idx.stable(tables)),
|
||||
OpaqueCast(ty) => stable_mir::mir::ProjectionElem::OpaqueCast(ty.stable(tables)),
|
||||
Subtype(ty) => stable_mir::mir::ProjectionElem::Subtype(ty.stable(tables)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
|
||||
type T = stable_mir::mir::UserTypeProjection;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Local {
|
||||
type T = stable_mir::mir::Local;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::RetagKind {
|
||||
type T = stable_mir::mir::RetagKind;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::RetagKind;
|
||||
match self {
|
||||
RetagKind::FnEntry => stable_mir::mir::RetagKind::FnEntry,
|
||||
RetagKind::TwoPhase => stable_mir::mir::RetagKind::TwoPhase,
|
||||
RetagKind::Raw => stable_mir::mir::RetagKind::Raw,
|
||||
RetagKind::Default => stable_mir::mir::RetagKind::Default,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::UnwindAction {
|
||||
type T = stable_mir::mir::UnwindAction;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::UnwindAction;
|
||||
match self {
|
||||
UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
|
||||
UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable,
|
||||
UnwindAction::Terminate(_) => stable_mir::mir::UnwindAction::Terminate,
|
||||
UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
|
||||
type T = stable_mir::mir::NonDivergingIntrinsic;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::NonDivergingIntrinsic;
|
||||
use stable_mir::mir::CopyNonOverlapping;
|
||||
match self {
|
||||
NonDivergingIntrinsic::Assume(op) => {
|
||||
stable_mir::mir::NonDivergingIntrinsic::Assume(op.stable(tables))
|
||||
}
|
||||
NonDivergingIntrinsic::CopyNonOverlapping(copy_non_overlapping) => {
|
||||
stable_mir::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
|
||||
src: copy_non_overlapping.src.stable(tables),
|
||||
dst: copy_non_overlapping.dst.stable(tables),
|
||||
count: copy_non_overlapping.count.stable(tables),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
|
||||
type T = stable_mir::mir::AssertMessage;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::AssertKind;
|
||||
match self {
|
||||
AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
|
||||
len: len.stable(tables),
|
||||
index: index.stable(tables),
|
||||
},
|
||||
AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
|
||||
bin_op.stable(tables),
|
||||
op1.stable(tables),
|
||||
op2.stable(tables),
|
||||
),
|
||||
AssertKind::OverflowNeg(op) => {
|
||||
stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables))
|
||||
}
|
||||
AssertKind::DivisionByZero(op) => {
|
||||
stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables))
|
||||
}
|
||||
AssertKind::RemainderByZero(op) => {
|
||||
stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
|
||||
}
|
||||
AssertKind::ResumedAfterReturn(coroutine) => {
|
||||
stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables))
|
||||
}
|
||||
AssertKind::ResumedAfterPanic(coroutine) => {
|
||||
stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables))
|
||||
}
|
||||
AssertKind::MisalignedPointerDereference { required, found } => {
|
||||
stable_mir::mir::AssertMessage::MisalignedPointerDereference {
|
||||
required: required.stable(tables),
|
||||
found: found.stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::BinOp {
|
||||
type T = stable_mir::mir::BinOp;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::BinOp;
|
||||
match self {
|
||||
BinOp::Add => stable_mir::mir::BinOp::Add,
|
||||
BinOp::AddUnchecked => stable_mir::mir::BinOp::AddUnchecked,
|
||||
BinOp::Sub => stable_mir::mir::BinOp::Sub,
|
||||
BinOp::SubUnchecked => stable_mir::mir::BinOp::SubUnchecked,
|
||||
BinOp::Mul => stable_mir::mir::BinOp::Mul,
|
||||
BinOp::MulUnchecked => stable_mir::mir::BinOp::MulUnchecked,
|
||||
BinOp::Div => stable_mir::mir::BinOp::Div,
|
||||
BinOp::Rem => stable_mir::mir::BinOp::Rem,
|
||||
BinOp::BitXor => stable_mir::mir::BinOp::BitXor,
|
||||
BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd,
|
||||
BinOp::BitOr => stable_mir::mir::BinOp::BitOr,
|
||||
BinOp::Shl => stable_mir::mir::BinOp::Shl,
|
||||
BinOp::ShlUnchecked => stable_mir::mir::BinOp::ShlUnchecked,
|
||||
BinOp::Shr => stable_mir::mir::BinOp::Shr,
|
||||
BinOp::ShrUnchecked => stable_mir::mir::BinOp::ShrUnchecked,
|
||||
BinOp::Eq => stable_mir::mir::BinOp::Eq,
|
||||
BinOp::Lt => stable_mir::mir::BinOp::Lt,
|
||||
BinOp::Le => stable_mir::mir::BinOp::Le,
|
||||
BinOp::Ne => stable_mir::mir::BinOp::Ne,
|
||||
BinOp::Ge => stable_mir::mir::BinOp::Ge,
|
||||
BinOp::Gt => stable_mir::mir::BinOp::Gt,
|
||||
BinOp::Offset => stable_mir::mir::BinOp::Offset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::UnOp {
|
||||
type T = stable_mir::mir::UnOp;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::UnOp;
|
||||
match self {
|
||||
UnOp::Not => stable_mir::mir::UnOp::Not,
|
||||
UnOp::Neg => stable_mir::mir::UnOp::Neg,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
|
||||
type T = stable_mir::mir::AggregateKind;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
mir::AggregateKind::Array(ty) => {
|
||||
stable_mir::mir::AggregateKind::Array(ty.stable(tables))
|
||||
}
|
||||
mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple,
|
||||
mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => {
|
||||
stable_mir::mir::AggregateKind::Adt(
|
||||
tables.adt_def(*def_id),
|
||||
var_idx.index(),
|
||||
generic_arg.stable(tables),
|
||||
user_ty_index.map(|idx| idx.index()),
|
||||
field_idx.map(|idx| idx.index()),
|
||||
)
|
||||
}
|
||||
mir::AggregateKind::Closure(def_id, generic_arg) => {
|
||||
stable_mir::mir::AggregateKind::Closure(
|
||||
tables.closure_def(*def_id),
|
||||
generic_arg.stable(tables),
|
||||
)
|
||||
}
|
||||
mir::AggregateKind::Coroutine(def_id, generic_arg, movability) => {
|
||||
stable_mir::mir::AggregateKind::Coroutine(
|
||||
tables.coroutine_def(*def_id),
|
||||
generic_arg.stable(tables),
|
||||
movability.stable(tables),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
|
||||
type T = stable_mir::mir::InlineAsmOperand;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::mir::InlineAsmOperand;
|
||||
|
||||
let (in_value, out_place) = match self {
|
||||
InlineAsmOperand::In { value, .. } => (Some(value.stable(tables)), None),
|
||||
InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable(tables))),
|
||||
InlineAsmOperand::InOut { in_value, out_place, .. } => {
|
||||
(Some(in_value.stable(tables)), out_place.map(|place| place.stable(tables)))
|
||||
}
|
||||
InlineAsmOperand::Const { .. }
|
||||
| InlineAsmOperand::SymFn { .. }
|
||||
| InlineAsmOperand::SymStatic { .. } => (None, None),
|
||||
};
|
||||
|
||||
stable_mir::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
|
||||
type T = stable_mir::mir::Terminator;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::mir::Terminator;
|
||||
Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
||||
type T = stable_mir::mir::TerminatorKind;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::mir::TerminatorKind;
|
||||
match self {
|
||||
mir::TerminatorKind::Goto { target } => {
|
||||
TerminatorKind::Goto { target: target.as_usize() }
|
||||
}
|
||||
mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
|
||||
discr: discr.stable(tables),
|
||||
targets: targets
|
||||
.iter()
|
||||
.map(|(value, target)| stable_mir::mir::SwitchTarget {
|
||||
value,
|
||||
target: target.as_usize(),
|
||||
})
|
||||
.collect(),
|
||||
otherwise: targets.otherwise().as_usize(),
|
||||
},
|
||||
mir::TerminatorKind::UnwindResume => TerminatorKind::Resume,
|
||||
mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort,
|
||||
mir::TerminatorKind::Return => TerminatorKind::Return,
|
||||
mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable,
|
||||
mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => {
|
||||
TerminatorKind::Drop {
|
||||
place: place.stable(tables),
|
||||
target: target.as_usize(),
|
||||
unwind: unwind.stable(tables),
|
||||
}
|
||||
}
|
||||
mir::TerminatorKind::Call {
|
||||
func,
|
||||
args,
|
||||
destination,
|
||||
target,
|
||||
unwind,
|
||||
call_source: _,
|
||||
fn_span: _,
|
||||
} => TerminatorKind::Call {
|
||||
func: func.stable(tables),
|
||||
args: args.iter().map(|arg| arg.stable(tables)).collect(),
|
||||
destination: destination.stable(tables),
|
||||
target: target.map(|t| t.as_usize()),
|
||||
unwind: unwind.stable(tables),
|
||||
},
|
||||
mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => {
|
||||
TerminatorKind::Assert {
|
||||
cond: cond.stable(tables),
|
||||
expected: *expected,
|
||||
msg: msg.stable(tables),
|
||||
target: target.as_usize(),
|
||||
unwind: unwind.stable(tables),
|
||||
}
|
||||
}
|
||||
mir::TerminatorKind::InlineAsm {
|
||||
template,
|
||||
operands,
|
||||
options,
|
||||
line_spans,
|
||||
destination,
|
||||
unwind,
|
||||
} => TerminatorKind::InlineAsm {
|
||||
template: format!("{template:?}"),
|
||||
operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
|
||||
options: format!("{options:?}"),
|
||||
line_spans: format!("{line_spans:?}"),
|
||||
destination: destination.map(|d| d.as_usize()),
|
||||
unwind: unwind.stable(tables),
|
||||
},
|
||||
mir::TerminatorKind::Yield { .. }
|
||||
| mir::TerminatorKind::CoroutineDrop
|
||||
| mir::TerminatorKind::FalseEdge { .. }
|
||||
| mir::TerminatorKind::FalseUnwind { .. } => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
|
||||
type T = Allocation;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
self.inner().stable(tables)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
|
||||
type T = stable_mir::ty::Allocation;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
alloc::allocation_filter(
|
||||
self,
|
||||
alloc_range(rustc_target::abi::Size::ZERO, self.size()),
|
||||
tables,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
|
||||
type T = stable_mir::mir::alloc::AllocId;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
tables.create_alloc_id(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
|
||||
type T = GlobalAlloc;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
mir::interpret::GlobalAlloc::Function(instance) => {
|
||||
GlobalAlloc::Function(instance.stable(tables))
|
||||
}
|
||||
mir::interpret::GlobalAlloc::VTable(ty, trait_ref) => {
|
||||
GlobalAlloc::VTable(ty.stable(tables), trait_ref.stable(tables))
|
||||
}
|
||||
mir::interpret::GlobalAlloc::Static(def) => {
|
||||
GlobalAlloc::Static(tables.static_def(*def))
|
||||
}
|
||||
mir::interpret::GlobalAlloc::Memory(alloc) => GlobalAlloc::Memory(alloc.stable(tables)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
|
||||
type T = stable_mir::ty::Const;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match *self {
|
||||
mir::Const::Ty(c) => c.stable(tables),
|
||||
mir::Const::Unevaluated(unev_const, ty) => {
|
||||
let kind =
|
||||
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
|
||||
def: tables.const_def(unev_const.def),
|
||||
args: unev_const.args.stable(tables),
|
||||
promoted: unev_const.promoted.map(|u| u.as_u32()),
|
||||
});
|
||||
let ty = ty.stable(tables);
|
||||
let id = tables.intern_const(*self);
|
||||
Const::new(kind, ty, id)
|
||||
}
|
||||
mir::Const::Val(val, ty) if matches!(val, mir::ConstValue::ZeroSized) => {
|
||||
let ty = ty.stable(tables);
|
||||
let id = tables.intern_const(*self);
|
||||
Const::new(ConstantKind::ZeroSized, ty, id)
|
||||
}
|
||||
mir::Const::Val(val, ty) => {
|
||||
let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables));
|
||||
let ty = ty.stable(tables);
|
||||
let id = tables.intern_const(*self);
|
||||
Const::new(kind, ty, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
|
||||
type T = Error;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
Error::new(format!("{self:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
|
||||
type T = stable_mir::mir::mono::MonoItem;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::mir::mono::MonoItem as StableMonoItem;
|
||||
match self {
|
||||
MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)),
|
||||
MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)),
|
||||
MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)),
|
||||
}
|
||||
}
|
||||
}
|
76
compiler/rustc_smir/src/rustc_smir/convert/mod.rs
Normal file
76
compiler/rustc_smir/src/rustc_smir/convert/mod.rs
Normal file
@ -0,0 +1,76 @@
|
||||
//! Conversion of internal Rust compiler items to stable ones.
|
||||
|
||||
use rustc_target::abi::FieldIdx;
|
||||
use stable_mir::mir::VariantIdx;
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
|
||||
mod mir;
|
||||
mod ty;
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_hir::Unsafety {
|
||||
type T = stable_mir::mir::Safety;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe,
|
||||
rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for FieldIdx {
|
||||
type T = usize;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for (rustc_target::abi::VariantIdx, FieldIdx) {
|
||||
type T = (usize, usize);
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
(self.0.as_usize(), self.1.as_usize())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_target::abi::VariantIdx {
|
||||
type T = VariantIdx;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
|
||||
type T = stable_mir::mir::CoroutineSource;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_hir::CoroutineSource;
|
||||
match self {
|
||||
CoroutineSource::Block => stable_mir::mir::CoroutineSource::Block,
|
||||
CoroutineSource::Closure => stable_mir::mir::CoroutineSource::Closure,
|
||||
CoroutineSource::Fn => stable_mir::mir::CoroutineSource::Fn,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
|
||||
type T = stable_mir::mir::CoroutineKind;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_hir::CoroutineKind;
|
||||
match self {
|
||||
CoroutineKind::Async(source) => {
|
||||
stable_mir::mir::CoroutineKind::Async(source.stable(tables))
|
||||
}
|
||||
CoroutineKind::Gen(source) => {
|
||||
stable_mir::mir::CoroutineKind::Gen(source.stable(tables))
|
||||
}
|
||||
CoroutineKind::Coroutine => stable_mir::mir::CoroutineKind::Coroutine,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_span::Span {
|
||||
type T = stable_mir::ty::Span;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
tables.create_span(*self)
|
||||
}
|
||||
}
|
815
compiler/rustc_smir/src/rustc_smir/convert/ty.rs
Normal file
815
compiler/rustc_smir/src/rustc_smir/convert/ty.rs
Normal file
@ -0,0 +1,815 @@
|
||||
//! Conversion of internal Rust compiler `ty` items to stable ones.
|
||||
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_middle::{mir, ty};
|
||||
use stable_mir::ty::{
|
||||
AdtKind, Const, ConstantKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy,
|
||||
TyKind, UintTy,
|
||||
};
|
||||
|
||||
use crate::rustc_smir::{alloc, Stable, Tables};
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::AliasKind {
|
||||
type T = stable_mir::ty::AliasKind;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::ty::AliasKind::*;
|
||||
match self {
|
||||
Projection => stable_mir::ty::AliasKind::Projection,
|
||||
Inherent => stable_mir::ty::AliasKind::Inherent,
|
||||
Opaque => stable_mir::ty::AliasKind::Opaque,
|
||||
Weak => stable_mir::ty::AliasKind::Weak,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
|
||||
type T = stable_mir::ty::AliasTy;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let ty::AliasTy { args, def_id, .. } = self;
|
||||
stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::DynKind {
|
||||
type T = stable_mir::ty::DynKind;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::ty::DynKind;
|
||||
match self {
|
||||
DynKind::Dyn => stable_mir::ty::DynKind::Dyn,
|
||||
DynKind::DynStar => stable_mir::ty::DynKind::DynStar,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
|
||||
type T = stable_mir::ty::ExistentialPredicate;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::ExistentialPredicate::*;
|
||||
match self {
|
||||
ty::ExistentialPredicate::Trait(existential_trait_ref) => {
|
||||
Trait(existential_trait_ref.stable(tables))
|
||||
}
|
||||
ty::ExistentialPredicate::Projection(existential_projection) => {
|
||||
Projection(existential_projection.stable(tables))
|
||||
}
|
||||
ty::ExistentialPredicate::AutoTrait(def_id) => AutoTrait(tables.trait_def(*def_id)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
|
||||
type T = stable_mir::ty::ExistentialTraitRef;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let ty::ExistentialTraitRef { def_id, args } = self;
|
||||
stable_mir::ty::ExistentialTraitRef {
|
||||
def_id: tables.trait_def(*def_id),
|
||||
generic_args: args.stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
|
||||
type T = stable_mir::ty::TermKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::TermKind;
|
||||
match self {
|
||||
ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables)),
|
||||
ty::TermKind::Const(cnst) => {
|
||||
let cnst = cnst.stable(tables);
|
||||
TermKind::Const(cnst)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
|
||||
type T = stable_mir::ty::ExistentialProjection;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let ty::ExistentialProjection { def_id, args, term } = self;
|
||||
stable_mir::ty::ExistentialProjection {
|
||||
def_id: tables.trait_def(*def_id),
|
||||
generic_args: args.stable(tables),
|
||||
term: term.unpack().stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
|
||||
type T = stable_mir::mir::PointerCoercion;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
match self {
|
||||
PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer,
|
||||
PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer,
|
||||
PointerCoercion::ClosureFnPointer(unsafety) => {
|
||||
stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable(tables))
|
||||
}
|
||||
PointerCoercion::MutToConstPointer => {
|
||||
stable_mir::mir::PointerCoercion::MutToConstPointer
|
||||
}
|
||||
PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer,
|
||||
PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex {
|
||||
type T = usize;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::AdtKind {
|
||||
type T = AdtKind;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::AdtKind::Struct => AdtKind::Struct,
|
||||
ty::AdtKind::Union => AdtKind::Union,
|
||||
ty::AdtKind::Enum => AdtKind::Enum,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
|
||||
type T = stable_mir::ty::GenericArgs;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
GenericArgs(self.iter().map(|arg| arg.unpack().stable(tables)).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> {
|
||||
type T = stable_mir::ty::GenericArgKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::GenericArgKind;
|
||||
match self {
|
||||
ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(region.stable(tables)),
|
||||
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(ty.stable(tables)),
|
||||
ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, S, V> Stable<'tcx> for ty::Binder<'tcx, S>
|
||||
where
|
||||
S: Stable<'tcx, T = V>,
|
||||
{
|
||||
type T = stable_mir::ty::Binder<V>;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::Binder;
|
||||
|
||||
Binder {
|
||||
value: self.as_ref().skip_binder().stable(tables),
|
||||
bound_vars: self
|
||||
.bound_vars()
|
||||
.iter()
|
||||
.map(|bound_var| bound_var.stable(tables))
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<S>
|
||||
where
|
||||
S: Stable<'tcx, T = V>,
|
||||
{
|
||||
type T = stable_mir::ty::EarlyBinder<V>;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::EarlyBinder;
|
||||
|
||||
EarlyBinder { value: self.as_ref().skip_binder().stable(tables) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
|
||||
type T = stable_mir::ty::FnSig;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_target::spec::abi;
|
||||
use stable_mir::ty::{Abi, FnSig};
|
||||
|
||||
FnSig {
|
||||
inputs_and_output: self.inputs_and_output.iter().map(|ty| ty.stable(tables)).collect(),
|
||||
c_variadic: self.c_variadic,
|
||||
unsafety: self.unsafety.stable(tables),
|
||||
abi: match self.abi {
|
||||
abi::Abi::Rust => Abi::Rust,
|
||||
abi::Abi::C { unwind } => Abi::C { unwind },
|
||||
abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind },
|
||||
abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind },
|
||||
abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind },
|
||||
abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind },
|
||||
abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind },
|
||||
abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind },
|
||||
abi::Abi::Win64 { unwind } => Abi::Win64 { unwind },
|
||||
abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind },
|
||||
abi::Abi::PtxKernel => Abi::PtxKernel,
|
||||
abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt,
|
||||
abi::Abi::X86Interrupt => Abi::X86Interrupt,
|
||||
abi::Abi::AmdGpuKernel => Abi::AmdGpuKernel,
|
||||
abi::Abi::EfiApi => Abi::EfiApi,
|
||||
abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
|
||||
abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
|
||||
abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
|
||||
abi::Abi::Wasm => Abi::Wasm,
|
||||
abi::Abi::System { unwind } => Abi::System { unwind },
|
||||
abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
|
||||
abi::Abi::RustCall => Abi::RustCall,
|
||||
abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
|
||||
abi::Abi::Unadjusted => Abi::Unadjusted,
|
||||
abi::Abi::RustCold => Abi::RustCold,
|
||||
abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM,
|
||||
abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
|
||||
type T = stable_mir::ty::BoundTyKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::BoundTyKind;
|
||||
|
||||
match self {
|
||||
ty::BoundTyKind::Anon => BoundTyKind::Anon,
|
||||
ty::BoundTyKind::Param(def_id, symbol) => {
|
||||
BoundTyKind::Param(tables.param_def(*def_id), symbol.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
|
||||
type T = stable_mir::ty::BoundRegionKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::BoundRegionKind;
|
||||
|
||||
match self {
|
||||
ty::BoundRegionKind::BrAnon => BoundRegionKind::BrAnon,
|
||||
ty::BoundRegionKind::BrNamed(def_id, symbol) => {
|
||||
BoundRegionKind::BrNamed(tables.br_named_def(*def_id), symbol.to_string())
|
||||
}
|
||||
ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
|
||||
type T = stable_mir::ty::BoundVariableKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::BoundVariableKind;
|
||||
|
||||
match self {
|
||||
ty::BoundVariableKind::Ty(bound_ty_kind) => {
|
||||
BoundVariableKind::Ty(bound_ty_kind.stable(tables))
|
||||
}
|
||||
ty::BoundVariableKind::Region(bound_region_kind) => {
|
||||
BoundVariableKind::Region(bound_region_kind.stable(tables))
|
||||
}
|
||||
ty::BoundVariableKind::Const => BoundVariableKind::Const,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::IntTy {
|
||||
type T = IntTy;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::IntTy::Isize => IntTy::Isize,
|
||||
ty::IntTy::I8 => IntTy::I8,
|
||||
ty::IntTy::I16 => IntTy::I16,
|
||||
ty::IntTy::I32 => IntTy::I32,
|
||||
ty::IntTy::I64 => IntTy::I64,
|
||||
ty::IntTy::I128 => IntTy::I128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::UintTy {
|
||||
type T = UintTy;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::UintTy::Usize => UintTy::Usize,
|
||||
ty::UintTy::U8 => UintTy::U8,
|
||||
ty::UintTy::U16 => UintTy::U16,
|
||||
ty::UintTy::U32 => UintTy::U32,
|
||||
ty::UintTy::U64 => UintTy::U64,
|
||||
ty::UintTy::U128 => UintTy::U128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::FloatTy {
|
||||
type T = FloatTy;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::FloatTy::F32 => FloatTy::F32,
|
||||
ty::FloatTy::F64 => FloatTy::F64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for Ty<'tcx> {
|
||||
type T = stable_mir::ty::Ty;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
tables.intern_ty(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
|
||||
type T = stable_mir::ty::TyKind;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::Bool => TyKind::RigidTy(RigidTy::Bool),
|
||||
ty::Char => TyKind::RigidTy(RigidTy::Char),
|
||||
ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables))),
|
||||
ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))),
|
||||
ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))),
|
||||
ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
|
||||
tables.adt_def(adt_def.did()),
|
||||
generic_args.stable(tables),
|
||||
)),
|
||||
ty::Foreign(def_id) => TyKind::RigidTy(RigidTy::Foreign(tables.foreign_def(*def_id))),
|
||||
ty::Str => TyKind::RigidTy(RigidTy::Str),
|
||||
ty::Array(ty, constant) => {
|
||||
TyKind::RigidTy(RigidTy::Array(ty.stable(tables), constant.stable(tables)))
|
||||
}
|
||||
ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables))),
|
||||
ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
|
||||
TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables), mutbl.stable(tables)))
|
||||
}
|
||||
ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
|
||||
region.stable(tables),
|
||||
ty.stable(tables),
|
||||
mutbl.stable(tables),
|
||||
)),
|
||||
ty::FnDef(def_id, generic_args) => {
|
||||
TyKind::RigidTy(RigidTy::FnDef(tables.fn_def(*def_id), generic_args.stable(tables)))
|
||||
}
|
||||
ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
|
||||
ty::Dynamic(existential_predicates, region, dyn_kind) => {
|
||||
TyKind::RigidTy(RigidTy::Dynamic(
|
||||
existential_predicates
|
||||
.iter()
|
||||
.map(|existential_predicate| existential_predicate.stable(tables))
|
||||
.collect(),
|
||||
region.stable(tables),
|
||||
dyn_kind.stable(tables),
|
||||
))
|
||||
}
|
||||
ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
|
||||
tables.closure_def(*def_id),
|
||||
generic_args.stable(tables),
|
||||
)),
|
||||
ty::Coroutine(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Coroutine(
|
||||
tables.coroutine_def(*def_id),
|
||||
generic_args.stable(tables),
|
||||
movability.stable(tables),
|
||||
)),
|
||||
ty::Never => TyKind::RigidTy(RigidTy::Never),
|
||||
ty::Tuple(fields) => {
|
||||
TyKind::RigidTy(RigidTy::Tuple(fields.iter().map(|ty| ty.stable(tables)).collect()))
|
||||
}
|
||||
ty::Alias(alias_kind, alias_ty) => {
|
||||
TyKind::Alias(alias_kind.stable(tables), alias_ty.stable(tables))
|
||||
}
|
||||
ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables)),
|
||||
ty::Bound(debruijn_idx, bound_ty) => {
|
||||
TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables))
|
||||
}
|
||||
ty::CoroutineWitness(def_id, args) => TyKind::RigidTy(RigidTy::CoroutineWitness(
|
||||
tables.coroutine_witness_def(*def_id),
|
||||
args.stable(tables),
|
||||
)),
|
||||
ty::Placeholder(..) | ty::Infer(_) | ty::Error(_) => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
|
||||
type T = stable_mir::ty::Const;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let kind = match self.kind() {
|
||||
ty::Value(val) => {
|
||||
let const_val = tables.tcx.valtree_to_const_val((self.ty(), val));
|
||||
if matches!(const_val, mir::ConstValue::ZeroSized) {
|
||||
ConstantKind::ZeroSized
|
||||
} else {
|
||||
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
|
||||
self.ty(),
|
||||
const_val,
|
||||
tables,
|
||||
))
|
||||
}
|
||||
}
|
||||
ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
|
||||
ty::ErrorCt(_) => unreachable!(),
|
||||
ty::InferCt(_) => unreachable!(),
|
||||
ty::BoundCt(_, _) => unimplemented!(),
|
||||
ty::PlaceholderCt(_) => unimplemented!(),
|
||||
ty::Unevaluated(uv) => {
|
||||
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
|
||||
def: tables.const_def(uv.def),
|
||||
args: uv.args.stable(tables),
|
||||
promoted: None,
|
||||
})
|
||||
}
|
||||
ty::ExprCt(_) => unimplemented!(),
|
||||
};
|
||||
let ty = self.ty().stable(tables);
|
||||
let id = tables.intern_const(mir::Const::Ty(*self));
|
||||
Const::new(kind, ty, id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ParamConst {
|
||||
type T = stable_mir::ty::ParamConst;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::ParamConst;
|
||||
ParamConst { index: self.index, name: self.name.to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ParamTy {
|
||||
type T = stable_mir::ty::ParamTy;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::ParamTy;
|
||||
ParamTy { index: self.index, name: self.name.to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::BoundTy {
|
||||
type T = stable_mir::ty::BoundTy;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::BoundTy;
|
||||
BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
|
||||
type T = stable_mir::ty::TraitSpecializationKind;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::TraitSpecializationKind;
|
||||
|
||||
match self {
|
||||
ty::trait_def::TraitSpecializationKind::None => TraitSpecializationKind::None,
|
||||
ty::trait_def::TraitSpecializationKind::Marker => TraitSpecializationKind::Marker,
|
||||
ty::trait_def::TraitSpecializationKind::AlwaysApplicable => {
|
||||
TraitSpecializationKind::AlwaysApplicable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::TraitDef {
|
||||
type T = stable_mir::ty::TraitDecl;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::opaque;
|
||||
use stable_mir::ty::TraitDecl;
|
||||
|
||||
TraitDecl {
|
||||
def_id: tables.trait_def(self.def_id),
|
||||
unsafety: self.unsafety.stable(tables),
|
||||
paren_sugar: self.paren_sugar,
|
||||
has_auto_impl: self.has_auto_impl,
|
||||
is_marker: self.is_marker,
|
||||
is_coinductive: self.is_coinductive,
|
||||
skip_array_during_method_dispatch: self.skip_array_during_method_dispatch,
|
||||
specialization_kind: self.specialization_kind.stable(tables),
|
||||
must_implement_one_of: self
|
||||
.must_implement_one_of
|
||||
.as_ref()
|
||||
.map(|idents| idents.iter().map(|ident| opaque(ident)).collect()),
|
||||
implement_via_object: self.implement_via_object,
|
||||
deny_explicit_impl: self.deny_explicit_impl,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
|
||||
type T = stable_mir::ty::TraitRef;
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::TraitRef;
|
||||
|
||||
TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Generics {
|
||||
type T = stable_mir::ty::Generics;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::Generics;
|
||||
|
||||
let params: Vec<_> = self.params.iter().map(|param| param.stable(tables)).collect();
|
||||
let param_def_id_to_index =
|
||||
params.iter().map(|param| (param.def_id, param.index)).collect();
|
||||
|
||||
Generics {
|
||||
parent: self.parent.map(|did| tables.generic_def(did)),
|
||||
parent_count: self.parent_count,
|
||||
params,
|
||||
param_def_id_to_index,
|
||||
has_self: self.has_self,
|
||||
has_late_bound_regions: self
|
||||
.has_late_bound_regions
|
||||
.as_ref()
|
||||
.map(|late_bound_regions| late_bound_regions.stable(tables)),
|
||||
host_effect_index: self.host_effect_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
|
||||
type T = stable_mir::ty::GenericParamDefKind;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::GenericParamDefKind;
|
||||
match self {
|
||||
ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime,
|
||||
ty::GenericParamDefKind::Type { has_default, synthetic } => {
|
||||
GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic }
|
||||
}
|
||||
ty::GenericParamDefKind::Const { has_default, is_host_effect: _ } => {
|
||||
GenericParamDefKind::Const { has_default: *has_default }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef {
|
||||
type T = stable_mir::ty::GenericParamDef;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
GenericParamDef {
|
||||
name: self.name.to_string(),
|
||||
def_id: tables.generic_def(self.def_id),
|
||||
index: self.index,
|
||||
pure_wrt_drop: self.pure_wrt_drop,
|
||||
kind: self.kind.stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
|
||||
type T = stable_mir::ty::PredicateKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::ty::PredicateKind;
|
||||
match self {
|
||||
PredicateKind::Clause(clause_kind) => {
|
||||
stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables))
|
||||
}
|
||||
PredicateKind::ObjectSafe(did) => {
|
||||
stable_mir::ty::PredicateKind::ObjectSafe(tables.trait_def(*did))
|
||||
}
|
||||
PredicateKind::Subtype(subtype_predicate) => {
|
||||
stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables))
|
||||
}
|
||||
PredicateKind::Coerce(coerce_predicate) => {
|
||||
stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables))
|
||||
}
|
||||
PredicateKind::ConstEquate(a, b) => {
|
||||
stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables))
|
||||
}
|
||||
PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous,
|
||||
PredicateKind::AliasRelate(a, b, alias_relation_direction) => {
|
||||
stable_mir::ty::PredicateKind::AliasRelate(
|
||||
a.unpack().stable(tables),
|
||||
b.unpack().stable(tables),
|
||||
alias_relation_direction.stable(tables),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
|
||||
type T = stable_mir::ty::ClauseKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::ty::ClauseKind;
|
||||
match *self {
|
||||
ClauseKind::Trait(trait_object) => {
|
||||
stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables))
|
||||
}
|
||||
ClauseKind::RegionOutlives(region_outlives) => {
|
||||
stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables))
|
||||
}
|
||||
ClauseKind::TypeOutlives(type_outlives) => {
|
||||
let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives;
|
||||
stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate(
|
||||
a.stable(tables),
|
||||
b.stable(tables),
|
||||
))
|
||||
}
|
||||
ClauseKind::Projection(projection_predicate) => {
|
||||
stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables))
|
||||
}
|
||||
ClauseKind::ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType(
|
||||
const_.stable(tables),
|
||||
ty.stable(tables),
|
||||
),
|
||||
ClauseKind::WellFormed(generic_arg) => {
|
||||
stable_mir::ty::ClauseKind::WellFormed(generic_arg.unpack().stable(tables))
|
||||
}
|
||||
ClauseKind::ConstEvaluatable(const_) => {
|
||||
stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ClosureKind {
|
||||
type T = stable_mir::ty::ClosureKind;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::ty::ClosureKind::*;
|
||||
match self {
|
||||
Fn => stable_mir::ty::ClosureKind::Fn,
|
||||
FnMut => stable_mir::ty::ClosureKind::FnMut,
|
||||
FnOnce => stable_mir::ty::ClosureKind::FnOnce,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> {
|
||||
type T = stable_mir::ty::SubtypePredicate;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let ty::SubtypePredicate { a, b, a_is_expected: _ } = self;
|
||||
stable_mir::ty::SubtypePredicate { a: a.stable(tables), b: b.stable(tables) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> {
|
||||
type T = stable_mir::ty::CoercePredicate;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let ty::CoercePredicate { a, b } = self;
|
||||
stable_mir::ty::CoercePredicate { a: a.stable(tables), b: b.stable(tables) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection {
|
||||
type T = stable_mir::ty::AliasRelationDirection;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::ty::AliasRelationDirection::*;
|
||||
match self {
|
||||
Equate => stable_mir::ty::AliasRelationDirection::Equate,
|
||||
Subtype => stable_mir::ty::AliasRelationDirection::Subtype,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> {
|
||||
type T = stable_mir::ty::TraitPredicate;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let ty::TraitPredicate { trait_ref, polarity } = self;
|
||||
stable_mir::ty::TraitPredicate {
|
||||
trait_ref: trait_ref.stable(tables),
|
||||
polarity: polarity.stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, A, B, U, V> Stable<'tcx> for ty::OutlivesPredicate<A, B>
|
||||
where
|
||||
A: Stable<'tcx, T = U>,
|
||||
B: Stable<'tcx, T = V>,
|
||||
{
|
||||
type T = stable_mir::ty::OutlivesPredicate<U, V>;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let ty::OutlivesPredicate(a, b) = self;
|
||||
stable_mir::ty::OutlivesPredicate(a.stable(tables), b.stable(tables))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> {
|
||||
type T = stable_mir::ty::ProjectionPredicate;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let ty::ProjectionPredicate { projection_ty, term } = self;
|
||||
stable_mir::ty::ProjectionPredicate {
|
||||
projection_ty: projection_ty.stable(tables),
|
||||
term: term.unpack().stable(tables),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::ImplPolarity {
|
||||
type T = stable_mir::ty::ImplPolarity;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
use rustc_middle::ty::ImplPolarity::*;
|
||||
match self {
|
||||
Positive => stable_mir::ty::ImplPolarity::Positive,
|
||||
Negative => stable_mir::ty::ImplPolarity::Negative,
|
||||
Reservation => stable_mir::ty::ImplPolarity::Reservation,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Region<'tcx> {
|
||||
type T = stable_mir::ty::Region;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
Region { kind: self.kind().stable(tables) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
|
||||
type T = stable_mir::ty::RegionKind;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
use stable_mir::ty::{BoundRegion, EarlyParamRegion, RegionKind};
|
||||
match self {
|
||||
ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion {
|
||||
def_id: tables.region_def(early_reg.def_id),
|
||||
index: early_reg.index,
|
||||
name: early_reg.name.to_string(),
|
||||
}),
|
||||
ty::ReBound(db_index, bound_reg) => RegionKind::ReBound(
|
||||
db_index.as_u32(),
|
||||
BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) },
|
||||
),
|
||||
ty::ReStatic => RegionKind::ReStatic,
|
||||
ty::RePlaceholder(place_holder) => {
|
||||
RegionKind::RePlaceholder(stable_mir::ty::Placeholder {
|
||||
universe: place_holder.universe.as_u32(),
|
||||
bound: BoundRegion {
|
||||
var: place_holder.bound.var.as_u32(),
|
||||
kind: place_holder.bound.kind.stable(tables),
|
||||
},
|
||||
})
|
||||
}
|
||||
ty::ReErased => RegionKind::ReErased,
|
||||
_ => unreachable!("{self:?}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
|
||||
type T = stable_mir::mir::mono::Instance;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||
let def = tables.instance_def(*self);
|
||||
let kind = match self.def {
|
||||
ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item,
|
||||
ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic,
|
||||
ty::InstanceDef::Virtual(..) => stable_mir::mir::mono::InstanceKind::Virtual,
|
||||
ty::InstanceDef::VTableShim(..)
|
||||
| ty::InstanceDef::ReifyShim(..)
|
||||
| ty::InstanceDef::FnPtrAddrShim(..)
|
||||
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||
| ty::InstanceDef::ThreadLocalShim(..)
|
||||
| ty::InstanceDef::DropGlue(..)
|
||||
| ty::InstanceDef::CloneShim(..)
|
||||
| ty::InstanceDef::FnPtrShim(..) => stable_mir::mir::mono::InstanceKind::Shim,
|
||||
};
|
||||
stable_mir::mir::mono::Instance { def, kind }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Variance {
|
||||
type T = stable_mir::mir::Variance;
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::Variance::Bivariant => stable_mir::mir::Variance::Bivariant,
|
||||
ty::Variance::Contravariant => stable_mir::mir::Variance::Contravariant,
|
||||
ty::Variance::Covariant => stable_mir::mir::Variance::Covariant,
|
||||
ty::Variance::Invariant => stable_mir::mir::Variance::Invariant,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for ty::Movability {
|
||||
type T = stable_mir::ty::Movability;
|
||||
|
||||
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||
match self {
|
||||
ty::Movability::Static => stable_mir::ty::Movability::Static,
|
||||
ty::Movability::Movable => stable_mir::ty::Movability::Movable,
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@ use rustc_index::IndexVec;
|
||||
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
|
||||
use rustc_infer::infer::resolve::EagerResolver;
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
||||
use rustc_middle::infer::canonical::Canonical;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
@ -25,10 +26,7 @@ use rustc_middle::traits::solve::{
|
||||
ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
|
||||
};
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{
|
||||
self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use std::iter;
|
||||
use std::ops::Deref;
|
||||
@ -58,7 +56,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
) -> (Vec<ty::GenericArg<'tcx>>, CanonicalInput<'tcx, T>) {
|
||||
let opaque_types = self.infcx.clone_opaque_types_for_query_response();
|
||||
let (goal, opaque_types) =
|
||||
(goal, opaque_types).fold_with(&mut EagerResolver { infcx: self.infcx });
|
||||
(goal, opaque_types).fold_with(&mut EagerResolver::new(self.infcx));
|
||||
|
||||
let mut orig_values = Default::default();
|
||||
let canonical_goal = Canonicalizer::canonicalize(
|
||||
@ -115,7 +113,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
let external_constraints = self.compute_external_query_constraints()?;
|
||||
|
||||
let (var_values, mut external_constraints) =
|
||||
(var_values, external_constraints).fold_with(&mut EagerResolver { infcx: self.infcx });
|
||||
(var_values, external_constraints).fold_with(&mut EagerResolver::new(self.infcx));
|
||||
// Remove any trivial region constraints once we've resolved regions
|
||||
external_constraints
|
||||
.region_constraints
|
||||
@ -364,86 +362,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves ty, region, and const vars to their inferred values or their root vars.
|
||||
struct EagerResolver<'a, 'tcx> {
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.infcx.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match *t.kind() {
|
||||
ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
|
||||
Ok(t) => t.fold_with(self),
|
||||
Err(_) => Ty::new_var(self.infcx.tcx, self.infcx.root_var(vid)),
|
||||
},
|
||||
ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid),
|
||||
ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid),
|
||||
_ => {
|
||||
if t.has_infer() {
|
||||
t.super_fold_with(self)
|
||||
} else {
|
||||
t
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
match *r {
|
||||
ty::ReVar(vid) => self
|
||||
.infcx
|
||||
.inner
|
||||
.borrow_mut()
|
||||
.unwrap_region_constraints()
|
||||
.opportunistic_resolve_var(self.infcx.tcx, vid),
|
||||
_ => r,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
match c.kind() {
|
||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
||||
// FIXME: we need to fold the ty too, I think.
|
||||
match self.infcx.probe_const_var(vid) {
|
||||
Ok(c) => c.fold_with(self),
|
||||
Err(_) => {
|
||||
ty::Const::new_var(self.infcx.tcx, self.infcx.root_const_var(vid), c.ty())
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
|
||||
debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool);
|
||||
match self.infcx.probe_effect_var(vid) {
|
||||
Some(c) => c.as_const(self.infcx.tcx),
|
||||
None => ty::Const::new_infer(
|
||||
self.infcx.tcx,
|
||||
ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)),
|
||||
self.infcx.tcx.types.bool,
|
||||
),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if c.has_infer() {
|
||||
c.super_fold_with(self)
|
||||
} else {
|
||||
c
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> inspect::ProofTreeBuilder<'tcx> {
|
||||
pub fn make_canonical_state<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
ecx: &EvalCtxt<'_, 'tcx>,
|
||||
data: T,
|
||||
) -> inspect::CanonicalState<'tcx, T> {
|
||||
let state = inspect::State { var_values: ecx.var_values, data };
|
||||
let state = state.fold_with(&mut EagerResolver { infcx: ecx.infcx });
|
||||
let state = state.fold_with(&mut EagerResolver::new(ecx.infcx));
|
||||
Canonicalizer::canonicalize(
|
||||
ecx.infcx,
|
||||
CanonicalizeMode::Response { max_input_universe: ecx.max_input_universe },
|
||||
|
@ -1001,7 +1001,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
|
||||
&mut self,
|
||||
t: ty::Binder<'tcx, T>,
|
||||
) -> ty::Binder<'tcx, T> {
|
||||
if !t.has_placeholders() && !t.has_infer_regions() {
|
||||
if !t.has_placeholders() && !t.has_infer() {
|
||||
return t;
|
||||
}
|
||||
self.current_index.shift_in(1);
|
||||
@ -1048,6 +1048,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let ty = self.infcx.shallow_resolve(ty);
|
||||
match *ty.kind() {
|
||||
ty::Placeholder(p) => {
|
||||
let replace_var = self.mapped_types.get(&p);
|
||||
@ -1063,16 +1064,23 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
|
||||
);
|
||||
Ty::new_bound(self.infcx.tcx, db, *replace_var)
|
||||
}
|
||||
None => ty,
|
||||
None => {
|
||||
if ty.has_infer() {
|
||||
ty.super_fold_with(self)
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ if ty.has_placeholders() || ty.has_infer_regions() => ty.super_fold_with(self),
|
||||
_ if ty.has_placeholders() || ty.has_infer() => ty.super_fold_with(self),
|
||||
_ => ty,
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||
let ct = self.infcx.shallow_resolve(ct);
|
||||
if let ty::ConstKind::Placeholder(p) = ct.kind() {
|
||||
let replace_var = self.mapped_consts.get(&p);
|
||||
match replace_var {
|
||||
@ -1087,7 +1095,13 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
|
||||
);
|
||||
ty::Const::new_bound(self.infcx.tcx, db, *replace_var, ct.ty())
|
||||
}
|
||||
None => ct,
|
||||
None => {
|
||||
if ct.has_infer() {
|
||||
ct.super_fold_with(self)
|
||||
} else {
|
||||
ct
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ct.super_fold_with(self)
|
||||
|
164
compiler/stable_mir/src/compiler_interface.rs
Normal file
164
compiler/stable_mir/src/compiler_interface.rs
Normal file
@ -0,0 +1,164 @@
|
||||
//! Define the interface with the Rust compiler.
|
||||
//!
|
||||
//! StableMIR users should not use any of the items in this module directly.
|
||||
//! These APIs have no stability guarantee.
|
||||
|
||||
use std::cell::Cell;
|
||||
|
||||
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
||||
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
||||
use crate::mir::Body;
|
||||
use crate::ty::{
|
||||
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FnDef, GenericArgs,
|
||||
GenericPredicates, Generics, ImplDef, ImplTrait, LineInfo, RigidTy, Span, TraitDecl, TraitDef,
|
||||
Ty, TyKind,
|
||||
};
|
||||
use crate::{
|
||||
mir, Crate, CrateItem, CrateItems, DefId, Error, Filename, ImplTraitDecls, ItemKind, Symbol,
|
||||
TraitDecls,
|
||||
};
|
||||
|
||||
/// This trait defines the interface between stable_mir and the Rust compiler.
|
||||
/// Do not use this directly.
|
||||
pub trait Context {
|
||||
fn entry_fn(&self) -> Option<CrateItem>;
|
||||
/// Retrieve all items of the local crate that have a MIR associated with them.
|
||||
fn all_local_items(&self) -> CrateItems;
|
||||
fn mir_body(&self, item: DefId) -> mir::Body;
|
||||
fn all_trait_decls(&self) -> TraitDecls;
|
||||
fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
|
||||
fn all_trait_impls(&self) -> ImplTraitDecls;
|
||||
fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
|
||||
fn generics_of(&self, def_id: DefId) -> Generics;
|
||||
fn predicates_of(&self, def_id: DefId) -> GenericPredicates;
|
||||
fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates;
|
||||
/// Get information about the local crate.
|
||||
fn local_crate(&self) -> Crate;
|
||||
/// Retrieve a list of all external crates.
|
||||
fn external_crates(&self) -> Vec<Crate>;
|
||||
|
||||
/// Find a crate with the given name.
|
||||
fn find_crates(&self, name: &str) -> Vec<Crate>;
|
||||
|
||||
/// Returns the name of given `DefId`
|
||||
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
|
||||
|
||||
/// Returns printable, human readable form of `Span`
|
||||
fn span_to_string(&self, span: Span) -> String;
|
||||
|
||||
/// Return filename from given `Span`, for diagnostic purposes
|
||||
fn get_filename(&self, span: &Span) -> Filename;
|
||||
|
||||
/// Return lines corresponding to this `Span`
|
||||
fn get_lines(&self, span: &Span) -> LineInfo;
|
||||
|
||||
/// Returns the `kind` of given `DefId`
|
||||
fn item_kind(&self, item: CrateItem) -> ItemKind;
|
||||
|
||||
/// Returns whether this is a foreign item.
|
||||
fn is_foreign_item(&self, item: CrateItem) -> bool;
|
||||
|
||||
/// Returns the kind of a given algebraic data type
|
||||
fn adt_kind(&self, def: AdtDef) -> AdtKind;
|
||||
|
||||
/// Returns if the ADT is a box.
|
||||
fn adt_is_box(&self, def: AdtDef) -> bool;
|
||||
|
||||
/// Evaluate constant as a target usize.
|
||||
fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error>;
|
||||
|
||||
/// Create a target usize constant for the given value.
|
||||
fn usize_to_const(&self, val: u64) -> Result<Const, Error>;
|
||||
|
||||
/// Create a new type from the given kind.
|
||||
fn new_rigid_ty(&self, kind: RigidTy) -> Ty;
|
||||
|
||||
/// Returns the type of given crate item.
|
||||
fn def_ty(&self, item: DefId) -> Ty;
|
||||
|
||||
/// Returns literal value of a const as a string.
|
||||
fn const_literal(&self, cnst: &Const) -> String;
|
||||
|
||||
/// `Span` of an item
|
||||
fn span_of_an_item(&self, def_id: DefId) -> Span;
|
||||
|
||||
/// Obtain the representation of a type.
|
||||
fn ty_kind(&self, ty: Ty) -> TyKind;
|
||||
|
||||
/// Get the body of an Instance.
|
||||
/// FIXME: Monomorphize the body.
|
||||
fn instance_body(&self, instance: InstanceDef) -> Option<Body>;
|
||||
|
||||
/// Get the instance type with generic substitutions applied and lifetimes erased.
|
||||
fn instance_ty(&self, instance: InstanceDef) -> Ty;
|
||||
|
||||
/// Get the instance.
|
||||
fn instance_def_id(&self, instance: InstanceDef) -> DefId;
|
||||
|
||||
/// Get the instance mangled name.
|
||||
fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol;
|
||||
|
||||
/// Convert a non-generic crate item into an instance.
|
||||
/// This function will panic if the item is generic.
|
||||
fn mono_instance(&self, item: CrateItem) -> Instance;
|
||||
|
||||
/// Item requires monomorphization.
|
||||
fn requires_monomorphization(&self, def_id: DefId) -> bool;
|
||||
|
||||
/// Resolve an instance from the given function definition and generic arguments.
|
||||
fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
|
||||
|
||||
/// Resolve an instance for drop_in_place for the given type.
|
||||
fn resolve_drop_in_place(&self, ty: Ty) -> Instance;
|
||||
|
||||
/// Resolve instance for a function pointer.
|
||||
fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
|
||||
|
||||
/// Resolve instance for a closure with the requested type.
|
||||
fn resolve_closure(
|
||||
&self,
|
||||
def: ClosureDef,
|
||||
args: &GenericArgs,
|
||||
kind: ClosureKind,
|
||||
) -> Option<Instance>;
|
||||
|
||||
/// Evaluate a static's initializer.
|
||||
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>;
|
||||
|
||||
/// Retrieve global allocation for the given allocation ID.
|
||||
fn global_alloc(&self, id: AllocId) -> GlobalAlloc;
|
||||
|
||||
/// Retrieve the id for the virtual table.
|
||||
fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
|
||||
fn krate(&self, def_id: DefId) -> Crate;
|
||||
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol;
|
||||
}
|
||||
|
||||
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
||||
// datastructures and stable MIR datastructures
|
||||
scoped_thread_local! (static TLV: Cell<*const ()>);
|
||||
|
||||
pub fn run<F, T>(context: &dyn Context, f: F) -> Result<T, Error>
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
if TLV.is_set() {
|
||||
Err(Error::from("StableMIR already running"))
|
||||
} else {
|
||||
let ptr: *const () = &context as *const &_ as _;
|
||||
TLV.set(&Cell::new(ptr), || Ok(f()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute the given function with access the compiler [Context].
|
||||
///
|
||||
/// I.e., This function will load the current context and calls a function with it.
|
||||
/// Do not nest these, as that will ICE.
|
||||
pub(crate) fn with<R>(f: impl FnOnce(&dyn Context) -> R) -> R {
|
||||
assert!(TLV.is_set());
|
||||
TLV.with(|tlv| {
|
||||
let ptr = tlv.get();
|
||||
assert!(!ptr.is_null());
|
||||
f(unsafe { *(ptr as *const &dyn Context) })
|
||||
})
|
||||
}
|
@ -17,38 +17,31 @@
|
||||
//! The goal is to eventually be published on
|
||||
//! [crates.io](https://crates.io).
|
||||
|
||||
use crate::mir::mono::{InstanceDef, StaticDef};
|
||||
use crate::mir::Body;
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::{cell::Cell, io};
|
||||
|
||||
use self::ty::{
|
||||
GenericPredicates, Generics, ImplDef, ImplTrait, IndexedVal, LineInfo, Span, TraitDecl,
|
||||
TraitDef, Ty, TyKind,
|
||||
};
|
||||
|
||||
#[macro_use]
|
||||
extern crate scoped_tls;
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::Debug;
|
||||
use std::io;
|
||||
|
||||
use crate::compiler_interface::with;
|
||||
pub use crate::crate_def::CrateDef;
|
||||
pub use crate::crate_def::DefId;
|
||||
pub use crate::error::*;
|
||||
use crate::mir::pretty::function_name;
|
||||
use crate::mir::Body;
|
||||
use crate::mir::Mutability;
|
||||
use crate::ty::{ImplDef, ImplTrait, IndexedVal, Span, TraitDecl, TraitDef, Ty};
|
||||
|
||||
#[macro_use]
|
||||
pub mod crate_def;
|
||||
pub mod compiler_interface;
|
||||
#[macro_use]
|
||||
pub mod error;
|
||||
pub mod mir;
|
||||
pub mod ty;
|
||||
pub mod visitor;
|
||||
|
||||
pub use crate::crate_def::CrateDef;
|
||||
pub use crate::crate_def::DefId;
|
||||
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
||||
use crate::mir::pretty::function_name;
|
||||
use crate::mir::Mutability;
|
||||
use crate::ty::{AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, RigidTy};
|
||||
pub use error::*;
|
||||
use mir::mono::Instance;
|
||||
use ty::{FnDef, GenericArgs};
|
||||
|
||||
/// Use String for now but we should replace it.
|
||||
pub type Symbol = String;
|
||||
|
||||
@ -179,149 +172,6 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
|
||||
with(|cx| cx.trait_impl(trait_impl))
|
||||
}
|
||||
|
||||
/// This trait defines the interface between stable_mir and the Rust compiler.
|
||||
/// Do not use this directly.
|
||||
pub trait Context {
|
||||
fn entry_fn(&self) -> Option<CrateItem>;
|
||||
/// Retrieve all items of the local crate that have a MIR associated with them.
|
||||
fn all_local_items(&self) -> CrateItems;
|
||||
fn mir_body(&self, item: DefId) -> mir::Body;
|
||||
fn all_trait_decls(&self) -> TraitDecls;
|
||||
fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
|
||||
fn all_trait_impls(&self) -> ImplTraitDecls;
|
||||
fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
|
||||
fn generics_of(&self, def_id: DefId) -> Generics;
|
||||
fn predicates_of(&self, def_id: DefId) -> GenericPredicates;
|
||||
fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates;
|
||||
/// Get information about the local crate.
|
||||
fn local_crate(&self) -> Crate;
|
||||
/// Retrieve a list of all external crates.
|
||||
fn external_crates(&self) -> Vec<Crate>;
|
||||
|
||||
/// Find a crate with the given name.
|
||||
fn find_crates(&self, name: &str) -> Vec<Crate>;
|
||||
|
||||
/// Returns the name of given `DefId`
|
||||
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
|
||||
|
||||
/// Returns printable, human readable form of `Span`
|
||||
fn span_to_string(&self, span: Span) -> String;
|
||||
|
||||
/// Return filename from given `Span`, for diagnostic purposes
|
||||
fn get_filename(&self, span: &Span) -> Filename;
|
||||
|
||||
/// Return lines corresponding to this `Span`
|
||||
fn get_lines(&self, span: &Span) -> LineInfo;
|
||||
|
||||
/// Returns the `kind` of given `DefId`
|
||||
fn item_kind(&self, item: CrateItem) -> ItemKind;
|
||||
|
||||
/// Returns whether this is a foreign item.
|
||||
fn is_foreign_item(&self, item: CrateItem) -> bool;
|
||||
|
||||
/// Returns the kind of a given algebraic data type
|
||||
fn adt_kind(&self, def: AdtDef) -> AdtKind;
|
||||
|
||||
/// Returns if the ADT is a box.
|
||||
fn adt_is_box(&self, def: AdtDef) -> bool;
|
||||
|
||||
/// Evaluate constant as a target usize.
|
||||
fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error>;
|
||||
|
||||
/// Create a target usize constant for the given value.
|
||||
fn usize_to_const(&self, val: u64) -> Result<Const, Error>;
|
||||
|
||||
/// Create a new type from the given kind.
|
||||
fn new_rigid_ty(&self, kind: RigidTy) -> Ty;
|
||||
|
||||
/// Returns the type of given crate item.
|
||||
fn def_ty(&self, item: DefId) -> Ty;
|
||||
|
||||
/// Returns literal value of a const as a string.
|
||||
fn const_literal(&self, cnst: &Const) -> String;
|
||||
|
||||
/// `Span` of an item
|
||||
fn span_of_an_item(&self, def_id: DefId) -> Span;
|
||||
|
||||
/// Obtain the representation of a type.
|
||||
fn ty_kind(&self, ty: Ty) -> TyKind;
|
||||
|
||||
/// Get the body of an Instance.
|
||||
/// FIXME: Monomorphize the body.
|
||||
fn instance_body(&self, instance: InstanceDef) -> Option<Body>;
|
||||
|
||||
/// Get the instance type with generic substitutions applied and lifetimes erased.
|
||||
fn instance_ty(&self, instance: InstanceDef) -> Ty;
|
||||
|
||||
/// Get the instance.
|
||||
fn instance_def_id(&self, instance: InstanceDef) -> DefId;
|
||||
|
||||
/// Get the instance mangled name.
|
||||
fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol;
|
||||
|
||||
/// Convert a non-generic crate item into an instance.
|
||||
/// This function will panic if the item is generic.
|
||||
fn mono_instance(&self, item: CrateItem) -> Instance;
|
||||
|
||||
/// Item requires monomorphization.
|
||||
fn requires_monomorphization(&self, def_id: DefId) -> bool;
|
||||
|
||||
/// Resolve an instance from the given function definition and generic arguments.
|
||||
fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
|
||||
|
||||
/// Resolve an instance for drop_in_place for the given type.
|
||||
fn resolve_drop_in_place(&self, ty: Ty) -> Instance;
|
||||
|
||||
/// Resolve instance for a function pointer.
|
||||
fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
|
||||
|
||||
/// Resolve instance for a closure with the requested type.
|
||||
fn resolve_closure(
|
||||
&self,
|
||||
def: ClosureDef,
|
||||
args: &GenericArgs,
|
||||
kind: ClosureKind,
|
||||
) -> Option<Instance>;
|
||||
|
||||
/// Evaluate a static's initializer.
|
||||
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>;
|
||||
|
||||
/// Retrieve global allocation for the given allocation ID.
|
||||
fn global_alloc(&self, id: AllocId) -> GlobalAlloc;
|
||||
|
||||
/// Retrieve the id for the virtual table.
|
||||
fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
|
||||
fn krate(&self, def_id: DefId) -> Crate;
|
||||
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol;
|
||||
}
|
||||
|
||||
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
||||
// datastructures and stable MIR datastructures
|
||||
scoped_thread_local! (static TLV: Cell<*const ()>);
|
||||
|
||||
pub fn run<F, T>(context: &dyn Context, f: F) -> Result<T, Error>
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
if TLV.is_set() {
|
||||
Err(Error::from("StableMIR already running"))
|
||||
} else {
|
||||
let ptr: *const () = &context as *const &_ as _;
|
||||
TLV.set(&Cell::new(ptr), || Ok(f()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads the current context and calls a function with it.
|
||||
/// Do not nest these, as that will ICE.
|
||||
pub fn with<R>(f: impl FnOnce(&dyn Context) -> R) -> R {
|
||||
assert!(TLV.is_set());
|
||||
TLV.with(|tlv| {
|
||||
let ptr = tlv.get();
|
||||
assert!(!ptr.is_null());
|
||||
f(unsafe { *(ptr as *const &dyn Context) })
|
||||
})
|
||||
}
|
||||
|
||||
/// A type that provides internal information but that can still be used for debug purpose.
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Opaque(String);
|
||||
|
@ -171,7 +171,6 @@ pub fn pretty_rvalue(rval: &Rvalue) -> String {
|
||||
|
||||
pub fn pretty_ty(ty: TyKind) -> String {
|
||||
let mut pretty = String::new();
|
||||
pretty.push_str("");
|
||||
match ty {
|
||||
TyKind::RigidTy(rigid_ty) => match rigid_ty {
|
||||
RigidTy::Bool => "bool".to_string(),
|
||||
@ -215,7 +214,10 @@ pub fn pretty_ty(ty: TyKind) -> String {
|
||||
pretty.push_str(&pretty_ty(ty.kind()));
|
||||
pretty
|
||||
}
|
||||
RigidTy::Ref(_, ty, _) => pretty_ty(ty.kind()),
|
||||
RigidTy::Ref(_, ty, mutability) => match mutability {
|
||||
Mutability::Not => format!("&{}", pretty_ty(ty.kind())),
|
||||
Mutability::Mut => format!("&mut {}", pretty_ty(ty.kind())),
|
||||
},
|
||||
RigidTy::FnDef(_, _) => format!("{:#?}", rigid_ty),
|
||||
RigidTy::FnPtr(_) => format!("{:#?}", rigid_ty),
|
||||
RigidTy::Closure(_, _) => format!("{:#?}", rigid_ty),
|
||||
|
@ -30,7 +30,7 @@
|
||||
#
|
||||
# If `change-id` does not match the version that is currently running,
|
||||
# `x.py` will prompt you to update it and check the related PR for more details.
|
||||
change-id = 116881
|
||||
change-id = 117813
|
||||
|
||||
# =============================================================================
|
||||
# Tweaking how LLVM is compiled
|
||||
|
@ -183,7 +183,7 @@ Some general areas that you may be interested in modifying are:
|
||||
|
||||
If you make a major change on bootstrap configuration, please remember to:
|
||||
|
||||
+ Update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/lib.rs`.
|
||||
+ Update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs`.
|
||||
* Update `change-id = {pull-request-id}` in `config.example.toml`.
|
||||
|
||||
A 'major change' includes
|
||||
|
@ -120,7 +120,7 @@ fn check_version(config: &Config) -> Option<String> {
|
||||
}
|
||||
|
||||
if let Ok(last_warned_id) = fs::read_to_string(&warned_id_path) {
|
||||
if id.to_string() == last_warned_id {
|
||||
if latest_change_id.to_string() == last_warned_id {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
@ -144,7 +144,7 @@ fn check_version(config: &Config) -> Option<String> {
|
||||
));
|
||||
|
||||
if io::stdout().is_terminal() {
|
||||
t!(fs::write(warned_id_path, id.to_string()));
|
||||
t!(fs::write(warned_id_path, latest_change_id.to_string()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use crate::t;
|
||||
use crate::utils::change_tracker::CONFIG_CHANGE_HISTORY;
|
||||
use crate::Config;
|
||||
use crate::{t, CONFIG_CHANGE_HISTORY};
|
||||
use sha2::Digest;
|
||||
use std::env::consts::EXE_SUFFIX;
|
||||
use std::fmt::Write as _;
|
||||
|
@ -47,9 +47,10 @@ use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, syml
|
||||
mod core;
|
||||
mod utils;
|
||||
|
||||
pub use crate::core::builder::PathSet;
|
||||
pub use crate::core::config::flags::Subcommand;
|
||||
pub use crate::core::config::Config;
|
||||
pub use core::builder::PathSet;
|
||||
pub use core::config::flags::Subcommand;
|
||||
pub use core::config::Config;
|
||||
pub use utils::change_tracker::{find_recent_config_change_ids, CONFIG_CHANGE_HISTORY};
|
||||
|
||||
const LLVM_TOOLS: &[&str] = &[
|
||||
"llvm-cov", // used to generate coverage report
|
||||
@ -70,62 +71,6 @@ const LLVM_TOOLS: &[&str] = &[
|
||||
/// LLD file names for all flavors.
|
||||
const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ChangeInfo {
|
||||
/// Represents the ID of PR caused major change on bootstrap.
|
||||
pub change_id: usize,
|
||||
pub severity: ChangeSeverity,
|
||||
/// Provides a short summary of the change that will guide developers
|
||||
/// on "how to handle/behave" in response to the changes.
|
||||
pub summary: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ChangeSeverity {
|
||||
/// Used when build configurations continue working as before.
|
||||
Info,
|
||||
/// Used when the default value of an option changes, or support for an option is removed entirely,
|
||||
/// potentially requiring developers to update their build configurations.
|
||||
Warning,
|
||||
}
|
||||
|
||||
impl ToString for ChangeSeverity {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
ChangeSeverity::Info => "INFO".to_string(),
|
||||
ChangeSeverity::Warning => "WARNING".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Keeps track of major changes made to the bootstrap configuration.
|
||||
///
|
||||
/// If you make any major changes (such as adding new values or changing default values),
|
||||
/// please ensure adding `ChangeInfo` to the end(because the list must be sorted by the merge date)
|
||||
/// of this list.
|
||||
pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
|
||||
ChangeInfo {
|
||||
change_id: 115898,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "Implementation of this change-tracking system. Ignore this.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 116998,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "Removed android-ndk r15 support in favor of android-ndk r25b.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 117435,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "New option `rust.parallel-compiler` added to config.toml.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 116881,
|
||||
severity: ChangeSeverity::Warning,
|
||||
summary: "Default value of `download-ci-llvm` was changed for `codegen` profile.",
|
||||
},
|
||||
];
|
||||
|
||||
/// Extra --check-cfg to add when building
|
||||
/// (Mode restriction, config name, config values (if any))
|
||||
const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
|
||||
@ -1895,31 +1840,6 @@ fn envify(s: &str) -> String {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn find_recent_config_change_ids(current_id: usize) -> Vec<ChangeInfo> {
|
||||
if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) {
|
||||
// If the current change-id is greater than the most recent one, return
|
||||
// an empty list (it may be due to switching from a recent branch to an
|
||||
// older one); otherwise, return the full list (assuming the user provided
|
||||
// the incorrect change-id by accident).
|
||||
if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) {
|
||||
if ¤t_id > &config.change_id {
|
||||
return Vec::new();
|
||||
}
|
||||
}
|
||||
|
||||
return CONFIG_CHANGE_HISTORY.to_vec();
|
||||
}
|
||||
|
||||
let index =
|
||||
CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap();
|
||||
|
||||
CONFIG_CHANGE_HISTORY
|
||||
.iter()
|
||||
.skip(index + 1) // Skip the current_id and IDs before it
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Computes a hash representing the state of a repository/submodule and additional input.
|
||||
///
|
||||
/// It uses `git diff` for the actual changes, and `git status` for including the untracked
|
||||
|
89
src/bootstrap/src/utils/change_tracker.rs
Normal file
89
src/bootstrap/src/utils/change_tracker.rs
Normal file
@ -0,0 +1,89 @@
|
||||
//! This module facilitates the tracking system for major changes made to the bootstrap,
|
||||
//! with the goal of keeping developers synchronized with important modifications in
|
||||
//! the bootstrap.
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ChangeInfo {
|
||||
/// Represents the ID of PR caused major change on bootstrap.
|
||||
pub change_id: usize,
|
||||
pub severity: ChangeSeverity,
|
||||
/// Provides a short summary of the change that will guide developers
|
||||
/// on "how to handle/behave" in response to the changes.
|
||||
pub summary: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum ChangeSeverity {
|
||||
/// Used when build configurations continue working as before.
|
||||
Info,
|
||||
/// Used when the default value of an option changes, or support for an option is removed entirely,
|
||||
/// potentially requiring developers to update their build configurations.
|
||||
Warning,
|
||||
}
|
||||
|
||||
impl ToString for ChangeSeverity {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
ChangeSeverity::Info => "INFO".to_string(),
|
||||
ChangeSeverity::Warning => "WARNING".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn find_recent_config_change_ids(current_id: usize) -> Vec<ChangeInfo> {
|
||||
if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) {
|
||||
// If the current change-id is greater than the most recent one, return
|
||||
// an empty list (it may be due to switching from a recent branch to an
|
||||
// older one); otherwise, return the full list (assuming the user provided
|
||||
// the incorrect change-id by accident).
|
||||
if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) {
|
||||
if ¤t_id > &config.change_id {
|
||||
return Vec::new();
|
||||
}
|
||||
}
|
||||
|
||||
return CONFIG_CHANGE_HISTORY.to_vec();
|
||||
}
|
||||
|
||||
let index =
|
||||
CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap();
|
||||
|
||||
CONFIG_CHANGE_HISTORY
|
||||
.iter()
|
||||
.skip(index + 1) // Skip the current_id and IDs before it
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Keeps track of major changes made to the bootstrap configuration.
|
||||
///
|
||||
/// If you make any major changes (such as adding new values or changing default values),
|
||||
/// please ensure adding `ChangeInfo` to the end(because the list must be sorted by the merge date)
|
||||
/// of this list.
|
||||
pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
|
||||
ChangeInfo {
|
||||
change_id: 115898,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "Implementation of this change-tracking system. Ignore this.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 116998,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "Removed android-ndk r15 support in favor of android-ndk r25b.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 117435,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "New option `rust.parallel-compiler` added to config.toml.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 116881,
|
||||
severity: ChangeSeverity::Warning,
|
||||
summary: "Default value of `download-ci-llvm` was changed for `codegen` profile.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 117813,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "Use of the `if-available` value for `download-ci-llvm` is deprecated; prefer using the new `if-unchanged` value.",
|
||||
},
|
||||
];
|
@ -4,6 +4,7 @@
|
||||
|
||||
pub(crate) mod cache;
|
||||
pub(crate) mod cc_detect;
|
||||
pub(crate) mod change_tracker;
|
||||
pub(crate) mod channel;
|
||||
pub(crate) mod dylib;
|
||||
pub(crate) mod exec;
|
||||
|
@ -596,8 +596,10 @@ fn extra_info_tags<'a, 'tcx: 'a>(
|
||||
|
||||
// The "rustc_private" crates are permanently unstable so it makes no sense
|
||||
// to render "unstable" everywhere.
|
||||
if item.stability(tcx).as_ref().map(|s| s.is_unstable() && s.feature != sym::rustc_private)
|
||||
== Some(true)
|
||||
if item
|
||||
.stability(tcx)
|
||||
.as_ref()
|
||||
.is_some_and(|s| s.is_unstable() && s.feature != sym::rustc_private)
|
||||
{
|
||||
write!(f, "{}", tag_html("unstable", "", "Experimental"))?;
|
||||
}
|
||||
|
@ -1755,17 +1755,26 @@ function initSearch(rawSearchIndex) {
|
||||
if (mgens && mgens.has(fnType.id) && mgens.get(fnType.id) !== 0) {
|
||||
return false;
|
||||
}
|
||||
// Where clauses can represent cyclical data.
|
||||
// `null` prevents it from trying to unbox in an infinite loop
|
||||
const mgensTmp = new Map(mgens);
|
||||
mgensTmp.set(fnType.id, null);
|
||||
// This is only a potential unbox if the search query appears in the where clause
|
||||
// for example, searching `Read -> usize` should find
|
||||
// `fn read_all<R: Read>(R) -> Result<usize>`
|
||||
// generic `R` is considered "unboxed"
|
||||
return checkIfInList(whereClause[(-fnType.id) - 1], queryElem, whereClause);
|
||||
return checkIfInList(
|
||||
whereClause[(-fnType.id) - 1],
|
||||
queryElem,
|
||||
whereClause,
|
||||
mgensTmp
|
||||
);
|
||||
} else if (fnType.generics.length > 0 || fnType.bindings.size > 0) {
|
||||
const simplifiedGenerics = [
|
||||
...fnType.generics,
|
||||
...Array.from(fnType.bindings.values()).flat(),
|
||||
];
|
||||
return checkIfInList(simplifiedGenerics, queryElem, whereClause);
|
||||
return checkIfInList(simplifiedGenerics, queryElem, whereClause, mgens);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1777,12 +1786,13 @@ function initSearch(rawSearchIndex) {
|
||||
* @param {Array<FunctionType>} list
|
||||
* @param {QueryElement} elem - The element from the parsed query.
|
||||
* @param {[FunctionType]} whereClause - Trait bounds for generic items.
|
||||
* @param {Map<number,number>|null} mgens - Map functions generics to query generics.
|
||||
*
|
||||
* @return {boolean} - Returns true if found, false otherwise.
|
||||
*/
|
||||
function checkIfInList(list, elem, whereClause) {
|
||||
function checkIfInList(list, elem, whereClause, mgens) {
|
||||
for (const entry of list) {
|
||||
if (checkType(entry, elem, whereClause)) {
|
||||
if (checkType(entry, elem, whereClause, mgens)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1796,23 +1806,29 @@ function initSearch(rawSearchIndex) {
|
||||
* @param {Row} row
|
||||
* @param {QueryElement} elem - The element from the parsed query.
|
||||
* @param {[FunctionType]} whereClause - Trait bounds for generic items.
|
||||
* @param {Map<number,number>|null} mgens - Map functions generics to query generics.
|
||||
*
|
||||
* @return {boolean} - Returns true if the type matches, false otherwise.
|
||||
*/
|
||||
function checkType(row, elem, whereClause) {
|
||||
function checkType(row, elem, whereClause, mgens) {
|
||||
if (row.bindings.size === 0 && elem.bindings.size === 0) {
|
||||
if (elem.id < 0) {
|
||||
return row.id < 0 || checkIfInList(row.generics, elem, whereClause);
|
||||
return row.id < 0 || checkIfInList(row.generics, elem, whereClause, mgens);
|
||||
}
|
||||
if (row.id > 0 && elem.id > 0 && elem.pathWithoutLast.length === 0 &&
|
||||
typePassesFilter(elem.typeFilter, row.ty) && elem.generics.length === 0 &&
|
||||
// special case
|
||||
elem.id !== typeNameIdOfArrayOrSlice
|
||||
) {
|
||||
return row.id === elem.id || checkIfInList(row.generics, elem, whereClause);
|
||||
return row.id === elem.id || checkIfInList(
|
||||
row.generics,
|
||||
elem,
|
||||
whereClause,
|
||||
mgens
|
||||
);
|
||||
}
|
||||
}
|
||||
return unifyFunctionTypes([row], [elem], whereClause);
|
||||
return unifyFunctionTypes([row], [elem], whereClause, mgens);
|
||||
}
|
||||
|
||||
function checkPath(contains, ty, maxEditDistance) {
|
||||
|
@ -632,7 +632,7 @@ fn iter_header_extra(
|
||||
it(None, directive, 0);
|
||||
}
|
||||
|
||||
let comment = if testfile.extension().map(|e| e == "rs") == Some(true) { "//" } else { "#" };
|
||||
let comment = if testfile.extension().is_some_and(|e| e == "rs") { "//" } else { "#" };
|
||||
|
||||
let mut rdr = BufReader::new(rdr);
|
||||
let mut ln = String::new();
|
||||
|
@ -1 +1 @@
|
||||
34c5ab9aac327a8a18e18ea37a2468a320d82fb0
|
||||
3668a8af1b81447c4afa1f82f60d7b94b71a549f
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inff32 which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32`
|
||||
--> $DIR/float_to_int_32_inf1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, i32>(f32::INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inff32 which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff32 which cannot be represented in target type `i32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f32 which cannot be represented in target type `i32`
|
||||
--> $DIR/float_to_int_32_infneg1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, i32>(f32::NEG_INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff32 which cannot be represented in target type `i32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f32 which cannot be represented in target type `i32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32`
|
||||
--> $DIR/float_to_int_32_nan.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, u32>(f32::NAN);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32`
|
||||
--> $DIR/float_to_int_32_nanneg.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f32, u32>(-f32::NAN);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inff64 which cannot be represented in target type `u128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f64 which cannot be represented in target type `u128`
|
||||
--> $DIR/float_to_int_64_inf1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u128>(f64::INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inff64 which cannot be represented in target type `u128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf_f64 which cannot be represented in target type `u128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `u128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `u128`
|
||||
--> $DIR/float_to_int_64_infneg1.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u128>(f64::NEG_INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `u128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `u128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `i128`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `i128`
|
||||
--> $DIR/float_to_int_64_infneg2.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, i128>(f64::NEG_INFINITY);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `i128`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `i128`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf64 which cannot be represented in target type `u32`
|
||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f64 which cannot be represented in target type `u32`
|
||||
--> $DIR/float_to_int_64_nan.rs:LL:CC
|
||||
|
|
||||
LL | float_to_int_unchecked::<f64, u32>(f64::NAN);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf64 which cannot be represented in target type `u32`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f64 which cannot be represented in target type `u32`
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
9
tests/rustdoc-js/assoc-type-loop.js
Normal file
9
tests/rustdoc-js/assoc-type-loop.js
Normal file
@ -0,0 +1,9 @@
|
||||
// Crash reduction of
|
||||
// https://github.com/rust-lang/rust/issues/118242
|
||||
|
||||
const EXPECTED = [
|
||||
{
|
||||
'query': 't',
|
||||
'correction': null,
|
||||
},
|
||||
];
|
35
tests/rustdoc-js/assoc-type-loop.rs
Normal file
35
tests/rustdoc-js/assoc-type-loop.rs
Normal file
@ -0,0 +1,35 @@
|
||||
#![crate_name="foo"]
|
||||
|
||||
// reduced from sqlx 0.7.3
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
pub enum Error {}
|
||||
pub trait Acquire<'c> {
|
||||
type Database: Database;
|
||||
type Connection: Deref<Target = <Self::Database as Database>::Connection> + DerefMut + Send;
|
||||
}
|
||||
pub trait Database {
|
||||
type Connection: Connection<Database = Self>;
|
||||
}
|
||||
pub trait Connection {
|
||||
type Database: Database;
|
||||
type Options: ConnectionOptions<Connection = Self>;
|
||||
fn begin(
|
||||
&mut self
|
||||
) -> Pin<Box<dyn Future<Output = Result<Transaction<'_, Self::Database>, Error>> + Send + '_>>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
pub trait ConnectionOptions {
|
||||
type Connection: Connection;
|
||||
}
|
||||
pub struct Transaction<'c, DB: Database> {
|
||||
_db: &'c DB,
|
||||
}
|
||||
impl<'t, 'c, DB: Database> Acquire<'t> for &'t mut Transaction<'c, DB>
|
||||
where <DB as Database>::Connection: Send
|
||||
{
|
||||
type Database = DB;
|
||||
type Connection = &'t mut <DB as Database>::Connection;
|
||||
}
|
@ -533,6 +533,12 @@ message = "The Miri subtree was changed"
|
||||
cc = ["@rust-lang/miri"]
|
||||
|
||||
[mentions."src/tools/rust-analyzer"]
|
||||
message = """
|
||||
rust-analyzer is developed in its own repository. If possible, consider making \
|
||||
this change to [rust-lang/rust-analyzer] instead.
|
||||
|
||||
[rust-lang/rust-analyzer]: https://github.com/rust-lang/rust-analyzer
|
||||
"""
|
||||
cc = ["@rust-lang/rust-analyzer"]
|
||||
|
||||
[mentions."src/tools/rustfmt"]
|
||||
@ -583,11 +589,23 @@ message = "The list of allowed third-party dependencies may have been modified!
|
||||
cc = ["@davidtwco", "@wesleywiser"]
|
||||
|
||||
[mentions."src/bootstrap/src/core/config"]
|
||||
message = "This PR modifies `src/bootstrap/src/core/config`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`."
|
||||
message = """
|
||||
This PR modifies `src/bootstrap/src/core/config`.
|
||||
|
||||
If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs` and `change-id` in `config.example.toml`.
|
||||
"""
|
||||
[mentions."src/bootstrap/defaults"]
|
||||
message = "This PR modifies `src/bootstrap/defaults`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`."
|
||||
message = """
|
||||
This PR modifies `src/bootstrap/defaults`.
|
||||
|
||||
If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs` and `change-id` in `config.example.toml`.
|
||||
"""
|
||||
[mentions."config.example.toml"]
|
||||
message = "This PR changes `config.example.toml`. If appropriate, please also update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/lib.rs` and `change-id` in `config.example.toml`."
|
||||
message = """
|
||||
This PR modifies `config.example.toml`.
|
||||
|
||||
If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/utils/change_tracker.rs` and `change-id` in `config.example.toml`.
|
||||
"""
|
||||
|
||||
[mentions."src/bootstrap/defaults/config.compiler.toml"]
|
||||
message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appropriate, please also update `config.codegen.toml` so the defaults are in sync."
|
||||
|
Loading…
Reference in New Issue
Block a user