mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
commit
547598b67e
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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()));
|
||||||
|
@ -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()));
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -260,3 +260,85 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for FullTypeResolver<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// EAGER RESOLUTION
|
||||||
|
|
||||||
|
/// Resolves ty, region, and const vars to their inferred values or their root vars.
|
||||||
|
pub struct EagerResolver<'a, 'tcx> {
|
||||||
|
infcx: &'a InferCtxt<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> EagerResolver<'a, 'tcx> {
|
||||||
|
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
|
||||||
|
EagerResolver { infcx }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> {
|
||||||
|
fn interner(&self) -> TyCtxt<'tcx> {
|
||||||
|
self.infcx.tcx
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||||
|
match *t.kind() {
|
||||||
|
ty::Infer(ty::TyVar(vid)) => match self.infcx.probe_ty_var(vid) {
|
||||||
|
Ok(t) => t.fold_with(self),
|
||||||
|
Err(_) => Ty::new_var(self.infcx.tcx, self.infcx.root_var(vid)),
|
||||||
|
},
|
||||||
|
ty::Infer(ty::IntVar(vid)) => self.infcx.opportunistic_resolve_int_var(vid),
|
||||||
|
ty::Infer(ty::FloatVar(vid)) => self.infcx.opportunistic_resolve_float_var(vid),
|
||||||
|
_ => {
|
||||||
|
if t.has_infer() {
|
||||||
|
t.super_fold_with(self)
|
||||||
|
} else {
|
||||||
|
t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||||
|
match *r {
|
||||||
|
ty::ReVar(vid) => self
|
||||||
|
.infcx
|
||||||
|
.inner
|
||||||
|
.borrow_mut()
|
||||||
|
.unwrap_region_constraints()
|
||||||
|
.opportunistic_resolve_var(self.infcx.tcx, vid),
|
||||||
|
_ => r,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
|
match c.kind() {
|
||||||
|
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
||||||
|
// FIXME: we need to fold the ty too, I think.
|
||||||
|
match self.infcx.probe_const_var(vid) {
|
||||||
|
Ok(c) => c.fold_with(self),
|
||||||
|
Err(_) => {
|
||||||
|
ty::Const::new_var(self.infcx.tcx, self.infcx.root_const_var(vid), c.ty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
|
||||||
|
debug_assert_eq!(c.ty(), self.infcx.tcx.types.bool);
|
||||||
|
match self.infcx.probe_effect_var(vid) {
|
||||||
|
Some(c) => c.as_const(self.infcx.tcx),
|
||||||
|
None => ty::Const::new_infer(
|
||||||
|
self.infcx.tcx,
|
||||||
|
ty::InferConst::EffectVar(self.infcx.root_effect_var(vid)),
|
||||||
|
self.infcx.tcx.types.bool,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
if c.has_infer() {
|
||||||
|
c.super_fold_with(self)
|
||||||
|
} else {
|
||||||
|
c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -154,17 +154,13 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
|
|||||||
|
|
||||||
let infcx = cx.tcx.infer_ctxt().build();
|
let 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;
|
||||||
|
|
||||||
|
@ -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(_) => {
|
||||||
|
@ -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)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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());
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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};
|
||||||
|
@ -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| {
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
|
@ -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>,
|
||||||
|
@ -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>)> + '_ {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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]
|
||||||
|
376
compiler/rustc_smir/src/rustc_smir/context.rs
Normal file
376
compiler/rustc_smir/src/rustc_smir/context.rs
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
//! Implementation of `[stable_mir::compiler_interface::Context]` trait.
|
||||||
|
//!
|
||||||
|
//! This trait is currently the main interface between the Rust compiler,
|
||||||
|
//! and the `stable_mir` crate.
|
||||||
|
|
||||||
|
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
|
||||||
|
use rustc_middle::ty::{GenericPredicates, Instance, ParamEnv, ScalarInt, ValTree};
|
||||||
|
use rustc_span::def_id::LOCAL_CRATE;
|
||||||
|
use stable_mir::compiler_interface::Context;
|
||||||
|
use stable_mir::mir::alloc::GlobalAlloc;
|
||||||
|
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
||||||
|
use stable_mir::mir::Body;
|
||||||
|
use stable_mir::ty::{
|
||||||
|
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FnDef, GenericArgs, LineInfo,
|
||||||
|
RigidTy, Span, TyKind,
|
||||||
|
};
|
||||||
|
use stable_mir::{self, Crate, CrateItem, Error, Filename, ItemKind, Symbol};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use crate::rustc_internal::{internal, RustcInternal};
|
||||||
|
use crate::rustc_smir::builder::BodyBuilder;
|
||||||
|
use crate::rustc_smir::{new_item_kind, smir_crate, Stable, Tables};
|
||||||
|
|
||||||
|
impl<'tcx> Context for TablesWrapper<'tcx> {
|
||||||
|
fn entry_fn(&self) -> Option<stable_mir::CrateItem> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let tcx = tables.tcx;
|
||||||
|
Some(tables.crate_item(tcx.entry_fn(())?.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_local_items(&self) -> stable_mir::CrateItems {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = tables[item];
|
||||||
|
tables.tcx.instance_mir(rustc_middle::ty::InstanceDef::Item(def_id)).stable(&mut tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_trait_decls(&self) -> stable_mir::TraitDecls {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
tables
|
||||||
|
.tcx
|
||||||
|
.traits(LOCAL_CRATE)
|
||||||
|
.iter()
|
||||||
|
.map(|trait_def_id| tables.trait_def(*trait_def_id))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = tables[trait_def.0];
|
||||||
|
let trait_def = tables.tcx.trait_def(def_id);
|
||||||
|
trait_def.stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
tables
|
||||||
|
.tcx
|
||||||
|
.trait_impls_in_crate(LOCAL_CRATE)
|
||||||
|
.iter()
|
||||||
|
.map(|impl_def_id| tables.impl_def(*impl_def_id))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = tables[impl_def.0];
|
||||||
|
let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap();
|
||||||
|
impl_trait.stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = tables[def_id];
|
||||||
|
let generics = tables.tcx.generics_of(def_id);
|
||||||
|
generics.stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = tables[def_id];
|
||||||
|
let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id);
|
||||||
|
stable_mir::ty::GenericPredicates {
|
||||||
|
parent: parent.map(|did| tables.trait_def(did)),
|
||||||
|
predicates: predicates
|
||||||
|
.iter()
|
||||||
|
.map(|(clause, span)| {
|
||||||
|
(
|
||||||
|
clause.as_predicate().kind().skip_binder().stable(&mut *tables),
|
||||||
|
span.stable(&mut *tables),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn explicit_predicates_of(
|
||||||
|
&self,
|
||||||
|
def_id: stable_mir::DefId,
|
||||||
|
) -> stable_mir::ty::GenericPredicates {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = tables[def_id];
|
||||||
|
let GenericPredicates { parent, predicates } = tables.tcx.explicit_predicates_of(def_id);
|
||||||
|
stable_mir::ty::GenericPredicates {
|
||||||
|
parent: parent.map(|did| tables.trait_def(did)),
|
||||||
|
predicates: predicates
|
||||||
|
.iter()
|
||||||
|
.map(|(clause, span)| {
|
||||||
|
(
|
||||||
|
clause.as_predicate().kind().skip_binder().stable(&mut *tables),
|
||||||
|
span.stable(&mut *tables),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn local_crate(&self) -> stable_mir::Crate {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
smir_crate(tables.tcx, LOCAL_CRATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn external_crates(&self) -> Vec<stable_mir::Crate> {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE]
|
||||||
|
.iter()
|
||||||
|
.chain(tables.tcx.crates(()).iter())
|
||||||
|
.map(|crate_num| {
|
||||||
|
let crate_name = tables.tcx.crate_name(*crate_num).to_string();
|
||||||
|
(name == crate_name).then(|| smir_crate(tables.tcx, *crate_num))
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|c| c)
|
||||||
|
.collect();
|
||||||
|
crates
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
if trimmed {
|
||||||
|
with_forced_trimmed_paths!(tables.tcx.def_path_str(tables[def_id]))
|
||||||
|
} else {
|
||||||
|
with_no_trimmed_paths!(tables.tcx.def_path_str(tables[def_id]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn span_to_string(&self, span: stable_mir::ty::Span) -> String {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_filename(&self, span: &Span) -> Filename {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
tables
|
||||||
|
.tcx
|
||||||
|
.sess
|
||||||
|
.source_map()
|
||||||
|
.span_to_filename(tables[*span])
|
||||||
|
.display(rustc_span::FileNameDisplayPreference::Local)
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_lines(&self, span: &Span) -> LineInfo {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]);
|
||||||
|
LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn item_kind(&self, item: CrateItem) -> ItemKind {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
new_item_kind(tables.tcx.def_kind(tables[item.0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_foreign_item(&self, item: CrateItem) -> bool {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
tables.tcx.is_foreign_item(tables[item.0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn adt_kind(&self, def: AdtDef) -> AdtKind {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
def.internal(&mut *tables).adt_kind().stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn adt_is_box(&self, def: AdtDef) -> bool {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
def.internal(&mut *tables).is_box()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let mir_const = cnst.internal(&mut *tables);
|
||||||
|
mir_const
|
||||||
|
.try_eval_target_usize(tables.tcx, ParamEnv::empty())
|
||||||
|
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usize_to_const(&self, val: u64) -> Result<Const, Error> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let ty = tables.tcx.types.usize;
|
||||||
|
let size = tables.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap().size;
|
||||||
|
|
||||||
|
let scalar = ScalarInt::try_from_uint(val, size).ok_or_else(|| {
|
||||||
|
Error::new(format!("Value overflow: cannot convert `{val}` to usize."))
|
||||||
|
})?;
|
||||||
|
Ok(rustc_middle::ty::Const::new_value(tables.tcx, ValTree::from_scalar_int(scalar), ty)
|
||||||
|
.stable(&mut *tables))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let internal_kind = kind.internal(&mut *tables);
|
||||||
|
tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
tables.tcx.type_of(item.internal(&mut *tables)).instantiate_identity().stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn const_literal(&self, cnst: &stable_mir::ty::Const) -> String {
|
||||||
|
internal(cnst).to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
tables.tcx.def_span(tables[def_id]).stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
tables.types[ty].kind().stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_body(&self, def: InstanceDef) -> Option<Body> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let instance = tables.instances[def];
|
||||||
|
tables
|
||||||
|
.has_body(instance)
|
||||||
|
.then(|| BodyBuilder::new(tables.tcx, instance).build(&mut *tables))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let instance = tables.instances[def];
|
||||||
|
instance.ty(tables.tcx, ParamEnv::empty()).stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = tables.instances[def].def_id();
|
||||||
|
tables.create_def_id(def_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol {
|
||||||
|
let tables = self.0.borrow_mut();
|
||||||
|
let instance = tables.instances[instance];
|
||||||
|
tables.tcx.symbol_name(instance).name.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = tables[item.0];
|
||||||
|
Instance::mono(tables.tcx, def_id).stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
let def_id = tables[def_id];
|
||||||
|
let generics = tables.tcx.generics_of(def_id);
|
||||||
|
let result = generics.requires_monomorphization(tables.tcx);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_instance(
|
||||||
|
&self,
|
||||||
|
def: stable_mir::ty::FnDef,
|
||||||
|
args: &stable_mir::ty::GenericArgs,
|
||||||
|
) -> Option<stable_mir::mir::mono::Instance> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = def.0.internal(&mut *tables);
|
||||||
|
let args_ref = args.internal(&mut *tables);
|
||||||
|
match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
|
||||||
|
Ok(Some(instance)) => Some(instance.stable(&mut *tables)),
|
||||||
|
Ok(None) | Err(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let internal_ty = ty.internal(&mut *tables);
|
||||||
|
let instance = Instance::resolve_drop_in_place(tables.tcx, internal_ty);
|
||||||
|
instance.stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_for_fn_ptr(
|
||||||
|
&self,
|
||||||
|
def: FnDef,
|
||||||
|
args: &GenericArgs,
|
||||||
|
) -> Option<stable_mir::mir::mono::Instance> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = def.0.internal(&mut *tables);
|
||||||
|
let args_ref = args.internal(&mut *tables);
|
||||||
|
Instance::resolve_for_fn_ptr(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref)
|
||||||
|
.stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_closure(
|
||||||
|
&self,
|
||||||
|
def: ClosureDef,
|
||||||
|
args: &GenericArgs,
|
||||||
|
kind: ClosureKind,
|
||||||
|
) -> Option<stable_mir::mir::mono::Instance> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = def.0.internal(&mut *tables);
|
||||||
|
let args_ref = args.internal(&mut *tables);
|
||||||
|
let closure_kind = kind.internal(&mut *tables);
|
||||||
|
Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind).stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let def_id = def.0.internal(&mut *tables);
|
||||||
|
tables.tcx.eval_static_initializer(def_id).stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let alloc_id = alloc.internal(&mut *tables);
|
||||||
|
tables.tcx.global_alloc(alloc_id).stable(&mut *tables)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vtable_allocation(
|
||||||
|
&self,
|
||||||
|
global_alloc: &GlobalAlloc,
|
||||||
|
) -> Option<stable_mir::mir::alloc::AllocId> {
|
||||||
|
let mut tables = self.0.borrow_mut();
|
||||||
|
let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { return None };
|
||||||
|
let alloc_id = tables
|
||||||
|
.tcx
|
||||||
|
.vtable_allocation((ty.internal(&mut *tables), trait_ref.internal(&mut *tables)));
|
||||||
|
Some(alloc_id.stable(&mut *tables))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn krate(&self, def_id: stable_mir::DefId) -> Crate {
|
||||||
|
let tables = self.0.borrow();
|
||||||
|
smir_crate(tables.tcx, tables[def_id].krate)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the instance name for diagnostic messages.
|
||||||
|
///
|
||||||
|
/// This will return the specialized name, e.g., `Vec<char>::new`.
|
||||||
|
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol {
|
||||||
|
let tables = self.0.borrow_mut();
|
||||||
|
let instance = tables.instances[def];
|
||||||
|
if trimmed {
|
||||||
|
with_forced_trimmed_paths!(
|
||||||
|
tables.tcx.def_path_str_with_args(instance.def_id(), instance.args)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
with_no_trimmed_paths!(
|
||||||
|
tables.tcx.def_path_str_with_args(instance.def_id(), instance.args)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TablesWrapper<'tcx>(pub RefCell<Tables<'tcx>>);
|
745
compiler/rustc_smir/src/rustc_smir/convert/mir.rs
Normal file
745
compiler/rustc_smir/src/rustc_smir/convert/mir.rs
Normal file
@ -0,0 +1,745 @@
|
|||||||
|
//! Conversion of internal Rust compiler `mir` items to stable ones.
|
||||||
|
|
||||||
|
use rustc_middle::mir;
|
||||||
|
use rustc_middle::mir::interpret::alloc_range;
|
||||||
|
use rustc_middle::mir::mono::MonoItem;
|
||||||
|
use stable_mir::mir::alloc::GlobalAlloc;
|
||||||
|
use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment};
|
||||||
|
use stable_mir::ty::{Allocation, Const, ConstantKind};
|
||||||
|
use stable_mir::{opaque, Error};
|
||||||
|
|
||||||
|
use crate::rustc_smir::{alloc, Stable, Tables};
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
|
||||||
|
type T = stable_mir::mir::Body;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
stable_mir::mir::Body::new(
|
||||||
|
self.basic_blocks
|
||||||
|
.iter()
|
||||||
|
.map(|block| stable_mir::mir::BasicBlock {
|
||||||
|
terminator: block.terminator().stable(tables),
|
||||||
|
statements: block
|
||||||
|
.statements
|
||||||
|
.iter()
|
||||||
|
.map(|statement| statement.stable(tables))
|
||||||
|
.collect(),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
self.local_decls
|
||||||
|
.iter()
|
||||||
|
.map(|decl| stable_mir::mir::LocalDecl {
|
||||||
|
ty: decl.ty.stable(tables),
|
||||||
|
span: decl.source_info.span.stable(tables),
|
||||||
|
mutability: decl.mutability.stable(tables),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
self.arg_count,
|
||||||
|
self.var_debug_info.iter().map(|info| info.stable(tables)).collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
|
||||||
|
type T = stable_mir::mir::VarDebugInfo;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
stable_mir::mir::VarDebugInfo {
|
||||||
|
name: self.name.to_string(),
|
||||||
|
source_info: self.source_info.stable(tables),
|
||||||
|
composite: self.composite.as_ref().map(|composite| composite.stable(tables)),
|
||||||
|
value: self.value.stable(tables),
|
||||||
|
argument_index: self.argument_index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
|
||||||
|
type T = stable_mir::mir::Statement;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::SourceInfo {
|
||||||
|
type T = stable_mir::mir::SourceInfo;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
stable_mir::mir::SourceInfo { span: self.span.stable(tables), scope: self.scope.into() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
|
||||||
|
type T = stable_mir::mir::VarDebugInfoFragment;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
VarDebugInfoFragment {
|
||||||
|
ty: self.ty.stable(tables),
|
||||||
|
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
|
||||||
|
type T = stable_mir::mir::VarDebugInfoContents;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
mir::VarDebugInfoContents::Place(place) => {
|
||||||
|
stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables))
|
||||||
|
}
|
||||||
|
mir::VarDebugInfoContents::Const(const_operand) => {
|
||||||
|
let op = ConstOperand {
|
||||||
|
span: const_operand.span.stable(tables),
|
||||||
|
user_ty: const_operand.user_ty.map(|index| index.as_usize()),
|
||||||
|
const_: const_operand.const_.stable(tables),
|
||||||
|
};
|
||||||
|
stable_mir::mir::VarDebugInfoContents::Const(op)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
|
||||||
|
type T = stable_mir::mir::StatementKind;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign(
|
||||||
|
assign.0.stable(tables),
|
||||||
|
assign.1.stable(tables),
|
||||||
|
),
|
||||||
|
mir::StatementKind::FakeRead(fake_read_place) => {
|
||||||
|
stable_mir::mir::StatementKind::FakeRead(
|
||||||
|
fake_read_place.0.stable(tables),
|
||||||
|
fake_read_place.1.stable(tables),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mir::StatementKind::SetDiscriminant { place, variant_index } => {
|
||||||
|
stable_mir::mir::StatementKind::SetDiscriminant {
|
||||||
|
place: place.as_ref().stable(tables),
|
||||||
|
variant_index: variant_index.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::StatementKind::Deinit(place) => {
|
||||||
|
stable_mir::mir::StatementKind::Deinit(place.stable(tables))
|
||||||
|
}
|
||||||
|
|
||||||
|
mir::StatementKind::StorageLive(place) => {
|
||||||
|
stable_mir::mir::StatementKind::StorageLive(place.stable(tables))
|
||||||
|
}
|
||||||
|
|
||||||
|
mir::StatementKind::StorageDead(place) => {
|
||||||
|
stable_mir::mir::StatementKind::StorageDead(place.stable(tables))
|
||||||
|
}
|
||||||
|
mir::StatementKind::Retag(retag, place) => {
|
||||||
|
stable_mir::mir::StatementKind::Retag(retag.stable(tables), place.stable(tables))
|
||||||
|
}
|
||||||
|
mir::StatementKind::PlaceMention(place) => {
|
||||||
|
stable_mir::mir::StatementKind::PlaceMention(place.stable(tables))
|
||||||
|
}
|
||||||
|
mir::StatementKind::AscribeUserType(place_projection, variance) => {
|
||||||
|
stable_mir::mir::StatementKind::AscribeUserType {
|
||||||
|
place: place_projection.as_ref().0.stable(tables),
|
||||||
|
projections: place_projection.as_ref().1.stable(tables),
|
||||||
|
variance: variance.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::StatementKind::Coverage(coverage) => {
|
||||||
|
stable_mir::mir::StatementKind::Coverage(opaque(coverage))
|
||||||
|
}
|
||||||
|
mir::StatementKind::Intrinsic(intrinstic) => {
|
||||||
|
stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables))
|
||||||
|
}
|
||||||
|
mir::StatementKind::ConstEvalCounter => {
|
||||||
|
stable_mir::mir::StatementKind::ConstEvalCounter
|
||||||
|
}
|
||||||
|
mir::StatementKind::Nop => stable_mir::mir::StatementKind::Nop,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
|
||||||
|
type T = stable_mir::mir::Rvalue;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::Rvalue::*;
|
||||||
|
match self {
|
||||||
|
Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
|
||||||
|
Repeat(op, len) => {
|
||||||
|
let len = len.stable(tables);
|
||||||
|
stable_mir::mir::Rvalue::Repeat(op.stable(tables), len)
|
||||||
|
}
|
||||||
|
Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
|
||||||
|
region.stable(tables),
|
||||||
|
kind.stable(tables),
|
||||||
|
place.stable(tables),
|
||||||
|
),
|
||||||
|
ThreadLocalRef(def_id) => {
|
||||||
|
stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id))
|
||||||
|
}
|
||||||
|
AddressOf(mutability, place) => {
|
||||||
|
stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables))
|
||||||
|
}
|
||||||
|
Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)),
|
||||||
|
Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast(
|
||||||
|
cast_kind.stable(tables),
|
||||||
|
op.stable(tables),
|
||||||
|
ty.stable(tables),
|
||||||
|
),
|
||||||
|
BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp(
|
||||||
|
bin_op.stable(tables),
|
||||||
|
ops.0.stable(tables),
|
||||||
|
ops.1.stable(tables),
|
||||||
|
),
|
||||||
|
CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
|
||||||
|
bin_op.stable(tables),
|
||||||
|
ops.0.stable(tables),
|
||||||
|
ops.1.stable(tables),
|
||||||
|
),
|
||||||
|
NullaryOp(null_op, ty) => {
|
||||||
|
stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), ty.stable(tables))
|
||||||
|
}
|
||||||
|
UnaryOp(un_op, op) => {
|
||||||
|
stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables))
|
||||||
|
}
|
||||||
|
Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables)),
|
||||||
|
Aggregate(agg_kind, operands) => {
|
||||||
|
let operands = operands.iter().map(|op| op.stable(tables)).collect();
|
||||||
|
stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables), operands)
|
||||||
|
}
|
||||||
|
ShallowInitBox(op, ty) => {
|
||||||
|
stable_mir::mir::Rvalue::ShallowInitBox(op.stable(tables), ty.stable(tables))
|
||||||
|
}
|
||||||
|
CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::Mutability {
|
||||||
|
type T = stable_mir::mir::Mutability;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_hir::Mutability::*;
|
||||||
|
match *self {
|
||||||
|
Not => stable_mir::mir::Mutability::Not,
|
||||||
|
Mut => stable_mir::mir::Mutability::Mut,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::BorrowKind {
|
||||||
|
type T = stable_mir::mir::BorrowKind;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::BorrowKind::*;
|
||||||
|
match *self {
|
||||||
|
Shared => stable_mir::mir::BorrowKind::Shared,
|
||||||
|
Fake => stable_mir::mir::BorrowKind::Fake,
|
||||||
|
Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
|
||||||
|
type T = stable_mir::mir::MutBorrowKind;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::MutBorrowKind::*;
|
||||||
|
match *self {
|
||||||
|
Default => stable_mir::mir::MutBorrowKind::Default,
|
||||||
|
TwoPhaseBorrow => stable_mir::mir::MutBorrowKind::TwoPhaseBorrow,
|
||||||
|
ClosureCapture => stable_mir::mir::MutBorrowKind::ClosureCapture,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
|
||||||
|
type T = stable_mir::mir::NullOp;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::NullOp::*;
|
||||||
|
match self {
|
||||||
|
SizeOf => stable_mir::mir::NullOp::SizeOf,
|
||||||
|
AlignOf => stable_mir::mir::NullOp::AlignOf,
|
||||||
|
OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf(
|
||||||
|
indices.iter().map(|idx| idx.stable(tables)).collect(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::CastKind {
|
||||||
|
type T = stable_mir::mir::CastKind;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::CastKind::*;
|
||||||
|
match self {
|
||||||
|
PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress,
|
||||||
|
PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress,
|
||||||
|
PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
|
||||||
|
DynStar => stable_mir::mir::CastKind::DynStar,
|
||||||
|
IntToInt => stable_mir::mir::CastKind::IntToInt,
|
||||||
|
FloatToInt => stable_mir::mir::CastKind::FloatToInt,
|
||||||
|
FloatToFloat => stable_mir::mir::CastKind::FloatToFloat,
|
||||||
|
IntToFloat => stable_mir::mir::CastKind::IntToFloat,
|
||||||
|
PtrToPtr => stable_mir::mir::CastKind::PtrToPtr,
|
||||||
|
FnPtrToPtr => stable_mir::mir::CastKind::FnPtrToPtr,
|
||||||
|
Transmute => stable_mir::mir::CastKind::Transmute,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
|
||||||
|
type T = stable_mir::mir::FakeReadCause;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::FakeReadCause::*;
|
||||||
|
match self {
|
||||||
|
ForMatchGuard => stable_mir::mir::FakeReadCause::ForMatchGuard,
|
||||||
|
ForMatchedPlace(local_def_id) => {
|
||||||
|
stable_mir::mir::FakeReadCause::ForMatchedPlace(opaque(local_def_id))
|
||||||
|
}
|
||||||
|
ForGuardBinding => stable_mir::mir::FakeReadCause::ForGuardBinding,
|
||||||
|
ForLet(local_def_id) => stable_mir::mir::FakeReadCause::ForLet(opaque(local_def_id)),
|
||||||
|
ForIndex => stable_mir::mir::FakeReadCause::ForIndex,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
|
||||||
|
type T = stable_mir::mir::Operand;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::Operand::*;
|
||||||
|
match self {
|
||||||
|
Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)),
|
||||||
|
Move(place) => stable_mir::mir::Operand::Move(place.stable(tables)),
|
||||||
|
Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
|
||||||
|
type T = stable_mir::mir::Constant;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
stable_mir::mir::Constant {
|
||||||
|
span: self.span.stable(tables),
|
||||||
|
user_ty: self.user_ty.map(|u| u.as_usize()).or(None),
|
||||||
|
literal: self.const_.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
|
||||||
|
type T = stable_mir::mir::Place;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
stable_mir::mir::Place {
|
||||||
|
local: self.local.as_usize(),
|
||||||
|
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
|
||||||
|
type T = stable_mir::mir::ProjectionElem;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::ProjectionElem::*;
|
||||||
|
match self {
|
||||||
|
Deref => stable_mir::mir::ProjectionElem::Deref,
|
||||||
|
Field(idx, ty) => {
|
||||||
|
stable_mir::mir::ProjectionElem::Field(idx.stable(tables), ty.stable(tables))
|
||||||
|
}
|
||||||
|
Index(local) => stable_mir::mir::ProjectionElem::Index(local.stable(tables)),
|
||||||
|
ConstantIndex { offset, min_length, from_end } => {
|
||||||
|
stable_mir::mir::ProjectionElem::ConstantIndex {
|
||||||
|
offset: *offset,
|
||||||
|
min_length: *min_length,
|
||||||
|
from_end: *from_end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Subslice { from, to, from_end } => stable_mir::mir::ProjectionElem::Subslice {
|
||||||
|
from: *from,
|
||||||
|
to: *to,
|
||||||
|
from_end: *from_end,
|
||||||
|
},
|
||||||
|
// MIR includes an `Option<Symbol>` argument for `Downcast` that is the name of the
|
||||||
|
// variant, used for printing MIR. However this information should also be accessible
|
||||||
|
// via a lookup using the `VariantIdx`. The `Option<Symbol>` argument is therefore
|
||||||
|
// dropped when converting to Stable MIR. A brief justification for this decision can be
|
||||||
|
// found at https://github.com/rust-lang/rust/pull/117517#issuecomment-1811683486
|
||||||
|
Downcast(_, idx) => stable_mir::mir::ProjectionElem::Downcast(idx.stable(tables)),
|
||||||
|
OpaqueCast(ty) => stable_mir::mir::ProjectionElem::OpaqueCast(ty.stable(tables)),
|
||||||
|
Subtype(ty) => stable_mir::mir::ProjectionElem::Subtype(ty.stable(tables)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
|
||||||
|
type T = stable_mir::mir::UserTypeProjection;
|
||||||
|
|
||||||
|
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::Local {
|
||||||
|
type T = stable_mir::mir::Local;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
self.as_usize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::RetagKind {
|
||||||
|
type T = stable_mir::mir::RetagKind;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::RetagKind;
|
||||||
|
match self {
|
||||||
|
RetagKind::FnEntry => stable_mir::mir::RetagKind::FnEntry,
|
||||||
|
RetagKind::TwoPhase => stable_mir::mir::RetagKind::TwoPhase,
|
||||||
|
RetagKind::Raw => stable_mir::mir::RetagKind::Raw,
|
||||||
|
RetagKind::Default => stable_mir::mir::RetagKind::Default,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::UnwindAction {
|
||||||
|
type T = stable_mir::mir::UnwindAction;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::UnwindAction;
|
||||||
|
match self {
|
||||||
|
UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
|
||||||
|
UnwindAction::Unreachable => stable_mir::mir::UnwindAction::Unreachable,
|
||||||
|
UnwindAction::Terminate(_) => stable_mir::mir::UnwindAction::Terminate,
|
||||||
|
UnwindAction::Cleanup(bb) => stable_mir::mir::UnwindAction::Cleanup(bb.as_usize()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
|
||||||
|
type T = stable_mir::mir::NonDivergingIntrinsic;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::NonDivergingIntrinsic;
|
||||||
|
use stable_mir::mir::CopyNonOverlapping;
|
||||||
|
match self {
|
||||||
|
NonDivergingIntrinsic::Assume(op) => {
|
||||||
|
stable_mir::mir::NonDivergingIntrinsic::Assume(op.stable(tables))
|
||||||
|
}
|
||||||
|
NonDivergingIntrinsic::CopyNonOverlapping(copy_non_overlapping) => {
|
||||||
|
stable_mir::mir::NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
|
||||||
|
src: copy_non_overlapping.src.stable(tables),
|
||||||
|
dst: copy_non_overlapping.dst.stable(tables),
|
||||||
|
count: copy_non_overlapping.count.stable(tables),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
|
||||||
|
type T = stable_mir::mir::AssertMessage;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::AssertKind;
|
||||||
|
match self {
|
||||||
|
AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
|
||||||
|
len: len.stable(tables),
|
||||||
|
index: index.stable(tables),
|
||||||
|
},
|
||||||
|
AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
|
||||||
|
bin_op.stable(tables),
|
||||||
|
op1.stable(tables),
|
||||||
|
op2.stable(tables),
|
||||||
|
),
|
||||||
|
AssertKind::OverflowNeg(op) => {
|
||||||
|
stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables))
|
||||||
|
}
|
||||||
|
AssertKind::DivisionByZero(op) => {
|
||||||
|
stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables))
|
||||||
|
}
|
||||||
|
AssertKind::RemainderByZero(op) => {
|
||||||
|
stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
|
||||||
|
}
|
||||||
|
AssertKind::ResumedAfterReturn(coroutine) => {
|
||||||
|
stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables))
|
||||||
|
}
|
||||||
|
AssertKind::ResumedAfterPanic(coroutine) => {
|
||||||
|
stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables))
|
||||||
|
}
|
||||||
|
AssertKind::MisalignedPointerDereference { required, found } => {
|
||||||
|
stable_mir::mir::AssertMessage::MisalignedPointerDereference {
|
||||||
|
required: required.stable(tables),
|
||||||
|
found: found.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::BinOp {
|
||||||
|
type T = stable_mir::mir::BinOp;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::BinOp;
|
||||||
|
match self {
|
||||||
|
BinOp::Add => stable_mir::mir::BinOp::Add,
|
||||||
|
BinOp::AddUnchecked => stable_mir::mir::BinOp::AddUnchecked,
|
||||||
|
BinOp::Sub => stable_mir::mir::BinOp::Sub,
|
||||||
|
BinOp::SubUnchecked => stable_mir::mir::BinOp::SubUnchecked,
|
||||||
|
BinOp::Mul => stable_mir::mir::BinOp::Mul,
|
||||||
|
BinOp::MulUnchecked => stable_mir::mir::BinOp::MulUnchecked,
|
||||||
|
BinOp::Div => stable_mir::mir::BinOp::Div,
|
||||||
|
BinOp::Rem => stable_mir::mir::BinOp::Rem,
|
||||||
|
BinOp::BitXor => stable_mir::mir::BinOp::BitXor,
|
||||||
|
BinOp::BitAnd => stable_mir::mir::BinOp::BitAnd,
|
||||||
|
BinOp::BitOr => stable_mir::mir::BinOp::BitOr,
|
||||||
|
BinOp::Shl => stable_mir::mir::BinOp::Shl,
|
||||||
|
BinOp::ShlUnchecked => stable_mir::mir::BinOp::ShlUnchecked,
|
||||||
|
BinOp::Shr => stable_mir::mir::BinOp::Shr,
|
||||||
|
BinOp::ShrUnchecked => stable_mir::mir::BinOp::ShrUnchecked,
|
||||||
|
BinOp::Eq => stable_mir::mir::BinOp::Eq,
|
||||||
|
BinOp::Lt => stable_mir::mir::BinOp::Lt,
|
||||||
|
BinOp::Le => stable_mir::mir::BinOp::Le,
|
||||||
|
BinOp::Ne => stable_mir::mir::BinOp::Ne,
|
||||||
|
BinOp::Ge => stable_mir::mir::BinOp::Ge,
|
||||||
|
BinOp::Gt => stable_mir::mir::BinOp::Gt,
|
||||||
|
BinOp::Offset => stable_mir::mir::BinOp::Offset,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::UnOp {
|
||||||
|
type T = stable_mir::mir::UnOp;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::UnOp;
|
||||||
|
match self {
|
||||||
|
UnOp::Not => stable_mir::mir::UnOp::Not,
|
||||||
|
UnOp::Neg => stable_mir::mir::UnOp::Neg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
|
||||||
|
type T = stable_mir::mir::AggregateKind;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
mir::AggregateKind::Array(ty) => {
|
||||||
|
stable_mir::mir::AggregateKind::Array(ty.stable(tables))
|
||||||
|
}
|
||||||
|
mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple,
|
||||||
|
mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => {
|
||||||
|
stable_mir::mir::AggregateKind::Adt(
|
||||||
|
tables.adt_def(*def_id),
|
||||||
|
var_idx.index(),
|
||||||
|
generic_arg.stable(tables),
|
||||||
|
user_ty_index.map(|idx| idx.index()),
|
||||||
|
field_idx.map(|idx| idx.index()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mir::AggregateKind::Closure(def_id, generic_arg) => {
|
||||||
|
stable_mir::mir::AggregateKind::Closure(
|
||||||
|
tables.closure_def(*def_id),
|
||||||
|
generic_arg.stable(tables),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mir::AggregateKind::Coroutine(def_id, generic_arg, movability) => {
|
||||||
|
stable_mir::mir::AggregateKind::Coroutine(
|
||||||
|
tables.coroutine_def(*def_id),
|
||||||
|
generic_arg.stable(tables),
|
||||||
|
movability.stable(tables),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
|
||||||
|
type T = stable_mir::mir::InlineAsmOperand;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::mir::InlineAsmOperand;
|
||||||
|
|
||||||
|
let (in_value, out_place) = match self {
|
||||||
|
InlineAsmOperand::In { value, .. } => (Some(value.stable(tables)), None),
|
||||||
|
InlineAsmOperand::Out { place, .. } => (None, place.map(|place| place.stable(tables))),
|
||||||
|
InlineAsmOperand::InOut { in_value, out_place, .. } => {
|
||||||
|
(Some(in_value.stable(tables)), out_place.map(|place| place.stable(tables)))
|
||||||
|
}
|
||||||
|
InlineAsmOperand::Const { .. }
|
||||||
|
| InlineAsmOperand::SymFn { .. }
|
||||||
|
| InlineAsmOperand::SymStatic { .. } => (None, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
stable_mir::mir::InlineAsmOperand { in_value, out_place, raw_rpr: format!("{self:?}") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
|
||||||
|
type T = stable_mir::mir::Terminator;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::mir::Terminator;
|
||||||
|
Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
||||||
|
type T = stable_mir::mir::TerminatorKind;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::mir::TerminatorKind;
|
||||||
|
match self {
|
||||||
|
mir::TerminatorKind::Goto { target } => {
|
||||||
|
TerminatorKind::Goto { target: target.as_usize() }
|
||||||
|
}
|
||||||
|
mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
|
||||||
|
discr: discr.stable(tables),
|
||||||
|
targets: targets
|
||||||
|
.iter()
|
||||||
|
.map(|(value, target)| stable_mir::mir::SwitchTarget {
|
||||||
|
value,
|
||||||
|
target: target.as_usize(),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
otherwise: targets.otherwise().as_usize(),
|
||||||
|
},
|
||||||
|
mir::TerminatorKind::UnwindResume => TerminatorKind::Resume,
|
||||||
|
mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort,
|
||||||
|
mir::TerminatorKind::Return => TerminatorKind::Return,
|
||||||
|
mir::TerminatorKind::Unreachable => TerminatorKind::Unreachable,
|
||||||
|
mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => {
|
||||||
|
TerminatorKind::Drop {
|
||||||
|
place: place.stable(tables),
|
||||||
|
target: target.as_usize(),
|
||||||
|
unwind: unwind.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::TerminatorKind::Call {
|
||||||
|
func,
|
||||||
|
args,
|
||||||
|
destination,
|
||||||
|
target,
|
||||||
|
unwind,
|
||||||
|
call_source: _,
|
||||||
|
fn_span: _,
|
||||||
|
} => TerminatorKind::Call {
|
||||||
|
func: func.stable(tables),
|
||||||
|
args: args.iter().map(|arg| arg.stable(tables)).collect(),
|
||||||
|
destination: destination.stable(tables),
|
||||||
|
target: target.map(|t| t.as_usize()),
|
||||||
|
unwind: unwind.stable(tables),
|
||||||
|
},
|
||||||
|
mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => {
|
||||||
|
TerminatorKind::Assert {
|
||||||
|
cond: cond.stable(tables),
|
||||||
|
expected: *expected,
|
||||||
|
msg: msg.stable(tables),
|
||||||
|
target: target.as_usize(),
|
||||||
|
unwind: unwind.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mir::TerminatorKind::InlineAsm {
|
||||||
|
template,
|
||||||
|
operands,
|
||||||
|
options,
|
||||||
|
line_spans,
|
||||||
|
destination,
|
||||||
|
unwind,
|
||||||
|
} => TerminatorKind::InlineAsm {
|
||||||
|
template: format!("{template:?}"),
|
||||||
|
operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
|
||||||
|
options: format!("{options:?}"),
|
||||||
|
line_spans: format!("{line_spans:?}"),
|
||||||
|
destination: destination.map(|d| d.as_usize()),
|
||||||
|
unwind: unwind.stable(tables),
|
||||||
|
},
|
||||||
|
mir::TerminatorKind::Yield { .. }
|
||||||
|
| mir::TerminatorKind::CoroutineDrop
|
||||||
|
| mir::TerminatorKind::FalseEdge { .. }
|
||||||
|
| mir::TerminatorKind::FalseUnwind { .. } => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
|
||||||
|
type T = Allocation;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
self.inner().stable(tables)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
|
||||||
|
type T = stable_mir::ty::Allocation;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
alloc::allocation_filter(
|
||||||
|
self,
|
||||||
|
alloc_range(rustc_target::abi::Size::ZERO, self.size()),
|
||||||
|
tables,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
|
||||||
|
type T = stable_mir::mir::alloc::AllocId;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
tables.create_alloc_id(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
|
||||||
|
type T = GlobalAlloc;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
mir::interpret::GlobalAlloc::Function(instance) => {
|
||||||
|
GlobalAlloc::Function(instance.stable(tables))
|
||||||
|
}
|
||||||
|
mir::interpret::GlobalAlloc::VTable(ty, trait_ref) => {
|
||||||
|
GlobalAlloc::VTable(ty.stable(tables), trait_ref.stable(tables))
|
||||||
|
}
|
||||||
|
mir::interpret::GlobalAlloc::Static(def) => {
|
||||||
|
GlobalAlloc::Static(tables.static_def(*def))
|
||||||
|
}
|
||||||
|
mir::interpret::GlobalAlloc::Memory(alloc) => GlobalAlloc::Memory(alloc.stable(tables)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
|
||||||
|
type T = stable_mir::ty::Const;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match *self {
|
||||||
|
mir::Const::Ty(c) => c.stable(tables),
|
||||||
|
mir::Const::Unevaluated(unev_const, ty) => {
|
||||||
|
let kind =
|
||||||
|
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
|
||||||
|
def: tables.const_def(unev_const.def),
|
||||||
|
args: unev_const.args.stable(tables),
|
||||||
|
promoted: unev_const.promoted.map(|u| u.as_u32()),
|
||||||
|
});
|
||||||
|
let ty = ty.stable(tables);
|
||||||
|
let id = tables.intern_const(*self);
|
||||||
|
Const::new(kind, ty, id)
|
||||||
|
}
|
||||||
|
mir::Const::Val(val, ty) if matches!(val, mir::ConstValue::ZeroSized) => {
|
||||||
|
let ty = ty.stable(tables);
|
||||||
|
let id = tables.intern_const(*self);
|
||||||
|
Const::new(ConstantKind::ZeroSized, ty, id)
|
||||||
|
}
|
||||||
|
mir::Const::Val(val, ty) => {
|
||||||
|
let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables));
|
||||||
|
let ty = ty.stable(tables);
|
||||||
|
let id = tables.intern_const(*self);
|
||||||
|
Const::new(kind, ty, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
|
||||||
|
type T = Error;
|
||||||
|
|
||||||
|
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
Error::new(format!("{self:?}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
|
||||||
|
type T = stable_mir::mir::mono::MonoItem;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::mir::mono::MonoItem as StableMonoItem;
|
||||||
|
match self {
|
||||||
|
MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)),
|
||||||
|
MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)),
|
||||||
|
MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
76
compiler/rustc_smir/src/rustc_smir/convert/mod.rs
Normal file
76
compiler/rustc_smir/src/rustc_smir/convert/mod.rs
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//! Conversion of internal Rust compiler items to stable ones.
|
||||||
|
|
||||||
|
use rustc_target::abi::FieldIdx;
|
||||||
|
use stable_mir::mir::VariantIdx;
|
||||||
|
|
||||||
|
use crate::rustc_smir::{Stable, Tables};
|
||||||
|
|
||||||
|
mod mir;
|
||||||
|
mod ty;
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_hir::Unsafety {
|
||||||
|
type T = stable_mir::mir::Safety;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe,
|
||||||
|
rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for FieldIdx {
|
||||||
|
type T = usize;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
self.as_usize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for (rustc_target::abi::VariantIdx, FieldIdx) {
|
||||||
|
type T = (usize, usize);
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
(self.0.as_usize(), self.1.as_usize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_target::abi::VariantIdx {
|
||||||
|
type T = VariantIdx;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
self.as_usize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
|
||||||
|
type T = stable_mir::mir::CoroutineSource;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_hir::CoroutineSource;
|
||||||
|
match self {
|
||||||
|
CoroutineSource::Block => stable_mir::mir::CoroutineSource::Block,
|
||||||
|
CoroutineSource::Closure => stable_mir::mir::CoroutineSource::Closure,
|
||||||
|
CoroutineSource::Fn => stable_mir::mir::CoroutineSource::Fn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
|
||||||
|
type T = stable_mir::mir::CoroutineKind;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_hir::CoroutineKind;
|
||||||
|
match self {
|
||||||
|
CoroutineKind::Async(source) => {
|
||||||
|
stable_mir::mir::CoroutineKind::Async(source.stable(tables))
|
||||||
|
}
|
||||||
|
CoroutineKind::Gen(source) => {
|
||||||
|
stable_mir::mir::CoroutineKind::Gen(source.stable(tables))
|
||||||
|
}
|
||||||
|
CoroutineKind::Coroutine => stable_mir::mir::CoroutineKind::Coroutine,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_span::Span {
|
||||||
|
type T = stable_mir::ty::Span;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
tables.create_span(*self)
|
||||||
|
}
|
||||||
|
}
|
815
compiler/rustc_smir/src/rustc_smir/convert/ty.rs
Normal file
815
compiler/rustc_smir/src/rustc_smir/convert/ty.rs
Normal file
@ -0,0 +1,815 @@
|
|||||||
|
//! Conversion of internal Rust compiler `ty` items to stable ones.
|
||||||
|
|
||||||
|
use rustc_middle::ty::Ty;
|
||||||
|
use rustc_middle::{mir, ty};
|
||||||
|
use stable_mir::ty::{
|
||||||
|
AdtKind, Const, ConstantKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy,
|
||||||
|
TyKind, UintTy,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::rustc_smir::{alloc, Stable, Tables};
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::AliasKind {
|
||||||
|
type T = stable_mir::ty::AliasKind;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::ty::AliasKind::*;
|
||||||
|
match self {
|
||||||
|
Projection => stable_mir::ty::AliasKind::Projection,
|
||||||
|
Inherent => stable_mir::ty::AliasKind::Inherent,
|
||||||
|
Opaque => stable_mir::ty::AliasKind::Opaque,
|
||||||
|
Weak => stable_mir::ty::AliasKind::Weak,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
|
||||||
|
type T = stable_mir::ty::AliasTy;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::AliasTy { args, def_id, .. } = self;
|
||||||
|
stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::DynKind {
|
||||||
|
type T = stable_mir::ty::DynKind;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::ty::DynKind;
|
||||||
|
match self {
|
||||||
|
DynKind::Dyn => stable_mir::ty::DynKind::Dyn,
|
||||||
|
DynKind::DynStar => stable_mir::ty::DynKind::DynStar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
|
||||||
|
type T = stable_mir::ty::ExistentialPredicate;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::ExistentialPredicate::*;
|
||||||
|
match self {
|
||||||
|
ty::ExistentialPredicate::Trait(existential_trait_ref) => {
|
||||||
|
Trait(existential_trait_ref.stable(tables))
|
||||||
|
}
|
||||||
|
ty::ExistentialPredicate::Projection(existential_projection) => {
|
||||||
|
Projection(existential_projection.stable(tables))
|
||||||
|
}
|
||||||
|
ty::ExistentialPredicate::AutoTrait(def_id) => AutoTrait(tables.trait_def(*def_id)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
|
||||||
|
type T = stable_mir::ty::ExistentialTraitRef;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::ExistentialTraitRef { def_id, args } = self;
|
||||||
|
stable_mir::ty::ExistentialTraitRef {
|
||||||
|
def_id: tables.trait_def(*def_id),
|
||||||
|
generic_args: args.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
|
||||||
|
type T = stable_mir::ty::TermKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::TermKind;
|
||||||
|
match self {
|
||||||
|
ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables)),
|
||||||
|
ty::TermKind::Const(cnst) => {
|
||||||
|
let cnst = cnst.stable(tables);
|
||||||
|
TermKind::Const(cnst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
|
||||||
|
type T = stable_mir::ty::ExistentialProjection;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::ExistentialProjection { def_id, args, term } = self;
|
||||||
|
stable_mir::ty::ExistentialProjection {
|
||||||
|
def_id: tables.trait_def(*def_id),
|
||||||
|
generic_args: args.stable(tables),
|
||||||
|
term: term.unpack().stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
|
||||||
|
type T = stable_mir::mir::PointerCoercion;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||||
|
match self {
|
||||||
|
PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer,
|
||||||
|
PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer,
|
||||||
|
PointerCoercion::ClosureFnPointer(unsafety) => {
|
||||||
|
stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable(tables))
|
||||||
|
}
|
||||||
|
PointerCoercion::MutToConstPointer => {
|
||||||
|
stable_mir::mir::PointerCoercion::MutToConstPointer
|
||||||
|
}
|
||||||
|
PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer,
|
||||||
|
PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex {
|
||||||
|
type T = usize;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
self.as_usize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::AdtKind {
|
||||||
|
type T = AdtKind;
|
||||||
|
|
||||||
|
fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
ty::AdtKind::Struct => AdtKind::Struct,
|
||||||
|
ty::AdtKind::Union => AdtKind::Union,
|
||||||
|
ty::AdtKind::Enum => AdtKind::Enum,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
|
||||||
|
type T = stable_mir::ty::GenericArgs;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
GenericArgs(self.iter().map(|arg| arg.unpack().stable(tables)).collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> {
|
||||||
|
type T = stable_mir::ty::GenericArgKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::GenericArgKind;
|
||||||
|
match self {
|
||||||
|
ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(region.stable(tables)),
|
||||||
|
ty::GenericArgKind::Type(ty) => GenericArgKind::Type(ty.stable(tables)),
|
||||||
|
ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, S, V> Stable<'tcx> for ty::Binder<'tcx, S>
|
||||||
|
where
|
||||||
|
S: Stable<'tcx, T = V>,
|
||||||
|
{
|
||||||
|
type T = stable_mir::ty::Binder<V>;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::Binder;
|
||||||
|
|
||||||
|
Binder {
|
||||||
|
value: self.as_ref().skip_binder().stable(tables),
|
||||||
|
bound_vars: self
|
||||||
|
.bound_vars()
|
||||||
|
.iter()
|
||||||
|
.map(|bound_var| bound_var.stable(tables))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, S, V> Stable<'tcx> for ty::EarlyBinder<S>
|
||||||
|
where
|
||||||
|
S: Stable<'tcx, T = V>,
|
||||||
|
{
|
||||||
|
type T = stable_mir::ty::EarlyBinder<V>;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::EarlyBinder;
|
||||||
|
|
||||||
|
EarlyBinder { value: self.as_ref().skip_binder().stable(tables) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
|
||||||
|
type T = stable_mir::ty::FnSig;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_target::spec::abi;
|
||||||
|
use stable_mir::ty::{Abi, FnSig};
|
||||||
|
|
||||||
|
FnSig {
|
||||||
|
inputs_and_output: self.inputs_and_output.iter().map(|ty| ty.stable(tables)).collect(),
|
||||||
|
c_variadic: self.c_variadic,
|
||||||
|
unsafety: self.unsafety.stable(tables),
|
||||||
|
abi: match self.abi {
|
||||||
|
abi::Abi::Rust => Abi::Rust,
|
||||||
|
abi::Abi::C { unwind } => Abi::C { unwind },
|
||||||
|
abi::Abi::Cdecl { unwind } => Abi::Cdecl { unwind },
|
||||||
|
abi::Abi::Stdcall { unwind } => Abi::Stdcall { unwind },
|
||||||
|
abi::Abi::Fastcall { unwind } => Abi::Fastcall { unwind },
|
||||||
|
abi::Abi::Vectorcall { unwind } => Abi::Vectorcall { unwind },
|
||||||
|
abi::Abi::Thiscall { unwind } => Abi::Thiscall { unwind },
|
||||||
|
abi::Abi::Aapcs { unwind } => Abi::Aapcs { unwind },
|
||||||
|
abi::Abi::Win64 { unwind } => Abi::Win64 { unwind },
|
||||||
|
abi::Abi::SysV64 { unwind } => Abi::SysV64 { unwind },
|
||||||
|
abi::Abi::PtxKernel => Abi::PtxKernel,
|
||||||
|
abi::Abi::Msp430Interrupt => Abi::Msp430Interrupt,
|
||||||
|
abi::Abi::X86Interrupt => Abi::X86Interrupt,
|
||||||
|
abi::Abi::AmdGpuKernel => Abi::AmdGpuKernel,
|
||||||
|
abi::Abi::EfiApi => Abi::EfiApi,
|
||||||
|
abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
|
||||||
|
abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
|
||||||
|
abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
|
||||||
|
abi::Abi::Wasm => Abi::Wasm,
|
||||||
|
abi::Abi::System { unwind } => Abi::System { unwind },
|
||||||
|
abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
|
||||||
|
abi::Abi::RustCall => Abi::RustCall,
|
||||||
|
abi::Abi::PlatformIntrinsic => Abi::PlatformIntrinsic,
|
||||||
|
abi::Abi::Unadjusted => Abi::Unadjusted,
|
||||||
|
abi::Abi::RustCold => Abi::RustCold,
|
||||||
|
abi::Abi::RiscvInterruptM => Abi::RiscvInterruptM,
|
||||||
|
abi::Abi::RiscvInterruptS => Abi::RiscvInterruptS,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
|
||||||
|
type T = stable_mir::ty::BoundTyKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::BoundTyKind;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
ty::BoundTyKind::Anon => BoundTyKind::Anon,
|
||||||
|
ty::BoundTyKind::Param(def_id, symbol) => {
|
||||||
|
BoundTyKind::Param(tables.param_def(*def_id), symbol.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
|
||||||
|
type T = stable_mir::ty::BoundRegionKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::BoundRegionKind;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
ty::BoundRegionKind::BrAnon => BoundRegionKind::BrAnon,
|
||||||
|
ty::BoundRegionKind::BrNamed(def_id, symbol) => {
|
||||||
|
BoundRegionKind::BrNamed(tables.br_named_def(*def_id), symbol.to_string())
|
||||||
|
}
|
||||||
|
ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
|
||||||
|
type T = stable_mir::ty::BoundVariableKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::BoundVariableKind;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
ty::BoundVariableKind::Ty(bound_ty_kind) => {
|
||||||
|
BoundVariableKind::Ty(bound_ty_kind.stable(tables))
|
||||||
|
}
|
||||||
|
ty::BoundVariableKind::Region(bound_region_kind) => {
|
||||||
|
BoundVariableKind::Region(bound_region_kind.stable(tables))
|
||||||
|
}
|
||||||
|
ty::BoundVariableKind::Const => BoundVariableKind::Const,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::IntTy {
|
||||||
|
type T = IntTy;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
ty::IntTy::Isize => IntTy::Isize,
|
||||||
|
ty::IntTy::I8 => IntTy::I8,
|
||||||
|
ty::IntTy::I16 => IntTy::I16,
|
||||||
|
ty::IntTy::I32 => IntTy::I32,
|
||||||
|
ty::IntTy::I64 => IntTy::I64,
|
||||||
|
ty::IntTy::I128 => IntTy::I128,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::UintTy {
|
||||||
|
type T = UintTy;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
ty::UintTy::Usize => UintTy::Usize,
|
||||||
|
ty::UintTy::U8 => UintTy::U8,
|
||||||
|
ty::UintTy::U16 => UintTy::U16,
|
||||||
|
ty::UintTy::U32 => UintTy::U32,
|
||||||
|
ty::UintTy::U64 => UintTy::U64,
|
||||||
|
ty::UintTy::U128 => UintTy::U128,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::FloatTy {
|
||||||
|
type T = FloatTy;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
ty::FloatTy::F32 => FloatTy::F32,
|
||||||
|
ty::FloatTy::F64 => FloatTy::F64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for Ty<'tcx> {
|
||||||
|
type T = stable_mir::ty::Ty;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
tables.intern_ty(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
|
||||||
|
type T = stable_mir::ty::TyKind;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
ty::Bool => TyKind::RigidTy(RigidTy::Bool),
|
||||||
|
ty::Char => TyKind::RigidTy(RigidTy::Char),
|
||||||
|
ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables))),
|
||||||
|
ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))),
|
||||||
|
ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))),
|
||||||
|
ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt(
|
||||||
|
tables.adt_def(adt_def.did()),
|
||||||
|
generic_args.stable(tables),
|
||||||
|
)),
|
||||||
|
ty::Foreign(def_id) => TyKind::RigidTy(RigidTy::Foreign(tables.foreign_def(*def_id))),
|
||||||
|
ty::Str => TyKind::RigidTy(RigidTy::Str),
|
||||||
|
ty::Array(ty, constant) => {
|
||||||
|
TyKind::RigidTy(RigidTy::Array(ty.stable(tables), constant.stable(tables)))
|
||||||
|
}
|
||||||
|
ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables))),
|
||||||
|
ty::RawPtr(ty::TypeAndMut { ty, mutbl }) => {
|
||||||
|
TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables), mutbl.stable(tables)))
|
||||||
|
}
|
||||||
|
ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref(
|
||||||
|
region.stable(tables),
|
||||||
|
ty.stable(tables),
|
||||||
|
mutbl.stable(tables),
|
||||||
|
)),
|
||||||
|
ty::FnDef(def_id, generic_args) => {
|
||||||
|
TyKind::RigidTy(RigidTy::FnDef(tables.fn_def(*def_id), generic_args.stable(tables)))
|
||||||
|
}
|
||||||
|
ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))),
|
||||||
|
ty::Dynamic(existential_predicates, region, dyn_kind) => {
|
||||||
|
TyKind::RigidTy(RigidTy::Dynamic(
|
||||||
|
existential_predicates
|
||||||
|
.iter()
|
||||||
|
.map(|existential_predicate| existential_predicate.stable(tables))
|
||||||
|
.collect(),
|
||||||
|
region.stable(tables),
|
||||||
|
dyn_kind.stable(tables),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure(
|
||||||
|
tables.closure_def(*def_id),
|
||||||
|
generic_args.stable(tables),
|
||||||
|
)),
|
||||||
|
ty::Coroutine(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Coroutine(
|
||||||
|
tables.coroutine_def(*def_id),
|
||||||
|
generic_args.stable(tables),
|
||||||
|
movability.stable(tables),
|
||||||
|
)),
|
||||||
|
ty::Never => TyKind::RigidTy(RigidTy::Never),
|
||||||
|
ty::Tuple(fields) => {
|
||||||
|
TyKind::RigidTy(RigidTy::Tuple(fields.iter().map(|ty| ty.stable(tables)).collect()))
|
||||||
|
}
|
||||||
|
ty::Alias(alias_kind, alias_ty) => {
|
||||||
|
TyKind::Alias(alias_kind.stable(tables), alias_ty.stable(tables))
|
||||||
|
}
|
||||||
|
ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables)),
|
||||||
|
ty::Bound(debruijn_idx, bound_ty) => {
|
||||||
|
TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables))
|
||||||
|
}
|
||||||
|
ty::CoroutineWitness(def_id, args) => TyKind::RigidTy(RigidTy::CoroutineWitness(
|
||||||
|
tables.coroutine_witness_def(*def_id),
|
||||||
|
args.stable(tables),
|
||||||
|
)),
|
||||||
|
ty::Placeholder(..) | ty::Infer(_) | ty::Error(_) => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
|
||||||
|
type T = stable_mir::ty::Const;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let kind = match self.kind() {
|
||||||
|
ty::Value(val) => {
|
||||||
|
let const_val = tables.tcx.valtree_to_const_val((self.ty(), val));
|
||||||
|
if matches!(const_val, mir::ConstValue::ZeroSized) {
|
||||||
|
ConstantKind::ZeroSized
|
||||||
|
} else {
|
||||||
|
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
|
||||||
|
self.ty(),
|
||||||
|
const_val,
|
||||||
|
tables,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ty::ParamCt(param) => stable_mir::ty::ConstantKind::Param(param.stable(tables)),
|
||||||
|
ty::ErrorCt(_) => unreachable!(),
|
||||||
|
ty::InferCt(_) => unreachable!(),
|
||||||
|
ty::BoundCt(_, _) => unimplemented!(),
|
||||||
|
ty::PlaceholderCt(_) => unimplemented!(),
|
||||||
|
ty::Unevaluated(uv) => {
|
||||||
|
stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst {
|
||||||
|
def: tables.const_def(uv.def),
|
||||||
|
args: uv.args.stable(tables),
|
||||||
|
promoted: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ty::ExprCt(_) => unimplemented!(),
|
||||||
|
};
|
||||||
|
let ty = self.ty().stable(tables);
|
||||||
|
let id = tables.intern_const(mir::Const::Ty(*self));
|
||||||
|
Const::new(kind, ty, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ParamConst {
|
||||||
|
type T = stable_mir::ty::ParamConst;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::ParamConst;
|
||||||
|
ParamConst { index: self.index, name: self.name.to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ParamTy {
|
||||||
|
type T = stable_mir::ty::ParamTy;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::ParamTy;
|
||||||
|
ParamTy { index: self.index, name: self.name.to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::BoundTy {
|
||||||
|
type T = stable_mir::ty::BoundTy;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::BoundTy;
|
||||||
|
BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
|
||||||
|
type T = stable_mir::ty::TraitSpecializationKind;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::TraitSpecializationKind;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
ty::trait_def::TraitSpecializationKind::None => TraitSpecializationKind::None,
|
||||||
|
ty::trait_def::TraitSpecializationKind::Marker => TraitSpecializationKind::Marker,
|
||||||
|
ty::trait_def::TraitSpecializationKind::AlwaysApplicable => {
|
||||||
|
TraitSpecializationKind::AlwaysApplicable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::TraitDef {
|
||||||
|
type T = stable_mir::ty::TraitDecl;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::opaque;
|
||||||
|
use stable_mir::ty::TraitDecl;
|
||||||
|
|
||||||
|
TraitDecl {
|
||||||
|
def_id: tables.trait_def(self.def_id),
|
||||||
|
unsafety: self.unsafety.stable(tables),
|
||||||
|
paren_sugar: self.paren_sugar,
|
||||||
|
has_auto_impl: self.has_auto_impl,
|
||||||
|
is_marker: self.is_marker,
|
||||||
|
is_coinductive: self.is_coinductive,
|
||||||
|
skip_array_during_method_dispatch: self.skip_array_during_method_dispatch,
|
||||||
|
specialization_kind: self.specialization_kind.stable(tables),
|
||||||
|
must_implement_one_of: self
|
||||||
|
.must_implement_one_of
|
||||||
|
.as_ref()
|
||||||
|
.map(|idents| idents.iter().map(|ident| opaque(ident)).collect()),
|
||||||
|
implement_via_object: self.implement_via_object,
|
||||||
|
deny_explicit_impl: self.deny_explicit_impl,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
|
||||||
|
type T = stable_mir::ty::TraitRef;
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::TraitRef;
|
||||||
|
|
||||||
|
TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables)).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::Generics {
|
||||||
|
type T = stable_mir::ty::Generics;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::Generics;
|
||||||
|
|
||||||
|
let params: Vec<_> = self.params.iter().map(|param| param.stable(tables)).collect();
|
||||||
|
let param_def_id_to_index =
|
||||||
|
params.iter().map(|param| (param.def_id, param.index)).collect();
|
||||||
|
|
||||||
|
Generics {
|
||||||
|
parent: self.parent.map(|did| tables.generic_def(did)),
|
||||||
|
parent_count: self.parent_count,
|
||||||
|
params,
|
||||||
|
param_def_id_to_index,
|
||||||
|
has_self: self.has_self,
|
||||||
|
has_late_bound_regions: self
|
||||||
|
.has_late_bound_regions
|
||||||
|
.as_ref()
|
||||||
|
.map(|late_bound_regions| late_bound_regions.stable(tables)),
|
||||||
|
host_effect_index: self.host_effect_index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
|
||||||
|
type T = stable_mir::ty::GenericParamDefKind;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::GenericParamDefKind;
|
||||||
|
match self {
|
||||||
|
ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime,
|
||||||
|
ty::GenericParamDefKind::Type { has_default, synthetic } => {
|
||||||
|
GenericParamDefKind::Type { has_default: *has_default, synthetic: *synthetic }
|
||||||
|
}
|
||||||
|
ty::GenericParamDefKind::Const { has_default, is_host_effect: _ } => {
|
||||||
|
GenericParamDefKind::Const { has_default: *has_default }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef {
|
||||||
|
type T = stable_mir::ty::GenericParamDef;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
GenericParamDef {
|
||||||
|
name: self.name.to_string(),
|
||||||
|
def_id: tables.generic_def(self.def_id),
|
||||||
|
index: self.index,
|
||||||
|
pure_wrt_drop: self.pure_wrt_drop,
|
||||||
|
kind: self.kind.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
|
||||||
|
type T = stable_mir::ty::PredicateKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::ty::PredicateKind;
|
||||||
|
match self {
|
||||||
|
PredicateKind::Clause(clause_kind) => {
|
||||||
|
stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables))
|
||||||
|
}
|
||||||
|
PredicateKind::ObjectSafe(did) => {
|
||||||
|
stable_mir::ty::PredicateKind::ObjectSafe(tables.trait_def(*did))
|
||||||
|
}
|
||||||
|
PredicateKind::Subtype(subtype_predicate) => {
|
||||||
|
stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables))
|
||||||
|
}
|
||||||
|
PredicateKind::Coerce(coerce_predicate) => {
|
||||||
|
stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables))
|
||||||
|
}
|
||||||
|
PredicateKind::ConstEquate(a, b) => {
|
||||||
|
stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables))
|
||||||
|
}
|
||||||
|
PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous,
|
||||||
|
PredicateKind::AliasRelate(a, b, alias_relation_direction) => {
|
||||||
|
stable_mir::ty::PredicateKind::AliasRelate(
|
||||||
|
a.unpack().stable(tables),
|
||||||
|
b.unpack().stable(tables),
|
||||||
|
alias_relation_direction.stable(tables),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
|
||||||
|
type T = stable_mir::ty::ClauseKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::ty::ClauseKind;
|
||||||
|
match *self {
|
||||||
|
ClauseKind::Trait(trait_object) => {
|
||||||
|
stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables))
|
||||||
|
}
|
||||||
|
ClauseKind::RegionOutlives(region_outlives) => {
|
||||||
|
stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables))
|
||||||
|
}
|
||||||
|
ClauseKind::TypeOutlives(type_outlives) => {
|
||||||
|
let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives;
|
||||||
|
stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate(
|
||||||
|
a.stable(tables),
|
||||||
|
b.stable(tables),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
ClauseKind::Projection(projection_predicate) => {
|
||||||
|
stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables))
|
||||||
|
}
|
||||||
|
ClauseKind::ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType(
|
||||||
|
const_.stable(tables),
|
||||||
|
ty.stable(tables),
|
||||||
|
),
|
||||||
|
ClauseKind::WellFormed(generic_arg) => {
|
||||||
|
stable_mir::ty::ClauseKind::WellFormed(generic_arg.unpack().stable(tables))
|
||||||
|
}
|
||||||
|
ClauseKind::ConstEvaluatable(const_) => {
|
||||||
|
stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ClosureKind {
|
||||||
|
type T = stable_mir::ty::ClosureKind;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::ty::ClosureKind::*;
|
||||||
|
match self {
|
||||||
|
Fn => stable_mir::ty::ClosureKind::Fn,
|
||||||
|
FnMut => stable_mir::ty::ClosureKind::FnMut,
|
||||||
|
FnOnce => stable_mir::ty::ClosureKind::FnOnce,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> {
|
||||||
|
type T = stable_mir::ty::SubtypePredicate;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::SubtypePredicate { a, b, a_is_expected: _ } = self;
|
||||||
|
stable_mir::ty::SubtypePredicate { a: a.stable(tables), b: b.stable(tables) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> {
|
||||||
|
type T = stable_mir::ty::CoercePredicate;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::CoercePredicate { a, b } = self;
|
||||||
|
stable_mir::ty::CoercePredicate { a: a.stable(tables), b: b.stable(tables) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection {
|
||||||
|
type T = stable_mir::ty::AliasRelationDirection;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::ty::AliasRelationDirection::*;
|
||||||
|
match self {
|
||||||
|
Equate => stable_mir::ty::AliasRelationDirection::Equate,
|
||||||
|
Subtype => stable_mir::ty::AliasRelationDirection::Subtype,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> {
|
||||||
|
type T = stable_mir::ty::TraitPredicate;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::TraitPredicate { trait_ref, polarity } = self;
|
||||||
|
stable_mir::ty::TraitPredicate {
|
||||||
|
trait_ref: trait_ref.stable(tables),
|
||||||
|
polarity: polarity.stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx, A, B, U, V> Stable<'tcx> for ty::OutlivesPredicate<A, B>
|
||||||
|
where
|
||||||
|
A: Stable<'tcx, T = U>,
|
||||||
|
B: Stable<'tcx, T = V>,
|
||||||
|
{
|
||||||
|
type T = stable_mir::ty::OutlivesPredicate<U, V>;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::OutlivesPredicate(a, b) = self;
|
||||||
|
stable_mir::ty::OutlivesPredicate(a.stable(tables), b.stable(tables))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> {
|
||||||
|
type T = stable_mir::ty::ProjectionPredicate;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let ty::ProjectionPredicate { projection_ty, term } = self;
|
||||||
|
stable_mir::ty::ProjectionPredicate {
|
||||||
|
projection_ty: projection_ty.stable(tables),
|
||||||
|
term: term.unpack().stable(tables),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::ImplPolarity {
|
||||||
|
type T = stable_mir::ty::ImplPolarity;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use rustc_middle::ty::ImplPolarity::*;
|
||||||
|
match self {
|
||||||
|
Positive => stable_mir::ty::ImplPolarity::Positive,
|
||||||
|
Negative => stable_mir::ty::ImplPolarity::Negative,
|
||||||
|
Reservation => stable_mir::ty::ImplPolarity::Reservation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::Region<'tcx> {
|
||||||
|
type T = stable_mir::ty::Region;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
Region { kind: self.kind().stable(tables) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
|
||||||
|
type T = stable_mir::ty::RegionKind;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
use stable_mir::ty::{BoundRegion, EarlyParamRegion, RegionKind};
|
||||||
|
match self {
|
||||||
|
ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion {
|
||||||
|
def_id: tables.region_def(early_reg.def_id),
|
||||||
|
index: early_reg.index,
|
||||||
|
name: early_reg.name.to_string(),
|
||||||
|
}),
|
||||||
|
ty::ReBound(db_index, bound_reg) => RegionKind::ReBound(
|
||||||
|
db_index.as_u32(),
|
||||||
|
BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) },
|
||||||
|
),
|
||||||
|
ty::ReStatic => RegionKind::ReStatic,
|
||||||
|
ty::RePlaceholder(place_holder) => {
|
||||||
|
RegionKind::RePlaceholder(stable_mir::ty::Placeholder {
|
||||||
|
universe: place_holder.universe.as_u32(),
|
||||||
|
bound: BoundRegion {
|
||||||
|
var: place_holder.bound.var.as_u32(),
|
||||||
|
kind: place_holder.bound.kind.stable(tables),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ty::ReErased => RegionKind::ReErased,
|
||||||
|
_ => unreachable!("{self:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
|
||||||
|
type T = stable_mir::mir::mono::Instance;
|
||||||
|
|
||||||
|
fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
let def = tables.instance_def(*self);
|
||||||
|
let kind = match self.def {
|
||||||
|
ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item,
|
||||||
|
ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic,
|
||||||
|
ty::InstanceDef::Virtual(..) => stable_mir::mir::mono::InstanceKind::Virtual,
|
||||||
|
ty::InstanceDef::VTableShim(..)
|
||||||
|
| ty::InstanceDef::ReifyShim(..)
|
||||||
|
| ty::InstanceDef::FnPtrAddrShim(..)
|
||||||
|
| ty::InstanceDef::ClosureOnceShim { .. }
|
||||||
|
| ty::InstanceDef::ThreadLocalShim(..)
|
||||||
|
| ty::InstanceDef::DropGlue(..)
|
||||||
|
| ty::InstanceDef::CloneShim(..)
|
||||||
|
| ty::InstanceDef::FnPtrShim(..) => stable_mir::mir::mono::InstanceKind::Shim,
|
||||||
|
};
|
||||||
|
stable_mir::mir::mono::Instance { def, kind }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::Variance {
|
||||||
|
type T = stable_mir::mir::Variance;
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
ty::Variance::Bivariant => stable_mir::mir::Variance::Bivariant,
|
||||||
|
ty::Variance::Contravariant => stable_mir::mir::Variance::Contravariant,
|
||||||
|
ty::Variance::Covariant => stable_mir::mir::Variance::Covariant,
|
||||||
|
ty::Variance::Invariant => stable_mir::mir::Variance::Invariant,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Stable<'tcx> for ty::Movability {
|
||||||
|
type T = stable_mir::ty::Movability;
|
||||||
|
|
||||||
|
fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
|
||||||
|
match self {
|
||||||
|
ty::Movability::Static => stable_mir::ty::Movability::Static,
|
||||||
|
ty::Movability::Movable => stable_mir::ty::Movability::Movable,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@ use rustc_index::IndexVec;
|
|||||||
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
use rustc_infer::infer::canonical::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 },
|
||||||
|
@ -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)
|
||||||
|
164
compiler/stable_mir/src/compiler_interface.rs
Normal file
164
compiler/stable_mir/src/compiler_interface.rs
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
//! Define the interface with the Rust compiler.
|
||||||
|
//!
|
||||||
|
//! StableMIR users should not use any of the items in this module directly.
|
||||||
|
//! These APIs have no stability guarantee.
|
||||||
|
|
||||||
|
use std::cell::Cell;
|
||||||
|
|
||||||
|
use crate::mir::alloc::{AllocId, GlobalAlloc};
|
||||||
|
use crate::mir::mono::{Instance, InstanceDef, StaticDef};
|
||||||
|
use crate::mir::Body;
|
||||||
|
use crate::ty::{
|
||||||
|
AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FnDef, GenericArgs,
|
||||||
|
GenericPredicates, Generics, ImplDef, ImplTrait, LineInfo, RigidTy, Span, TraitDecl, TraitDef,
|
||||||
|
Ty, TyKind,
|
||||||
|
};
|
||||||
|
use crate::{
|
||||||
|
mir, Crate, CrateItem, CrateItems, DefId, Error, Filename, ImplTraitDecls, ItemKind, Symbol,
|
||||||
|
TraitDecls,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// This trait defines the interface between stable_mir and the Rust compiler.
|
||||||
|
/// Do not use this directly.
|
||||||
|
pub trait Context {
|
||||||
|
fn entry_fn(&self) -> Option<CrateItem>;
|
||||||
|
/// Retrieve all items of the local crate that have a MIR associated with them.
|
||||||
|
fn all_local_items(&self) -> CrateItems;
|
||||||
|
fn mir_body(&self, item: DefId) -> mir::Body;
|
||||||
|
fn all_trait_decls(&self) -> TraitDecls;
|
||||||
|
fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl;
|
||||||
|
fn all_trait_impls(&self) -> ImplTraitDecls;
|
||||||
|
fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait;
|
||||||
|
fn generics_of(&self, def_id: DefId) -> Generics;
|
||||||
|
fn predicates_of(&self, def_id: DefId) -> GenericPredicates;
|
||||||
|
fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates;
|
||||||
|
/// Get information about the local crate.
|
||||||
|
fn local_crate(&self) -> Crate;
|
||||||
|
/// Retrieve a list of all external crates.
|
||||||
|
fn external_crates(&self) -> Vec<Crate>;
|
||||||
|
|
||||||
|
/// Find a crate with the given name.
|
||||||
|
fn find_crates(&self, name: &str) -> Vec<Crate>;
|
||||||
|
|
||||||
|
/// Returns the name of given `DefId`
|
||||||
|
fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol;
|
||||||
|
|
||||||
|
/// Returns printable, human readable form of `Span`
|
||||||
|
fn span_to_string(&self, span: Span) -> String;
|
||||||
|
|
||||||
|
/// Return filename from given `Span`, for diagnostic purposes
|
||||||
|
fn get_filename(&self, span: &Span) -> Filename;
|
||||||
|
|
||||||
|
/// Return lines corresponding to this `Span`
|
||||||
|
fn get_lines(&self, span: &Span) -> LineInfo;
|
||||||
|
|
||||||
|
/// Returns the `kind` of given `DefId`
|
||||||
|
fn item_kind(&self, item: CrateItem) -> ItemKind;
|
||||||
|
|
||||||
|
/// Returns whether this is a foreign item.
|
||||||
|
fn is_foreign_item(&self, item: CrateItem) -> bool;
|
||||||
|
|
||||||
|
/// Returns the kind of a given algebraic data type
|
||||||
|
fn adt_kind(&self, def: AdtDef) -> AdtKind;
|
||||||
|
|
||||||
|
/// Returns if the ADT is a box.
|
||||||
|
fn adt_is_box(&self, def: AdtDef) -> bool;
|
||||||
|
|
||||||
|
/// Evaluate constant as a target usize.
|
||||||
|
fn eval_target_usize(&self, cnst: &Const) -> Result<u64, Error>;
|
||||||
|
|
||||||
|
/// Create a target usize constant for the given value.
|
||||||
|
fn usize_to_const(&self, val: u64) -> Result<Const, Error>;
|
||||||
|
|
||||||
|
/// Create a new type from the given kind.
|
||||||
|
fn new_rigid_ty(&self, kind: RigidTy) -> Ty;
|
||||||
|
|
||||||
|
/// Returns the type of given crate item.
|
||||||
|
fn def_ty(&self, item: DefId) -> Ty;
|
||||||
|
|
||||||
|
/// Returns literal value of a const as a string.
|
||||||
|
fn const_literal(&self, cnst: &Const) -> String;
|
||||||
|
|
||||||
|
/// `Span` of an item
|
||||||
|
fn span_of_an_item(&self, def_id: DefId) -> Span;
|
||||||
|
|
||||||
|
/// Obtain the representation of a type.
|
||||||
|
fn ty_kind(&self, ty: Ty) -> TyKind;
|
||||||
|
|
||||||
|
/// Get the body of an Instance.
|
||||||
|
/// FIXME: Monomorphize the body.
|
||||||
|
fn instance_body(&self, instance: InstanceDef) -> Option<Body>;
|
||||||
|
|
||||||
|
/// Get the instance type with generic substitutions applied and lifetimes erased.
|
||||||
|
fn instance_ty(&self, instance: InstanceDef) -> Ty;
|
||||||
|
|
||||||
|
/// Get the instance.
|
||||||
|
fn instance_def_id(&self, instance: InstanceDef) -> DefId;
|
||||||
|
|
||||||
|
/// Get the instance mangled name.
|
||||||
|
fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol;
|
||||||
|
|
||||||
|
/// Convert a non-generic crate item into an instance.
|
||||||
|
/// This function will panic if the item is generic.
|
||||||
|
fn mono_instance(&self, item: CrateItem) -> Instance;
|
||||||
|
|
||||||
|
/// Item requires monomorphization.
|
||||||
|
fn requires_monomorphization(&self, def_id: DefId) -> bool;
|
||||||
|
|
||||||
|
/// Resolve an instance from the given function definition and generic arguments.
|
||||||
|
fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
|
||||||
|
|
||||||
|
/// Resolve an instance for drop_in_place for the given type.
|
||||||
|
fn resolve_drop_in_place(&self, ty: Ty) -> Instance;
|
||||||
|
|
||||||
|
/// Resolve instance for a function pointer.
|
||||||
|
fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>;
|
||||||
|
|
||||||
|
/// Resolve instance for a closure with the requested type.
|
||||||
|
fn resolve_closure(
|
||||||
|
&self,
|
||||||
|
def: ClosureDef,
|
||||||
|
args: &GenericArgs,
|
||||||
|
kind: ClosureKind,
|
||||||
|
) -> Option<Instance>;
|
||||||
|
|
||||||
|
/// Evaluate a static's initializer.
|
||||||
|
fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>;
|
||||||
|
|
||||||
|
/// Retrieve global allocation for the given allocation ID.
|
||||||
|
fn global_alloc(&self, id: AllocId) -> GlobalAlloc;
|
||||||
|
|
||||||
|
/// Retrieve the id for the virtual table.
|
||||||
|
fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>;
|
||||||
|
fn krate(&self, def_id: DefId) -> Crate;
|
||||||
|
fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A thread local variable that stores a pointer to the tables mapping between TyCtxt
|
||||||
|
// datastructures and stable MIR datastructures
|
||||||
|
scoped_thread_local! (static TLV: Cell<*const ()>);
|
||||||
|
|
||||||
|
pub fn run<F, T>(context: &dyn Context, f: F) -> Result<T, Error>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> T,
|
||||||
|
{
|
||||||
|
if TLV.is_set() {
|
||||||
|
Err(Error::from("StableMIR already running"))
|
||||||
|
} else {
|
||||||
|
let ptr: *const () = &context as *const &_ as _;
|
||||||
|
TLV.set(&Cell::new(ptr), || Ok(f()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Execute the given function with access the compiler [Context].
|
||||||
|
///
|
||||||
|
/// I.e., This function will load the current context and calls a function with it.
|
||||||
|
/// Do not nest these, as that will ICE.
|
||||||
|
pub(crate) fn with<R>(f: impl FnOnce(&dyn Context) -> R) -> R {
|
||||||
|
assert!(TLV.is_set());
|
||||||
|
TLV.with(|tlv| {
|
||||||
|
let ptr = tlv.get();
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
f(unsafe { *(ptr as *const &dyn Context) })
|
||||||
|
})
|
||||||
|
}
|
@ -17,38 +17,31 @@
|
|||||||
//! The goal is to eventually be published on
|
//! 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);
|
||||||
|
@ -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),
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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 _;
|
||||||
|
@ -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 ¤t_id > &config.change_id {
|
|
||||||
return Vec::new();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return CONFIG_CHANGE_HISTORY.to_vec();
|
|
||||||
}
|
|
||||||
|
|
||||||
let index =
|
|
||||||
CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap();
|
|
||||||
|
|
||||||
CONFIG_CHANGE_HISTORY
|
|
||||||
.iter()
|
|
||||||
.skip(index + 1) // Skip the current_id and IDs before it
|
|
||||||
.cloned()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes a hash representing the state of a repository/submodule and additional input.
|
/// 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
|
||||||
|
89
src/bootstrap/src/utils/change_tracker.rs
Normal file
89
src/bootstrap/src/utils/change_tracker.rs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//! This module facilitates the tracking system for major changes made to the bootstrap,
|
||||||
|
//! with the goal of keeping developers synchronized with important modifications in
|
||||||
|
//! the bootstrap.
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ChangeInfo {
|
||||||
|
/// Represents the ID of PR caused major change on bootstrap.
|
||||||
|
pub change_id: usize,
|
||||||
|
pub severity: ChangeSeverity,
|
||||||
|
/// Provides a short summary of the change that will guide developers
|
||||||
|
/// on "how to handle/behave" in response to the changes.
|
||||||
|
pub summary: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum ChangeSeverity {
|
||||||
|
/// Used when build configurations continue working as before.
|
||||||
|
Info,
|
||||||
|
/// Used when the default value of an option changes, or support for an option is removed entirely,
|
||||||
|
/// potentially requiring developers to update their build configurations.
|
||||||
|
Warning,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for ChangeSeverity {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
match self {
|
||||||
|
ChangeSeverity::Info => "INFO".to_string(),
|
||||||
|
ChangeSeverity::Warning => "WARNING".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_recent_config_change_ids(current_id: usize) -> Vec<ChangeInfo> {
|
||||||
|
if !CONFIG_CHANGE_HISTORY.iter().any(|config| config.change_id == current_id) {
|
||||||
|
// If the current change-id is greater than the most recent one, return
|
||||||
|
// an empty list (it may be due to switching from a recent branch to an
|
||||||
|
// older one); otherwise, return the full list (assuming the user provided
|
||||||
|
// the incorrect change-id by accident).
|
||||||
|
if let Some(config) = CONFIG_CHANGE_HISTORY.iter().max_by_key(|config| config.change_id) {
|
||||||
|
if ¤t_id > &config.change_id {
|
||||||
|
return Vec::new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CONFIG_CHANGE_HISTORY.to_vec();
|
||||||
|
}
|
||||||
|
|
||||||
|
let index =
|
||||||
|
CONFIG_CHANGE_HISTORY.iter().position(|config| config.change_id == current_id).unwrap();
|
||||||
|
|
||||||
|
CONFIG_CHANGE_HISTORY
|
||||||
|
.iter()
|
||||||
|
.skip(index + 1) // Skip the current_id and IDs before it
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Keeps track of major changes made to the bootstrap configuration.
|
||||||
|
///
|
||||||
|
/// If you make any major changes (such as adding new values or changing default values),
|
||||||
|
/// please ensure adding `ChangeInfo` to the end(because the list must be sorted by the merge date)
|
||||||
|
/// of this list.
|
||||||
|
pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
|
||||||
|
ChangeInfo {
|
||||||
|
change_id: 115898,
|
||||||
|
severity: ChangeSeverity::Info,
|
||||||
|
summary: "Implementation of this change-tracking system. Ignore this.",
|
||||||
|
},
|
||||||
|
ChangeInfo {
|
||||||
|
change_id: 116998,
|
||||||
|
severity: ChangeSeverity::Info,
|
||||||
|
summary: "Removed android-ndk r15 support in favor of android-ndk r25b.",
|
||||||
|
},
|
||||||
|
ChangeInfo {
|
||||||
|
change_id: 117435,
|
||||||
|
severity: ChangeSeverity::Info,
|
||||||
|
summary: "New option `rust.parallel-compiler` added to config.toml.",
|
||||||
|
},
|
||||||
|
ChangeInfo {
|
||||||
|
change_id: 116881,
|
||||||
|
severity: ChangeSeverity::Warning,
|
||||||
|
summary: "Default value of `download-ci-llvm` was changed for `codegen` profile.",
|
||||||
|
},
|
||||||
|
ChangeInfo {
|
||||||
|
change_id: 117813,
|
||||||
|
severity: ChangeSeverity::Info,
|
||||||
|
summary: "Use of the `if-available` value for `download-ci-llvm` is deprecated; prefer using the new `if-unchanged` value.",
|
||||||
|
},
|
||||||
|
];
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
pub(crate) mod cache;
|
pub(crate) mod 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;
|
||||||
|
@ -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"))?;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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();
|
||||||
|
@ -1 +1 @@
|
|||||||
34c5ab9aac327a8a18e18ea37a2468a320d82fb0
|
3668a8af1b81447c4afa1f82f60d7b94b71a549f
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inff32 which cannot be represented in target type `i32`
|
error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32`
|
||||||
--> $DIR/float_to_int_32_inf1.rs:LL:CC
|
--> $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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
9
tests/rustdoc-js/assoc-type-loop.js
Normal file
9
tests/rustdoc-js/assoc-type-loop.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Crash reduction of
|
||||||
|
// https://github.com/rust-lang/rust/issues/118242
|
||||||
|
|
||||||
|
const EXPECTED = [
|
||||||
|
{
|
||||||
|
'query': 't',
|
||||||
|
'correction': null,
|
||||||
|
},
|
||||||
|
];
|
35
tests/rustdoc-js/assoc-type-loop.rs
Normal file
35
tests/rustdoc-js/assoc-type-loop.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#![crate_name="foo"]
|
||||||
|
|
||||||
|
// reduced from sqlx 0.7.3
|
||||||
|
use std::future::Future;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::ops::{Deref, DerefMut};
|
||||||
|
pub enum Error {}
|
||||||
|
pub trait Acquire<'c> {
|
||||||
|
type Database: Database;
|
||||||
|
type Connection: Deref<Target = <Self::Database as Database>::Connection> + DerefMut + Send;
|
||||||
|
}
|
||||||
|
pub trait Database {
|
||||||
|
type Connection: Connection<Database = Self>;
|
||||||
|
}
|
||||||
|
pub trait Connection {
|
||||||
|
type Database: Database;
|
||||||
|
type Options: ConnectionOptions<Connection = Self>;
|
||||||
|
fn begin(
|
||||||
|
&mut self
|
||||||
|
) -> Pin<Box<dyn Future<Output = Result<Transaction<'_, Self::Database>, Error>> + Send + '_>>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
pub trait ConnectionOptions {
|
||||||
|
type Connection: Connection;
|
||||||
|
}
|
||||||
|
pub struct Transaction<'c, DB: Database> {
|
||||||
|
_db: &'c DB,
|
||||||
|
}
|
||||||
|
impl<'t, 'c, DB: Database> Acquire<'t> for &'t mut Transaction<'c, DB>
|
||||||
|
where <DB as Database>::Connection: Send
|
||||||
|
{
|
||||||
|
type Database = DB;
|
||||||
|
type Connection = &'t mut <DB as Database>::Connection;
|
||||||
|
}
|
@ -533,6 +533,12 @@ message = "The Miri subtree was changed"
|
|||||||
cc = ["@rust-lang/miri"]
|
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."
|
||||||
|
Loading…
Reference in New Issue
Block a user