Auto merge of #3191 - RalfJung:rustup, r=RalfJung

Rustup
This commit is contained in:
bors 2023-11-25 13:27:26 +00:00
commit 547598b67e
58 changed files with 2680 additions and 2609 deletions

View File

@ -121,24 +121,24 @@ rustc_index::newtype_index! {
/// `BorrowIndex`, and maps each such index to a `BorrowData` /// `BorrowIndex`, and maps each such index to a `BorrowData`
/// describing the borrow. These indexes are used for representing the /// describing the borrow. These indexes are used for representing the
/// borrows in compact bitvectors. /// borrows in compact bitvectors.
pub struct Borrows<'a, 'tcx> { pub struct Borrows<'mir, 'tcx> {
tcx: TyCtxt<'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>>, borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
} }
struct OutOfScopePrecomputer<'a, 'tcx> { struct OutOfScopePrecomputer<'mir, 'tcx> {
visited: BitSet<mir::BasicBlock>, visited: BitSet<mir::BasicBlock>,
visit_stack: Vec<mir::BasicBlock>, visit_stack: Vec<mir::BasicBlock>,
body: &'a Body<'tcx>, body: &'mir Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>,
borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>, borrows_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
} }
impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> { impl<'mir, 'tcx> OutOfScopePrecomputer<'mir, 'tcx> {
fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self {
OutOfScopePrecomputer { OutOfScopePrecomputer {
visited: BitSet::new_empty(body.basic_blocks.len()), visited: BitSet::new_empty(body.basic_blocks.len()),
visit_stack: vec![], visit_stack: vec![],
@ -241,17 +241,17 @@ pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
prec.borrows_out_of_scope_at_location prec.borrows_out_of_scope_at_location
} }
struct PoloniusOutOfScopePrecomputer<'a, 'tcx> { struct PoloniusOutOfScopePrecomputer<'mir, 'tcx> {
visited: BitSet<mir::BasicBlock>, visited: BitSet<mir::BasicBlock>,
visit_stack: Vec<mir::BasicBlock>, visit_stack: Vec<mir::BasicBlock>,
body: &'a Body<'tcx>, body: &'mir Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>,
loans_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>, loans_out_of_scope_at_location: FxIndexMap<Location, Vec<BorrowIndex>>,
} }
impl<'a, 'tcx> PoloniusOutOfScopePrecomputer<'a, 'tcx> { impl<'mir, 'tcx> PoloniusOutOfScopePrecomputer<'mir, 'tcx> {
fn new(body: &'a Body<'tcx>, regioncx: &'a RegionInferenceContext<'tcx>) -> Self { fn new(body: &'mir Body<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>) -> Self {
Self { Self {
visited: BitSet::new_empty(body.basic_blocks.len()), visited: BitSet::new_empty(body.basic_blocks.len()),
visit_stack: vec![], 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( pub fn new(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>, body: &'mir Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>, regioncx: &'mir RegionInferenceContext<'tcx>,
borrow_set: &'a BorrowSet<'tcx>, borrow_set: &'mir BorrowSet<'tcx>,
) -> Self { ) -> Self {
let mut borrows_out_of_scope_at_location = let mut borrows_out_of_scope_at_location =
calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set); calculate_borrows_out_of_scope_at_location(body, regioncx, borrow_set);

View File

@ -288,7 +288,7 @@ fn do_mir_borrowck<'tcx>(
.into_engine(tcx, body) .into_engine(tcx, body)
.pass_name("borrowck") .pass_name("borrowck")
.iterate_to_fixpoint(); .iterate_to_fixpoint();
let flow_ever_inits = EverInitializedPlaces::new(tcx, body, &mdpe) let flow_ever_inits = EverInitializedPlaces::new(body, &mdpe)
.into_engine(tcx, body) .into_engine(tcx, body)
.pass_name("borrowck") .pass_name("borrowck")
.iterate_to_fixpoint(); .iterate_to_fixpoint();

View File

@ -27,7 +27,7 @@ fn main() {
args.push(codegen_backend_arg); args.push(codegen_backend_arg);
} }
if !passed_args.iter().any(|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"));
args.push(OsString::from(sysroot.to_str().unwrap())); args.push(OsString::from(sysroot.to_str().unwrap()));

View File

@ -27,7 +27,7 @@ fn main() {
args.push(codegen_backend_arg); args.push(codegen_backend_arg);
} }
if !passed_args.iter().any(|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"));
args.push(OsString::from(sysroot.to_str().unwrap())); args.push(OsString::from(sysroot.to_str().unwrap()));

View File

@ -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. /// 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>) { 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(); iter.next();
} }
} }

View File

@ -1674,10 +1674,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let impl_ty = ocx.normalize(&cause, param_env, impl_ty); let impl_ty = ocx.normalize(&cause, param_env, impl_ty);
// Check that the self types can be related. // Check that the self types can be related.
// FIXME(inherent_associated_types): Should we use `eq` here? Method probing uses if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() {
// `sup` for this situtation, too. What for? To constrain inference variables?
if ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err()
{
return false; return false;
} }

View File

@ -2293,12 +2293,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let clone_trait = let clone_trait =
self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span)); self.tcx.require_lang_item(LangItem::Clone, Some(segment.ident.span));
if args.is_empty() if args.is_empty()
&& self.typeck_results.borrow().type_dependent_def_id(expr.hir_id).map( && self
|did| { .typeck_results
.borrow()
.type_dependent_def_id(expr.hir_id)
.is_some_and(|did| {
let ai = self.tcx.associated_item(did); let ai = self.tcx.associated_item(did);
ai.trait_container(self.tcx) == Some(clone_trait) ai.trait_container(self.tcx) == Some(clone_trait)
}, })
) == Some(true)
&& segment.ident.name == sym::clone && segment.ident.name == sym::clone
{ {
// If this expression had a clone call when suggesting borrowing // If this expression had a clone call when suggesting borrowing

View File

@ -161,7 +161,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
&& self && self
.tcx() .tcx()
.opt_associated_item(scope_def_id.to_def_id()) .opt_associated_item(scope_def_id.to_def_id())
.map(|i| i.fn_has_self_parameter) .is_some_and(|i| i.fn_has_self_parameter)
== Some(true)
} }
} }

View File

@ -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
}
}
}
}
}

View File

@ -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 infcx = cx.tcx.infer_ctxt().build();
let suggest_display = is_str let suggest_display = is_str
|| cx || cx.tcx.get_diagnostic_item(sym::Display).is_some_and(|t| {
.tcx infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
.get_diagnostic_item(sym::Display) });
.map(|t| infcx.type_implements_trait(t, [ty], cx.param_env).may_apply())
== Some(true);
let suggest_debug = !suggest_display let suggest_debug = !suggest_display
&& cx && cx.tcx.get_diagnostic_item(sym::Debug).is_some_and(|t| {
.tcx infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()
.get_diagnostic_item(sym::Debug) });
.map(|t| infcx.type_implements_trait(t, [ty], cx.param_env).may_apply())
== Some(true);
let suggest_panic_any = !is_str && panic == sym::std_panic_macro; let suggest_panic_any = !is_str && panic == sym::std_panic_macro;

View File

@ -8,6 +8,7 @@ use crate::ty::{
}; };
use crate::ty::{GenericArg, GenericArgKind}; use crate::ty::{GenericArg, GenericArgKind};
use rustc_apfloat::ieee::{Double, Single}; use rustc_apfloat::ieee::{Double, Single};
use rustc_apfloat::Float;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::sso::SsoHashSet;
use rustc_hir as hir; 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"), ty::Bool if int == ScalarInt::TRUE => p!("true"),
// Float // Float
ty::Float(ty::FloatTy::F32) => { 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) => { 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 // Int
ty::Uint(_) | ty::Int(_) => { ty::Uint(_) | ty::Int(_) => {

View File

@ -1,10 +1,8 @@
use crate::elaborate_drops::DropFlagState; use crate::elaborate_drops::DropFlagState;
use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind}; use rustc_middle::mir::{self, Body, Location, Terminator, TerminatorKind};
use rustc_middle::ty::TyCtxt;
use rustc_target::abi::VariantIdx; use rustc_target::abi::VariantIdx;
use super::indexes::MovePathIndex; use super::move_paths::{InitKind, LookupResult, MoveData, MovePathIndex};
use super::move_paths::{InitKind, LookupResult, MoveData};
use super::MoveDataParamEnv; use super::MoveDataParamEnv;
pub fn move_path_children_matching<'tcx, F>( pub fn move_path_children_matching<'tcx, F>(
@ -30,8 +28,6 @@ where
} }
pub fn on_lookup_result_bits<'tcx, F>( pub fn on_lookup_result_bits<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
lookup_result: LookupResult, lookup_result: LookupResult,
each_child: F, each_child: F,
@ -42,13 +38,11 @@ pub fn on_lookup_result_bits<'tcx, F>(
LookupResult::Parent(..) => { LookupResult::Parent(..) => {
// access to untracked value - do not touch children // 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>( pub fn on_all_children_bits<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
move_path_index: MovePathIndex, move_path_index: MovePathIndex,
mut each_child: F, mut each_child: F,
@ -56,8 +50,6 @@ pub fn on_all_children_bits<'tcx, F>(
F: FnMut(MovePathIndex), F: FnMut(MovePathIndex),
{ {
fn on_all_children_bits<'tcx, F>( fn on_all_children_bits<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
move_path_index: MovePathIndex, move_path_index: MovePathIndex,
each_child: &mut F, 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; let mut next_child_index = move_data.move_paths[move_path_index].first_child;
while let Some(child_index) = next_child_index { 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; 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>( pub fn drop_flag_effects_for_function_entry<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
ctxt: &MoveDataParamEnv<'tcx>, ctxt: &MoveDataParamEnv<'tcx>,
mut callback: F, mut callback: F,
@ -87,14 +78,13 @@ pub fn drop_flag_effects_for_function_entry<'tcx, F>(
for arg in body.args_iter() { for arg in body.args_iter() {
let place = mir::Place::from(arg); let place = mir::Place::from(arg);
let lookup_result = move_data.rev_lookup.find(place.as_ref()); 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) callback(mpi, DropFlagState::Present)
}); });
} }
} }
pub fn drop_flag_effects_for_location<'tcx, F>( pub fn drop_flag_effects_for_location<'tcx, F>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, body: &Body<'tcx>,
ctxt: &MoveDataParamEnv<'tcx>, ctxt: &MoveDataParamEnv<'tcx>,
loc: Location, loc: Location,
@ -110,7 +100,7 @@ pub fn drop_flag_effects_for_location<'tcx, F>(
let path = mi.move_path_index(move_data); let path = mi.move_path_index(move_data);
debug!("moving out of path {:?}", move_data.move_paths[path]); 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. // 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() body.stmt_at(loc).right()
{ {
if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) { if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(place.as_ref()) {
on_all_children_bits(tcx, body, move_data, mpi, |mpi| { on_all_children_bits(move_data, mpi, |mpi| callback(mpi, DropFlagState::Absent))
callback(mpi, DropFlagState::Absent)
})
} }
} }
debug!("drop_flag_effects: assignment for location({:?})", loc); 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>( fn for_location_inits<'tcx, F>(move_data: &MoveData<'tcx>, loc: Location, mut callback: F)
tcx: TyCtxt<'tcx>, where
body: &Body<'tcx>,
move_data: &MoveData<'tcx>,
loc: Location,
mut callback: F,
) where
F: FnMut(MovePathIndex), F: FnMut(MovePathIndex),
{ {
for ii in &move_data.init_loc_map[loc] { for ii in &move_data.init_loc_map[loc] {
@ -144,7 +127,7 @@ pub fn for_location_inits<'tcx, F>(
InitKind::Deep => { InitKind::Deep => {
let path = init.path; 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 => { InitKind::Shallow => {
let mpi = init.path; 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, /// NOTE: If there are no move paths corresponding to an inactive variant,
/// `handle_inactive_variant` will not be called for that variant. /// `handle_inactive_variant` will not be called for that variant.
pub(crate) fn on_all_inactive_variants<'tcx>( pub(crate) fn on_all_inactive_variants<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mir::Body<'tcx>,
move_data: &MoveData<'tcx>, move_data: &MoveData<'tcx>,
enum_place: mir::Place<'tcx>, enum_place: mir::Place<'tcx>,
active_variant: VariantIdx, active_variant: VariantIdx,
@ -185,9 +166,7 @@ pub(crate) fn on_all_inactive_variants<'tcx>(
}; };
if variant_idx != active_variant { if variant_idx != active_variant {
on_all_children_bits(tcx, body, move_data, variant_mpi, |mpi| { on_all_children_bits(move_data, variant_mpi, |mpi| handle_inactive_variant(mpi));
handle_inactive_variant(mpi)
});
} }
} }
} }

View File

@ -147,7 +147,7 @@ where
} }
/// Returns the underlying `Results`. /// 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() self.results.borrow()
} }
@ -166,11 +166,6 @@ where
&mut self.results.borrow_mut().analysis &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. /// 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. /// For forward dataflow analyses, this is the dataflow state prior to the first statement.

View File

@ -287,12 +287,12 @@ impl Direction for Backward {
} }
} }
struct BackwardSwitchIntEdgeEffectsApplier<'a, 'tcx, D, F> { struct BackwardSwitchIntEdgeEffectsApplier<'mir, 'tcx, D, F> {
body: &'a mir::Body<'tcx>, body: &'mir mir::Body<'tcx>,
pred: BasicBlock, pred: BasicBlock,
exit_state: &'a mut D, exit_state: &'mir mut D,
bb: BasicBlock, bb: BasicBlock,
propagate: &'a mut F, propagate: &'mir mut F,
effects_applied: bool, effects_applied: bool,
} }
@ -523,9 +523,9 @@ impl Direction for Forward {
} }
} }
struct ForwardSwitchIntEdgeEffectsApplier<'a, D, F> { struct ForwardSwitchIntEdgeEffectsApplier<'mir, D, F> {
exit_state: &'a mut D, exit_state: &'mir mut D,
targets: &'a SwitchTargets, targets: &'mir SwitchTargets,
propagate: F, propagate: F,
effects_applied: bool, effects_applied: bool,

View File

@ -128,12 +128,12 @@ where
} }
/// A solver for dataflow problems. /// A solver for dataflow problems.
pub struct Engine<'a, 'tcx, A> pub struct Engine<'mir, 'tcx, A>
where where
A: Analysis<'tcx>, A: Analysis<'tcx>,
{ {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>, body: &'mir mir::Body<'tcx>,
entry_sets: IndexVec<BasicBlock, A::Domain>, entry_sets: IndexVec<BasicBlock, A::Domain>,
pass_name: Option<&'static str>, pass_name: Option<&'static str>,
analysis: A, analysis: A,
@ -147,14 +147,14 @@ where
apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>, 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 where
A: GenKillAnalysis<'tcx, Idx = T, Domain = D>, A: GenKillAnalysis<'tcx, Idx = T, Domain = D>,
D: Clone + JoinSemiLattice + GenKill<T> + BitSetExt<T>, D: Clone + JoinSemiLattice + GenKill<T> + BitSetExt<T>,
T: Idx, T: Idx,
{ {
/// Creates a new `Engine` to solve a gen-kill dataflow problem. /// 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 // 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). // 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 where
A: Analysis<'tcx, Domain = D>, A: Analysis<'tcx, Domain = D>,
D: Clone + JoinSemiLattice, D: Clone + JoinSemiLattice,
@ -196,13 +196,13 @@ where
/// ///
/// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for /// Gen-kill problems should use `new_gen_kill`, which will coalesce transfer functions for
/// better performance. /// 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) Self::new(tcx, body, analysis, None)
} }
fn new( fn new(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>, body: &'mir mir::Body<'tcx>,
analysis: A, analysis: A,
apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>, apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
) -> Self { ) -> Self {
@ -239,7 +239,6 @@ where
tcx, tcx,
apply_statement_trans_for_block, apply_statement_trans_for_block,
pass_name, pass_name,
..
} = self; } = self;
let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len()); let mut dirty_queue: WorkQueue<BasicBlock> = WorkQueue::with_none(body.basic_blocks.len());

View File

@ -15,7 +15,7 @@ use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext};
use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor}; use super::{Analysis, CallReturnPlaces, Direction, Results, ResultsRefCursor, ResultsVisitor};
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum OutputStyle { pub(crate) enum OutputStyle {
AfterOnly, AfterOnly,
BeforeAndAfter, BeforeAndAfter,
} }
@ -29,7 +29,7 @@ impl OutputStyle {
} }
} }
pub struct Formatter<'res, 'mir, 'tcx, A> pub(crate) struct Formatter<'res, 'mir, 'tcx, A>
where where
A: Analysis<'tcx>, A: Analysis<'tcx>,
{ {
@ -43,7 +43,7 @@ impl<'res, 'mir, 'tcx, A> Formatter<'res, 'mir, 'tcx, A>
where where
A: Analysis<'tcx>, A: Analysis<'tcx>,
{ {
pub fn new( pub(crate) fn new(
body: &'mir Body<'tcx>, body: &'mir Body<'tcx>,
results: &'res mut Results<'tcx, A>, results: &'res mut Results<'tcx, A>,
style: OutputStyle, style: OutputStyle,
@ -55,7 +55,7 @@ where
/// A pair of a basic block and an index into that basic blocks `successors`. /// A pair of a basic block and an index into that basic blocks `successors`.
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct CfgEdge { pub(crate) struct CfgEdge {
source: BasicBlock, source: BasicBlock,
index: usize, index: usize,
} }

View File

@ -45,7 +45,7 @@ pub mod graphviz;
pub mod lattice; pub mod lattice;
mod visitor; 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::direction::{Backward, Direction, Forward};
pub use self::engine::{Engine, EntrySets, Results, ResultsCloned}; pub use self::engine::{Engine, EntrySets, Results, ResultsCloned};
pub use self::lattice::{JoinSemiLattice, MaybeReachable}; pub use self::lattice::{JoinSemiLattice, MaybeReachable};

View File

@ -72,7 +72,7 @@ impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
) -> bool { ) -> bool {
if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) { if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
let mut maybe_live = false; 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 |= state.contains(child);
}); });
!maybe_live !maybe_live
@ -203,14 +203,13 @@ impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
/// this data and `MaybeInitializedPlaces` yields the set of places /// this data and `MaybeInitializedPlaces` yields the set of places
/// that would require a dynamic drop-flag at that statement. /// that would require a dynamic drop-flag at that statement.
pub struct DefinitelyInitializedPlaces<'a, 'tcx> { pub struct DefinitelyInitializedPlaces<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>, body: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>,
} }
impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> { impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
DefinitelyInitializedPlaces { tcx, body, mdpe } DefinitelyInitializedPlaces { body, mdpe }
} }
} }
@ -250,15 +249,13 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
/// } /// }
/// ``` /// ```
pub struct EverInitializedPlaces<'a, 'tcx> { pub struct EverInitializedPlaces<'a, 'tcx> {
#[allow(dead_code)]
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>, body: &'a Body<'tcx>,
mdpe: &'a MoveDataParamEnv<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>,
} }
impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> { impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self { pub fn new(body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
EverInitializedPlaces { tcx, body, mdpe } 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) { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
*state = *state =
MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len())); 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); assert!(s == DropFlagState::Present);
state.gen(path); state.gen(path);
}); });
@ -339,7 +336,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
statement: &mir::Statement<'tcx>, statement: &mir::Statement<'tcx>,
location: Location, 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) Self::update_bits(trans, path, s)
}); });
@ -351,7 +348,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
| mir::Rvalue::AddressOf(_, place) = rvalue | mir::Rvalue::AddressOf(_, place) = rvalue
&& let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) && 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); trans.gen(child);
}) })
} }
@ -371,7 +368,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
{ {
edges = TerminatorEdges::Single(target); 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) Self::update_bits(state, path, s)
}); });
edges edges
@ -387,8 +384,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
// when a call returns successfully, that means we need to set // when a call returns successfully, that means we need to set
// the bits for that dest_place to 1 (initialized). // the bits for that dest_place to 1 (initialized).
on_lookup_result_bits( on_lookup_result_bits(
self.tcx,
self.body,
self.move_data(), self.move_data(),
self.move_data().rev_lookup.find(place.as_ref()), self.move_data().rev_lookup.find(place.as_ref()),
|mpi| { |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 // Kill all move paths that correspond to variants we know to be inactive along this
// particular outgoing edge of a `SwitchInt`. // particular outgoing edge of a `SwitchInt`.
drop_flag_effects::on_all_inactive_variants( drop_flag_effects::on_all_inactive_variants(
self.tcx,
self.body,
self.move_data(), self.move_data(),
enum_place, enum_place,
variant, variant,
@ -458,7 +451,7 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
// set all bits to 1 (uninit) before gathering counter-evidence // set all bits to 1 (uninit) before gathering counter-evidence
state.insert_all(); 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); assert!(s == DropFlagState::Present);
state.remove(path); state.remove(path);
}); });
@ -478,7 +471,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
_statement: &mir::Statement<'tcx>, _statement: &mir::Statement<'tcx>,
location: Location, 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) Self::update_bits(trans, path, s)
}); });
@ -492,7 +485,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
terminator: &'mir mir::Terminator<'tcx>, terminator: &'mir mir::Terminator<'tcx>,
location: Location, location: Location,
) -> TerminatorEdges<'mir, 'tcx> { ) -> 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) Self::update_bits(trans, path, s)
}); });
if self.skip_unreachable_unwind.contains(location.block) { 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 // when a call returns successfully, that means we need to set
// the bits for that dest_place to 0 (initialized). // the bits for that dest_place to 0 (initialized).
on_lookup_result_bits( on_lookup_result_bits(
self.tcx,
self.body,
self.move_data(), self.move_data(),
self.move_data().rev_lookup.find(place.as_ref()), self.move_data().rev_lookup.find(place.as_ref()),
|mpi| { |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 // Mark all move paths that correspond to variants other than this one as maybe
// uninitialized (in reality, they are *definitely* uninitialized). // uninitialized (in reality, they are *definitely* uninitialized).
drop_flag_effects::on_all_inactive_variants( drop_flag_effects::on_all_inactive_variants(
self.tcx,
self.body,
self.move_data(), self.move_data(),
enum_place, enum_place,
variant, 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) { fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
state.0.clear(); 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); assert!(s == DropFlagState::Present);
state.0.insert(path); state.0.insert(path);
}); });
@ -609,7 +598,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
_statement: &mir::Statement<'tcx>, _statement: &mir::Statement<'tcx>,
location: Location, 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) Self::update_bits(trans, path, s)
}) })
} }
@ -620,7 +609,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
terminator: &'mir mir::Terminator<'tcx>, terminator: &'mir mir::Terminator<'tcx>,
location: Location, location: Location,
) -> TerminatorEdges<'mir, 'tcx> { ) -> 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) Self::update_bits(trans, path, s)
}); });
terminator.edges() terminator.edges()
@ -636,8 +625,6 @@ impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
// when a call returns successfully, that means we need to set // when a call returns successfully, that means we need to set
// the bits for that dest_place to 1 (initialized). // the bits for that dest_place to 1 (initialized).
on_lookup_result_bits( on_lookup_result_bits(
self.tcx,
self.body,
self.move_data(), self.move_data(),
self.move_data().rev_lookup.find(place.as_ref()), self.move_data().rev_lookup.find(place.as_ref()),
|mpi| { |mpi| {

View File

@ -23,7 +23,6 @@ use crate::{Analysis, AnalysisDomain, Backward, GenKill, GenKillAnalysis};
/// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals /// [`MaybeBorrowedLocals`]: super::MaybeBorrowedLocals
/// [flow-test]: https://github.com/rust-lang/rust/blob/a08c47310c7d49cbdc5d7afb38408ba519967ecd/src/test/ui/mir-dataflow/liveness-ptr.rs /// [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 /// [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
#[derive(Clone, Copy)]
pub struct MaybeLiveLocals; pub struct MaybeLiveLocals;
impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals { impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals {

View File

@ -4,7 +4,6 @@
#![feature(let_chains)] #![feature(let_chains)]
#![feature(min_specialization)] #![feature(min_specialization)]
#![feature(stmt_expr_attributes)] #![feature(stmt_expr_attributes)]
#![feature(trusted_step)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
@ -14,24 +13,19 @@ extern crate tracing;
#[macro_use] #[macro_use]
extern crate rustc_middle; extern crate rustc_middle;
use rustc_ast::MetaItem;
use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
use rustc_fluent_macro::fluent_messages; use rustc_fluent_macro::fluent_messages;
use rustc_hir::def_id::DefId; use rustc_middle::ty;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::{sym, Symbol};
pub use self::drop_flag_effects::{ pub use self::drop_flag_effects::{
drop_flag_effects_for_function_entry, drop_flag_effects_for_location, drop_flag_effects_for_function_entry, drop_flag_effects_for_location,
move_path_children_matching, on_all_children_bits, on_lookup_result_bits, move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
}; };
pub use self::framework::{ pub use self::framework::{
fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward, fmt, lattice, visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis,
CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice, JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor,
MaybeReachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
}; };
use self::framework::{Backward, CloneAnalysis, ResultsClonedCursor, SwitchIntEdgeEffects};
use self::move_paths::MoveData; use self::move_paths::MoveData;
pub mod debuginfo; pub mod debuginfo;
@ -48,24 +42,7 @@ pub mod value_analysis;
fluent_messages! { "../messages.ftl" } fluent_messages! { "../messages.ftl" }
pub(crate) mod indexes {
pub(crate) use super::move_paths::MovePathIndex;
}
pub struct MoveDataParamEnv<'tcx> { pub struct MoveDataParamEnv<'tcx> {
pub move_data: MoveData<'tcx>, pub move_data: MoveData<'tcx>,
pub param_env: ty::ParamEnv<'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
}

View File

@ -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::{ use crate::errors::{
PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary, PeekArgumentNotALocal, PeekArgumentUntracked, PeekBitNotSet, PeekMustBeNotTemporary,
PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation, PeekMustBePlaceOrRefPlace, StopAfterDataFlowEndedCompilation,
@ -18,13 +10,33 @@ use crate::move_paths::{HasMoveData, MoveData};
use crate::move_paths::{LookupResult, MovePathIndex}; use crate::move_paths::{LookupResult, MovePathIndex};
use crate::MoveDataParamEnv; use crate::MoveDataParamEnv;
use crate::{Analysis, JoinSemiLattice, ResultsCursor}; 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; 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. // FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first.
impl<'tcx> MirPass<'tcx> for SanityCheck { impl<'tcx> MirPass<'tcx> for SanityCheck {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
use crate::has_rustc_mir_with;
let def_id = body.source.def_id(); let def_id = body.source.def_id();
if !tcx.has_attr(def_id, sym::rustc_mir) { if !tcx.has_attr(def_id, sym::rustc_mir) {
debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); 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() { 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) .into_engine(tcx, body)
.iterate_to_fixpoint(); .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 /// (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 /// expression form above, then that emits an error as well, but those
/// errors are not intended to be used for unit tests.) /// errors are not intended to be used for unit tests.)
pub fn sanity_check_via_rustc_peek<'tcx, A>( fn sanity_check_via_rustc_peek<'tcx, A>(tcx: TyCtxt<'tcx>, mut cursor: ResultsCursor<'_, 'tcx, A>)
tcx: TyCtxt<'tcx>, where
mut cursor: ResultsCursor<'_, 'tcx, A>,
) where
A: RustcPeekAt<'tcx>, A: RustcPeekAt<'tcx>,
{ {
let def_id = cursor.body().source.def_id(); 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 }; let loc = Location { block: bb, statement_index };
cursor.seek_before_primary_effect(loc); 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); analysis.peek_at(tcx, *place, state, call);
} }
@ -173,7 +184,7 @@ impl PeekCallKind {
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct PeekCall { struct PeekCall {
arg: Local, arg: Local,
kind: PeekCallKind, kind: PeekCallKind,
span: Span, span: Span,
@ -221,7 +232,7 @@ impl PeekCall {
} }
} }
pub trait RustcPeekAt<'tcx>: Analysis<'tcx> { trait RustcPeekAt<'tcx>: Analysis<'tcx> {
fn peek_at( fn peek_at(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,

View File

@ -3,13 +3,13 @@ use rustc_middle::mir::*;
/// Used for reverting changes made by `DerefSeparator` /// Used for reverting changes made by `DerefSeparator`
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct UnDerefer<'tcx> { pub(crate) struct UnDerefer<'tcx> {
deref_chains: FxHashMap<Local, Vec<PlaceRef<'tcx>>>, deref_chains: FxHashMap<Local, Vec<PlaceRef<'tcx>>>,
} }
impl<'tcx> UnDerefer<'tcx> { impl<'tcx> UnDerefer<'tcx> {
#[inline] #[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(); let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default();
chain.push(reffed); chain.push(reffed);
self.deref_chains.insert(local, chain); self.deref_chains.insert(local, chain);
@ -17,7 +17,7 @@ impl<'tcx> UnDerefer<'tcx> {
/// Returns the chain of places behind `DerefTemp` locals /// Returns the chain of places behind `DerefTemp` locals
#[inline] #[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() self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default()
} }
@ -25,7 +25,7 @@ impl<'tcx> UnDerefer<'tcx> {
/// ///
/// See [`PlaceRef::iter_projections`] /// See [`PlaceRef::iter_projections`]
#[inline] #[inline]
pub fn iter_projections( pub(crate) fn iter_projections(
&self, &self,
place: PlaceRef<'tcx>, place: PlaceRef<'tcx>,
) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + '_ { ) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + '_ {

View File

@ -332,8 +332,6 @@ pub struct ValueAnalysisWrapper<T>(pub T);
impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper<T> { impl<'tcx, T: ValueAnalysis<'tcx>> AnalysisDomain<'tcx> for ValueAnalysisWrapper<T> {
type Domain = State<T::Value>; type Domain = State<T::Value>;
type Direction = crate::Forward;
const NAME: &'static str = T::NAME; const NAME: &'static str = T::NAME;
fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain { 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(_)) 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. /// 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) { pub fn flood_with(&mut self, place: PlaceRef<'_>, map: &Map, value: V) {
self.flood_with_tail_elem(place, None, map, value) 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. /// 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) 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. /// This does nothing if the place is not tracked.
/// ///
/// The target place must have been flooded before calling this method. /// 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 { match result {
ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map), ValueOrPlace::Value(value) => self.insert_value_idx(target, value, map),
ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map), ValueOrPlace::Place(source) => self.insert_place_idx(target, source, map),
@ -910,18 +892,13 @@ impl Map {
self.inner_values[root] = start..end; 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. /// Applies a single projection element, yielding the corresponding child.
pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> { pub fn apply(&self, place: PlaceIndex, elem: TrackElem) -> Option<PlaceIndex> {
self.projections.get(&(place, elem)).copied() self.projections.get(&(place, elem)).copied()
} }
/// Locates the given place, if it exists in the tree. /// Locates the given place, if it exists in the tree.
pub fn find_extra( fn find_extra(
&self, &self,
place: PlaceRef<'_>, place: PlaceRef<'_>,
extra: impl IntoIterator<Item = TrackElem>, extra: impl IntoIterator<Item = TrackElem>,
@ -954,7 +931,7 @@ impl Map {
} }
/// Iterate over all direct children. /// 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) Children::new(self, parent)
} }

View File

@ -668,36 +668,34 @@ fn locals_live_across_suspend_points<'tcx>(
always_live_locals: &BitSet<Local>, always_live_locals: &BitSet<Local>,
movable: bool, movable: bool,
) -> LivenessInfo { ) -> LivenessInfo {
let body_ref: &Body<'_> = body;
// Calculate when MIR locals have live storage. This gives us an upper bound of their // Calculate when MIR locals have live storage. This gives us an upper bound of their
// lifetimes. // lifetimes.
let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals)) 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() .iterate_to_fixpoint()
.into_results_cursor(body_ref); .into_results_cursor(body);
// Calculate the MIR locals which have been previously // Calculate the MIR locals which have been previously
// borrowed (even if they are still active). // borrowed (even if they are still active).
let borrowed_locals_results = 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 // Calculate the MIR locals that we actually need to keep storage around
// for. // for.
let mut requires_storage_results = let mut requires_storage_results =
MaybeRequiresStorage::new(borrowed_locals_results.cloned_results_cursor(body)) MaybeRequiresStorage::new(borrowed_locals_results.cloned_results_cursor(body))
.into_engine(tcx, body_ref) .into_engine(tcx, body)
.iterate_to_fixpoint(); .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. // Calculate the liveness of MIR locals ignoring borrows.
let mut liveness = MaybeLiveLocals let mut liveness = MaybeLiveLocals
.into_engine(tcx, body_ref) .into_engine(tcx, body)
.pass_name("coroutine") .pass_name("coroutine")
.iterate_to_fixpoint() .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 storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks);
let mut live_locals_at_suspension_points = Vec::new(); let mut live_locals_at_suspension_points = Vec::new();
@ -763,7 +761,7 @@ fn locals_live_across_suspend_points<'tcx>(
.collect(); .collect();
let storage_conflicts = compute_storage_conflicts( let storage_conflicts = compute_storage_conflicts(
body_ref, body,
&saved_locals, &saved_locals,
always_live_locals.clone(), always_live_locals.clone(),
requires_storage_results, requires_storage_results,

View File

@ -172,19 +172,13 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, '_, 'tcx> {
let mut some_live = false; let mut some_live = false;
let mut some_dead = false; let mut some_dead = false;
let mut children_count = 0; let mut children_count = 0;
on_all_children_bits( on_all_children_bits(self.ctxt.move_data(), path, |child| {
self.tcx(), let (live, dead) = self.ctxt.init_data.maybe_live_dead(child);
self.body(), debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead));
self.ctxt.move_data(), some_live |= live;
path, some_dead |= dead;
|child| { children_count += 1;
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) ((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); self.ctxt.set_drop_flag(loc, path, DropFlagState::Absent);
} }
DropFlagMode::Deep => { DropFlagMode::Deep => {
on_all_children_bits( on_all_children_bits(self.ctxt.move_data(), path, |child| {
self.tcx(), self.ctxt.set_drop_flag(loc, child, DropFlagState::Absent)
self.body(), });
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) { fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
let tcx = self.tcx;
let patch = &mut self.patch; let patch = &mut self.patch;
debug!("create_drop_flag({:?})", self.body.span); 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>> { fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
@ -304,7 +293,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
match path { match path {
LookupResult::Exact(path) => { LookupResult::Exact(path) => {
self.init_data.seek_before(self.body.terminator_loc(bb)); 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); let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child);
debug!( debug!(
"collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}", "collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}",
@ -444,7 +433,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
let loc = Location { block: tgt, statement_index: 0 }; let loc = Location { block: tgt, statement_index: 0 };
let path = self.move_data().rev_lookup.find(destination.as_ref()); 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) 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) { fn drop_flags_for_args(&mut self) {
let loc = Location::START; let loc = Location::START;
rustc_mir_dataflow::drop_flag_effects_for_function_entry( rustc_mir_dataflow::drop_flag_effects_for_function_entry(self.body, self.env, |path, ds| {
self.tcx, self.set_drop_flag(loc, path, ds);
self.body, })
self.env,
|path, ds| {
self.set_drop_flag(loc, path, ds);
},
)
} }
fn drop_flags_for_locs(&mut self) { 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 }; let loc = Location { block: bb, statement_index: i };
rustc_mir_dataflow::drop_flag_effects_for_location( rustc_mir_dataflow::drop_flag_effects_for_location(
self.tcx,
self.body, self.body,
self.env, self.env,
loc, loc,
@ -515,7 +498,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
let loc = Location { block: bb, statement_index: data.statements.len() }; let loc = Location { block: bb, statement_index: data.statements.len() };
let path = self.move_data().rev_lookup.find(destination.as_ref()); 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) self.set_drop_flag(loc, child, DropFlagState::Present)
}); });
} }

View File

@ -3,7 +3,7 @@
//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
//! until stable MIR is complete. //! 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;
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_middle::mir::interpret::AllocId; use rustc_middle::mir::interpret::AllocId;
@ -181,7 +181,7 @@ where
instances: IndexMap::default(), instances: IndexMap::default(),
constants: IndexMap::default(), constants: IndexMap::default(),
})); }));
stable_mir::run(&tables, || init(&tables, f)) stable_mir::compiler_interface::run(&tables, || init(&tables, f))
} }
#[macro_export] #[macro_export]

View 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>>);

View 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)),
}
}
}

View 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)
}
}

View 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

View File

@ -18,6 +18,7 @@ use rustc_index::IndexVec;
use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::CanonicalVarValues;
use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints};
use rustc_infer::infer::resolve::EagerResolver;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_middle::infer::canonical::Canonical; use rustc_middle::infer::canonical::Canonical;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
@ -25,10 +26,7 @@ use rustc_middle::traits::solve::{
ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput, ExternalConstraintsData, MaybeCause, PredefinedOpaquesData, QueryInput,
}; };
use rustc_middle::traits::ObligationCause; use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{ use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt,
};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
use std::iter; use std::iter;
use std::ops::Deref; use std::ops::Deref;
@ -58,7 +56,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
) -> (Vec<ty::GenericArg<'tcx>>, CanonicalInput<'tcx, T>) { ) -> (Vec<ty::GenericArg<'tcx>>, CanonicalInput<'tcx, T>) {
let opaque_types = self.infcx.clone_opaque_types_for_query_response(); let opaque_types = self.infcx.clone_opaque_types_for_query_response();
let (goal, opaque_types) = 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 mut orig_values = Default::default();
let canonical_goal = Canonicalizer::canonicalize( let canonical_goal = Canonicalizer::canonicalize(
@ -115,7 +113,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
let external_constraints = self.compute_external_query_constraints()?; let external_constraints = self.compute_external_query_constraints()?;
let (var_values, mut external_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 // Remove any trivial region constraints once we've resolved regions
external_constraints external_constraints
.region_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> { impl<'tcx> inspect::ProofTreeBuilder<'tcx> {
pub fn make_canonical_state<T: TypeFoldable<TyCtxt<'tcx>>>( pub fn make_canonical_state<T: TypeFoldable<TyCtxt<'tcx>>>(
ecx: &EvalCtxt<'_, 'tcx>, ecx: &EvalCtxt<'_, 'tcx>,
data: T, data: T,
) -> inspect::CanonicalState<'tcx, T> { ) -> inspect::CanonicalState<'tcx, T> {
let state = inspect::State { var_values: ecx.var_values, data }; 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( Canonicalizer::canonicalize(
ecx.infcx, ecx.infcx,
CanonicalizeMode::Response { max_input_universe: ecx.max_input_universe }, CanonicalizeMode::Response { max_input_universe: ecx.max_input_universe },

View File

@ -1001,7 +1001,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
&mut self, &mut self,
t: ty::Binder<'tcx, T>, t: ty::Binder<'tcx, 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; return t;
} }
self.current_index.shift_in(1); 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> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
let ty = self.infcx.shallow_resolve(ty);
match *ty.kind() { match *ty.kind() {
ty::Placeholder(p) => { ty::Placeholder(p) => {
let replace_var = self.mapped_types.get(&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) 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, _ => ty,
} }
} }
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { 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() { if let ty::ConstKind::Placeholder(p) = ct.kind() {
let replace_var = self.mapped_consts.get(&p); let replace_var = self.mapped_consts.get(&p);
match replace_var { 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()) 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 { } else {
ct.super_fold_with(self) ct.super_fold_with(self)

View 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) })
})
}

View File

@ -17,38 +17,31 @@
//! The goal is to eventually be published on //! The goal is to eventually be published on
//! [crates.io](https://crates.io). //! [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] #[macro_use]
extern crate scoped_tls; 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] #[macro_use]
pub mod crate_def; pub mod crate_def;
pub mod compiler_interface;
#[macro_use] #[macro_use]
pub mod error; pub mod error;
pub mod mir; pub mod mir;
pub mod ty; pub mod ty;
pub mod visitor; 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. /// Use String for now but we should replace it.
pub type Symbol = String; pub type Symbol = String;
@ -179,149 +172,6 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
with(|cx| cx.trait_impl(trait_impl)) 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. /// A type that provides internal information but that can still be used for debug purpose.
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
pub struct Opaque(String); pub struct Opaque(String);

View File

@ -171,7 +171,6 @@ pub fn pretty_rvalue(rval: &Rvalue) -> String {
pub fn pretty_ty(ty: TyKind) -> String { pub fn pretty_ty(ty: TyKind) -> String {
let mut pretty = String::new(); let mut pretty = String::new();
pretty.push_str("");
match ty { match ty {
TyKind::RigidTy(rigid_ty) => match rigid_ty { TyKind::RigidTy(rigid_ty) => match rigid_ty {
RigidTy::Bool => "bool".to_string(), RigidTy::Bool => "bool".to_string(),
@ -215,7 +214,10 @@ pub fn pretty_ty(ty: TyKind) -> String {
pretty.push_str(&pretty_ty(ty.kind())); pretty.push_str(&pretty_ty(ty.kind()));
pretty 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::FnDef(_, _) => format!("{:#?}", rigid_ty),
RigidTy::FnPtr(_) => format!("{:#?}", rigid_ty), RigidTy::FnPtr(_) => format!("{:#?}", rigid_ty),
RigidTy::Closure(_, _) => format!("{:#?}", rigid_ty), RigidTy::Closure(_, _) => format!("{:#?}", rigid_ty),

View File

@ -30,7 +30,7 @@
# #
# If `change-id` does not match the version that is currently running, # 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. # `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 # Tweaking how LLVM is compiled

View File

@ -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: 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`. * Update `change-id = {pull-request-id}` in `config.example.toml`.
A 'major change' includes A 'major change' includes

View File

@ -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 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; return None;
} }
} }
@ -144,7 +144,7 @@ fn check_version(config: &Config) -> Option<String> {
)); ));
if io::stdout().is_terminal() { 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 { } else {

View File

@ -1,6 +1,7 @@
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::t;
use crate::utils::change_tracker::CONFIG_CHANGE_HISTORY;
use crate::Config; use crate::Config;
use crate::{t, CONFIG_CHANGE_HISTORY};
use sha2::Digest; use sha2::Digest;
use std::env::consts::EXE_SUFFIX; use std::env::consts::EXE_SUFFIX;
use std::fmt::Write as _; use std::fmt::Write as _;

View File

@ -47,9 +47,10 @@ use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, syml
mod core; mod core;
mod utils; mod utils;
pub use crate::core::builder::PathSet; pub use core::builder::PathSet;
pub use crate::core::config::flags::Subcommand; pub use core::config::flags::Subcommand;
pub use crate::core::config::Config; pub use core::config::Config;
pub use utils::change_tracker::{find_recent_config_change_ids, CONFIG_CHANGE_HISTORY};
const LLVM_TOOLS: &[&str] = &[ const LLVM_TOOLS: &[&str] = &[
"llvm-cov", // used to generate coverage report "llvm-cov", // used to generate coverage report
@ -70,62 +71,6 @@ const LLVM_TOOLS: &[&str] = &[
/// LLD file names for all flavors. /// LLD file names for all flavors.
const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"]; 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 /// Extra --check-cfg to add when building
/// (Mode restriction, config name, config values (if any)) /// (Mode restriction, config name, config values (if any))
const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
@ -1895,31 +1840,6 @@ fn envify(s: &str) -> String {
.collect() .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 &current_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. /// 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 /// It uses `git diff` for the actual changes, and `git status` for including the untracked

View 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 &current_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.",
},
];

View File

@ -4,6 +4,7 @@
pub(crate) mod cache; pub(crate) mod cache;
pub(crate) mod cc_detect; pub(crate) mod cc_detect;
pub(crate) mod change_tracker;
pub(crate) mod channel; pub(crate) mod channel;
pub(crate) mod dylib; pub(crate) mod dylib;
pub(crate) mod exec; pub(crate) mod exec;

View File

@ -596,8 +596,10 @@ fn extra_info_tags<'a, 'tcx: 'a>(
// The "rustc_private" crates are permanently unstable so it makes no sense // The "rustc_private" crates are permanently unstable so it makes no sense
// to render "unstable" everywhere. // to render "unstable" everywhere.
if item.stability(tcx).as_ref().map(|s| s.is_unstable() && s.feature != sym::rustc_private) if item
== Some(true) .stability(tcx)
.as_ref()
.is_some_and(|s| s.is_unstable() && s.feature != sym::rustc_private)
{ {
write!(f, "{}", tag_html("unstable", "", "Experimental"))?; write!(f, "{}", tag_html("unstable", "", "Experimental"))?;
} }

View File

@ -1755,17 +1755,26 @@ function initSearch(rawSearchIndex) {
if (mgens && mgens.has(fnType.id) && mgens.get(fnType.id) !== 0) { if (mgens && mgens.has(fnType.id) && mgens.get(fnType.id) !== 0) {
return false; 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 // This is only a potential unbox if the search query appears in the where clause
// for example, searching `Read -> usize` should find // for example, searching `Read -> usize` should find
// `fn read_all<R: Read>(R) -> Result<usize>` // `fn read_all<R: Read>(R) -> Result<usize>`
// generic `R` is considered "unboxed" // 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) { } else if (fnType.generics.length > 0 || fnType.bindings.size > 0) {
const simplifiedGenerics = [ const simplifiedGenerics = [
...fnType.generics, ...fnType.generics,
...Array.from(fnType.bindings.values()).flat(), ...Array.from(fnType.bindings.values()).flat(),
]; ];
return checkIfInList(simplifiedGenerics, queryElem, whereClause); return checkIfInList(simplifiedGenerics, queryElem, whereClause, mgens);
} }
return false; return false;
} }
@ -1777,12 +1786,13 @@ function initSearch(rawSearchIndex) {
* @param {Array<FunctionType>} list * @param {Array<FunctionType>} list
* @param {QueryElement} elem - The element from the parsed query. * @param {QueryElement} elem - The element from the parsed query.
* @param {[FunctionType]} whereClause - Trait bounds for generic items. * @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. * @return {boolean} - Returns true if found, false otherwise.
*/ */
function checkIfInList(list, elem, whereClause) { function checkIfInList(list, elem, whereClause, mgens) {
for (const entry of list) { for (const entry of list) {
if (checkType(entry, elem, whereClause)) { if (checkType(entry, elem, whereClause, mgens)) {
return true; return true;
} }
} }
@ -1796,23 +1806,29 @@ function initSearch(rawSearchIndex) {
* @param {Row} row * @param {Row} row
* @param {QueryElement} elem - The element from the parsed query. * @param {QueryElement} elem - The element from the parsed query.
* @param {[FunctionType]} whereClause - Trait bounds for generic items. * @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. * @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 (row.bindings.size === 0 && elem.bindings.size === 0) {
if (elem.id < 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 && if (row.id > 0 && elem.id > 0 && elem.pathWithoutLast.length === 0 &&
typePassesFilter(elem.typeFilter, row.ty) && elem.generics.length === 0 && typePassesFilter(elem.typeFilter, row.ty) && elem.generics.length === 0 &&
// special case // special case
elem.id !== typeNameIdOfArrayOrSlice 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) { function checkPath(contains, ty, maxEditDistance) {

View File

@ -632,7 +632,7 @@ fn iter_header_extra(
it(None, directive, 0); 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 rdr = BufReader::new(rdr);
let mut ln = String::new(); let mut ln = String::new();

View File

@ -1 +1 @@
34c5ab9aac327a8a18e18ea37a2468a320d82fb0 3668a8af1b81447c4afa1f82f60d7b94b71a549f

View File

@ -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 --> $DIR/float_to_int_32_inf1.rs:LL:CC
| |
LL | float_to_int_unchecked::<f32, i32>(f32::INFINITY); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -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 --> $DIR/float_to_int_32_infneg1.rs:LL:CC
| |
LL | float_to_int_unchecked::<f32, i32>(f32::NEG_INFINITY); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -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 --> $DIR/float_to_int_32_nan.rs:LL:CC
| |
LL | float_to_int_unchecked::<f32, u32>(f32::NAN); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -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 --> $DIR/float_to_int_32_nanneg.rs:LL:CC
| |
LL | float_to_int_unchecked::<f32, u32>(-f32::NAN); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -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 --> $DIR/float_to_int_64_inf1.rs:LL:CC
| |
LL | float_to_int_unchecked::<f64, u128>(f64::INFINITY); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -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 --> $DIR/float_to_int_64_infneg1.rs:LL:CC
| |
LL | float_to_int_unchecked::<f64, u128>(f64::NEG_INFINITY); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -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 --> $DIR/float_to_int_64_infneg2.rs:LL:CC
| |
LL | float_to_int_unchecked::<f64, i128>(f64::NEG_INFINITY); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -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 --> $DIR/float_to_int_64_nan.rs:LL:CC
| |
LL | float_to_int_unchecked::<f64, u32>(f64::NAN); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View File

@ -0,0 +1,9 @@
// Crash reduction of
// https://github.com/rust-lang/rust/issues/118242
const EXPECTED = [
{
'query': 't',
'correction': null,
},
];

View 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;
}

View File

@ -533,6 +533,12 @@ message = "The Miri subtree was changed"
cc = ["@rust-lang/miri"] cc = ["@rust-lang/miri"]
[mentions."src/tools/rust-analyzer"] [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"] cc = ["@rust-lang/rust-analyzer"]
[mentions."src/tools/rustfmt"] [mentions."src/tools/rustfmt"]
@ -583,11 +589,23 @@ message = "The list of allowed third-party dependencies may have been modified!
cc = ["@davidtwco", "@wesleywiser"] cc = ["@davidtwco", "@wesleywiser"]
[mentions."src/bootstrap/src/core/config"] [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"] [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"] [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"] [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." message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appropriate, please also update `config.codegen.toml` so the defaults are in sync."