Auto merge of #143434 - matthiaskrgr:rollup-eyr4rcb, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - rust-lang/rust#140643 (Refactor StableMIR) - rust-lang/rust#143286 (Make -Ztrack-diagnostics emit like a note) - rust-lang/rust#143308 (Remove `PointerLike` trait) - rust-lang/rust#143387 (Make __rust_alloc_error_handler_should_panic a function) - rust-lang/rust#143400 (Port `#[rustc_pass_by_value]` to the new attribute system) - rust-lang/rust#143417 (bump termize dep) - rust-lang/rust#143420 (rustc-dev-guide subtree update) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0c4fa2690d
87 changed files with 3913 additions and 2643 deletions
16
Cargo.lock
16
Cargo.lock
|
|
@ -581,7 +581,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"syn 2.0.104",
|
||||
"tempfile",
|
||||
"termize",
|
||||
"termize 0.1.1",
|
||||
"tokio",
|
||||
"toml 0.7.8",
|
||||
"ui_test",
|
||||
|
|
@ -3761,7 +3761,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_json",
|
||||
"termcolor",
|
||||
"termize",
|
||||
"termize 0.2.0",
|
||||
"tracing",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
|
@ -4522,7 +4522,7 @@ dependencies = [
|
|||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
"termize",
|
||||
"termize 0.2.0",
|
||||
"tracing",
|
||||
"windows 0.61.3",
|
||||
]
|
||||
|
|
@ -5294,6 +5294,16 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termize"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8da106d1a19c5b9c53c03311936568a0439926a7607815bd3461139cbab1cc"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "test-float-parse"
|
||||
version = "0.1.0"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_macros::HashStable_Generic;
|
|||
|
||||
use crate::{
|
||||
AbiAlign, Align, BackendRepr, FieldsShape, Float, HasDataLayout, LayoutData, Niche,
|
||||
PointeeInfo, Primitive, Scalar, Size, TargetDataLayout, Variants,
|
||||
PointeeInfo, Primitive, Size, Variants,
|
||||
};
|
||||
|
||||
// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
|
||||
|
|
@ -115,16 +115,6 @@ impl<'a> Layout<'a> {
|
|||
pub fn unadjusted_abi_align(self) -> Align {
|
||||
self.0.0.unadjusted_abi_align
|
||||
}
|
||||
|
||||
/// Whether the layout is from a type that implements [`std::marker::PointerLike`].
|
||||
///
|
||||
/// Currently, that means that the type is pointer-sized, pointer-aligned,
|
||||
/// and has a initialized (non-union), scalar ABI.
|
||||
pub fn is_pointer_like(self, data_layout: &TargetDataLayout) -> bool {
|
||||
self.size() == data_layout.pointer_size
|
||||
&& self.align().abi == data_layout.pointer_align.abi
|
||||
&& matches!(self.backend_repr(), BackendRepr::Scalar(Scalar::Initialized { .. }))
|
||||
}
|
||||
}
|
||||
|
||||
/// The layout of a type, alongside the type itself.
|
||||
|
|
|
|||
|
|
@ -287,6 +287,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[optimize(size|speed)]`
|
||||
Optimize(OptimizeAttr, Span),
|
||||
|
||||
/// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
|
||||
PassByValue(Span),
|
||||
|
||||
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
|
||||
PubTransparent(Span),
|
||||
|
||||
|
|
|
|||
|
|
@ -12,40 +12,43 @@ impl AttributeKind {
|
|||
use EncodeCrossCrate::*;
|
||||
|
||||
match self {
|
||||
// tidy-alphabetical-start
|
||||
Align { .. } => No,
|
||||
AllowConstFnUnstable(..) => No,
|
||||
AllowInternalUnstable(..) => Yes,
|
||||
AsPtr(..) => Yes,
|
||||
BodyStability { .. } => No,
|
||||
Cold(..) => No,
|
||||
Confusables { .. } => Yes,
|
||||
ConstContinue(..) => No,
|
||||
ConstStability { .. } => Yes,
|
||||
ConstStabilityIndirect => No,
|
||||
Deprecation { .. } => Yes,
|
||||
DocComment { .. } => Yes,
|
||||
ExportName { .. } => Yes,
|
||||
Inline(..) => No,
|
||||
LinkSection { .. } => No,
|
||||
MacroTransparency(..) => Yes,
|
||||
Repr(..) => No,
|
||||
Stability { .. } => Yes,
|
||||
Cold(..) => No,
|
||||
ConstContinue(..) => No,
|
||||
LinkName { .. } => Yes,
|
||||
LinkSection { .. } => No,
|
||||
LoopMatch(..) => No,
|
||||
MacroTransparency(..) => Yes,
|
||||
MayDangle(..) => No,
|
||||
MustUse { .. } => Yes,
|
||||
Naked(..) => No,
|
||||
NoImplicitPrelude(..) => No,
|
||||
NoMangle(..) => No,
|
||||
Optimize(..) => No,
|
||||
PassByValue(..) => Yes,
|
||||
PubTransparent(..) => Yes,
|
||||
Repr(..) => No,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcObjectLifetimeDefault => No,
|
||||
SkipDuringMethodDispatch { .. } => No,
|
||||
Stability { .. } => Yes,
|
||||
TargetFeature(..) => No,
|
||||
TrackCaller(..) => Yes,
|
||||
Used { .. } => No,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,3 +17,10 @@ impl<S: Stage> NoArgsAttributeParser<S> for PubTransparentParser {
|
|||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent;
|
||||
}
|
||||
|
||||
pub(crate) struct PassByValueParser;
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for PassByValueParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_pass_by_value];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const CREATE: fn(Span) -> AttributeKind = AttributeKind::PassByValue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ use crate::attributes::confusables::ConfusablesParser;
|
|||
use crate::attributes::deprecation::DeprecationParser;
|
||||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
use crate::attributes::link_attrs::{LinkNameParser, LinkSectionParser};
|
||||
use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
|
||||
use crate::attributes::lint_helpers::{AsPtrParser, PassByValueParser, PubTransparentParser};
|
||||
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
|
||||
use crate::attributes::must_use::MustUseParser;
|
||||
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
|
||||
|
|
@ -144,6 +144,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<MayDangleParser>>,
|
||||
Single<WithoutArgs<NoImplicitPreludeParser>>,
|
||||
Single<WithoutArgs<NoMangleParser>>,
|
||||
Single<WithoutArgs<PassByValueParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
|||
|
|
@ -84,19 +84,34 @@ fn codegen_inner(
|
|||
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
|
||||
);
|
||||
|
||||
let data_id = module
|
||||
.declare_data(
|
||||
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||
Linkage::Export,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let mut data = DataDescription::new();
|
||||
data.set_align(1);
|
||||
let val = oom_strategy.should_panic();
|
||||
data.define(Box::new([val]));
|
||||
module.define_data(data_id, &data).unwrap();
|
||||
{
|
||||
let sig = Signature {
|
||||
call_conv: module.target_config().default_call_conv,
|
||||
params: vec![],
|
||||
returns: vec![AbiParam::new(types::I8)],
|
||||
};
|
||||
let func_id = module
|
||||
.declare_function(
|
||||
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||
Linkage::Export,
|
||||
&sig,
|
||||
)
|
||||
.unwrap();
|
||||
let mut ctx = Context::new();
|
||||
ctx.func.signature = sig;
|
||||
{
|
||||
let mut func_ctx = FunctionBuilderContext::new();
|
||||
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
|
||||
|
||||
let block = bcx.create_block();
|
||||
bcx.switch_to_block(block);
|
||||
let value = bcx.ins().iconst(types::I8, oom_strategy.should_panic() as i64);
|
||||
bcx.ins().return_(&[value]);
|
||||
bcx.seal_all_blocks();
|
||||
bcx.finalize();
|
||||
}
|
||||
module.define_function(func_id, &mut ctx).unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
let sig = Signature {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{FnAttribute, VarAttribute};
|
||||
use gccjit::FnAttribute;
|
||||
use gccjit::{Context, FunctionType, RValue, ToRValue, Type};
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||
alloc_error_handler_name, default_fn_name, global_fn_name,
|
||||
|
|
@ -71,15 +71,13 @@ pub(crate) unsafe fn codegen(
|
|||
None,
|
||||
);
|
||||
|
||||
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
|
||||
let global = context.new_global(None, GlobalKind::Exported, i8, name);
|
||||
#[cfg(feature = "master")]
|
||||
global.add_attribute(VarAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
tcx.sess.default_visibility(),
|
||||
)));
|
||||
let value = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let value = context.new_rvalue_from_int(i8, value as i32);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
create_const_value_function(
|
||||
tcx,
|
||||
context,
|
||||
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||
i8,
|
||||
context.new_rvalue_from_int(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as i32),
|
||||
);
|
||||
|
||||
create_wrapper_function(
|
||||
tcx,
|
||||
|
|
@ -91,6 +89,30 @@ pub(crate) unsafe fn codegen(
|
|||
);
|
||||
}
|
||||
|
||||
fn create_const_value_function(
|
||||
tcx: TyCtxt<'_>,
|
||||
context: &Context<'_>,
|
||||
name: &str,
|
||||
output: Type<'_>,
|
||||
value: RValue<'_>,
|
||||
) {
|
||||
let func = context.new_function(None, FunctionType::Exported, output, &[], name, false);
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
func.add_attribute(FnAttribute::Visibility(symbol_visibility_to_gcc(
|
||||
tcx.sess.default_visibility(),
|
||||
)));
|
||||
|
||||
func.add_attribute(FnAttribute::AlwaysInline);
|
||||
|
||||
if tcx.sess.must_emit_unwind_tables() {
|
||||
// TODO(antoyo): emit unwind tables.
|
||||
}
|
||||
|
||||
let block = func.new_block("entry");
|
||||
block.end_with_return(None, value);
|
||||
}
|
||||
|
||||
fn create_wrapper_function(
|
||||
tcx: TyCtxt<'_>,
|
||||
context: &Context<'_>,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc_symbol_mangling::mangle_internal_symbol;
|
|||
|
||||
use crate::builder::SBuilder;
|
||||
use crate::declare::declare_simple_fn;
|
||||
use crate::llvm::{self, False, True, Type};
|
||||
use crate::llvm::{self, False, True, Type, Value};
|
||||
use crate::{SimpleCx, attributes, debuginfo};
|
||||
|
||||
pub(crate) unsafe fn codegen(
|
||||
|
|
@ -73,13 +73,14 @@ pub(crate) unsafe fn codegen(
|
|||
);
|
||||
|
||||
unsafe {
|
||||
// __rust_alloc_error_handler_should_panic
|
||||
let name = mangle_internal_symbol(tcx, OomStrategy::SYMBOL);
|
||||
let ll_g = cx.declare_global(&name, i8);
|
||||
llvm::set_visibility(ll_g, llvm::Visibility::from_generic(tcx.sess.default_visibility()));
|
||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||
llvm::set_initializer(ll_g, llval);
|
||||
// __rust_alloc_error_handler_should_panic_v2
|
||||
create_const_value_function(
|
||||
tcx,
|
||||
&cx,
|
||||
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||
&i8,
|
||||
&llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, False),
|
||||
);
|
||||
|
||||
// __rust_no_alloc_shim_is_unstable_v2
|
||||
create_wrapper_function(
|
||||
|
|
@ -100,6 +101,34 @@ pub(crate) unsafe fn codegen(
|
|||
}
|
||||
}
|
||||
|
||||
fn create_const_value_function(
|
||||
tcx: TyCtxt<'_>,
|
||||
cx: &SimpleCx<'_>,
|
||||
name: &str,
|
||||
output: &Type,
|
||||
value: &Value,
|
||||
) {
|
||||
let ty = cx.type_func(&[], output);
|
||||
let llfn = declare_simple_fn(
|
||||
&cx,
|
||||
name,
|
||||
llvm::CallConv::CCallConv,
|
||||
llvm::UnnamedAddr::Global,
|
||||
llvm::Visibility::from_generic(tcx.sess.default_visibility()),
|
||||
ty,
|
||||
);
|
||||
|
||||
attributes::apply_to_llfn(
|
||||
llfn,
|
||||
llvm::AttributePlace::Function,
|
||||
&[llvm::AttributeKind::AlwaysInline.create_attr(cx.llcx)],
|
||||
);
|
||||
|
||||
let llbb = unsafe { llvm::LLVMAppendBasicBlockInContext(cx.llcx, llfn, c"entry".as_ptr()) };
|
||||
let mut bx = SBuilder::build(&cx, llbb);
|
||||
bx.ret(value);
|
||||
}
|
||||
|
||||
fn create_wrapper_function(
|
||||
tcx: TyCtxt<'_>,
|
||||
cx: &SimpleCx<'_>,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ rustc_type_ir = { path = "../rustc_type_ir" }
|
|||
serde = { version = "1.0.125", features = [ "derive" ] }
|
||||
serde_json = "1.0.59"
|
||||
termcolor = "1.2.0"
|
||||
termize = "0.1.1"
|
||||
termize = "0.2"
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -417,6 +417,15 @@ impl DiagInner {
|
|||
self.args = std::mem::take(&mut self.reserved_args);
|
||||
}
|
||||
|
||||
pub fn emitted_at_sub_diag(&self) -> Subdiag {
|
||||
let track = format!("-Ztrack-diagnostics: created at {}", self.emitted_at);
|
||||
Subdiag {
|
||||
level: crate::Level::Note,
|
||||
messages: vec![(DiagMessage::Str(Cow::Owned(track)), Style::NoStyle)],
|
||||
span: MultiSpan::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Fields used for Hash, and PartialEq trait.
|
||||
fn keys(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ use rustc_span::{FileLines, FileName, SourceFile, Span, char_width, str_width};
|
|||
use termcolor::{Buffer, BufferWriter, Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
|
||||
use tracing::{debug, instrument, trace, warn};
|
||||
|
||||
use crate::diagnostic::DiagLocation;
|
||||
use crate::registry::Registry;
|
||||
use crate::snippet::{
|
||||
Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
|
||||
|
|
@ -505,6 +504,10 @@ impl Emitter for HumanEmitter {
|
|||
fn emit_diagnostic(&mut self, mut diag: DiagInner, _registry: &Registry) {
|
||||
let fluent_args = to_fluent_args(diag.args.iter());
|
||||
|
||||
if self.track_diagnostics && diag.span.has_primary_spans() && !diag.span.is_dummy() {
|
||||
diag.children.insert(0, diag.emitted_at_sub_diag());
|
||||
}
|
||||
|
||||
let mut suggestions = diag.suggestions.unwrap_tag();
|
||||
self.primary_span_formatted(&mut diag.span, &mut suggestions, &fluent_args);
|
||||
|
||||
|
|
@ -523,7 +526,6 @@ impl Emitter for HumanEmitter {
|
|||
&diag.span,
|
||||
&diag.children,
|
||||
&suggestions,
|
||||
self.track_diagnostics.then_some(&diag.emitted_at),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1468,7 +1470,6 @@ impl HumanEmitter {
|
|||
level: &Level,
|
||||
max_line_num_len: usize,
|
||||
is_secondary: bool,
|
||||
emitted_at: Option<&DiagLocation>,
|
||||
is_cont: bool,
|
||||
) -> io::Result<()> {
|
||||
let mut buffer = StyledBuffer::new();
|
||||
|
|
@ -1978,12 +1979,6 @@ impl HumanEmitter {
|
|||
trace!("buffer: {:#?}", buffer.render());
|
||||
}
|
||||
|
||||
if let Some(tracked) = emitted_at {
|
||||
let track = format!("-Ztrack-diagnostics: created at {tracked}");
|
||||
let len = buffer.num_lines();
|
||||
buffer.append(len, &track, Style::NoStyle);
|
||||
}
|
||||
|
||||
// final step: take our styled buffer, render it, then output it
|
||||
emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
|
||||
|
||||
|
|
@ -2478,7 +2473,6 @@ impl HumanEmitter {
|
|||
span: &MultiSpan,
|
||||
children: &[Subdiag],
|
||||
suggestions: &[CodeSuggestion],
|
||||
emitted_at: Option<&DiagLocation>,
|
||||
) {
|
||||
let max_line_num_len = if self.ui_testing {
|
||||
ANONYMIZED_LINE_NUM.len()
|
||||
|
|
@ -2495,7 +2489,6 @@ impl HumanEmitter {
|
|||
level,
|
||||
max_line_num_len,
|
||||
false,
|
||||
emitted_at,
|
||||
!children.is_empty()
|
||||
|| suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden),
|
||||
) {
|
||||
|
|
@ -2541,7 +2534,6 @@ impl HumanEmitter {
|
|||
&child.level,
|
||||
max_line_num_len,
|
||||
true,
|
||||
None,
|
||||
!should_close,
|
||||
) {
|
||||
panic!("failed to emit error: {err}");
|
||||
|
|
@ -2561,7 +2553,6 @@ impl HumanEmitter {
|
|||
&Level::Help,
|
||||
max_line_num_len,
|
||||
true,
|
||||
None,
|
||||
// FIXME: this needs to account for the suggestion type,
|
||||
// some don't take any space.
|
||||
i + 1 != suggestions.len(),
|
||||
|
|
|
|||
|
|
@ -372,13 +372,16 @@ impl Diagnostic {
|
|||
};
|
||||
let level = diag.level.to_str();
|
||||
let spans = DiagnosticSpan::from_multispan(&diag.span, &args, je);
|
||||
let children = diag
|
||||
let mut children: Vec<Diagnostic> = diag
|
||||
.children
|
||||
.iter()
|
||||
.map(|c| Diagnostic::from_sub_diagnostic(c, &args, je))
|
||||
.chain(sugg)
|
||||
.collect();
|
||||
|
||||
if je.track_diagnostics && diag.span.has_primary_spans() && !diag.span.is_dummy() {
|
||||
children
|
||||
.insert(0, Diagnostic::from_sub_diagnostic(&diag.emitted_at_sub_diag(), &args, je));
|
||||
}
|
||||
let buf = BufWriter::default();
|
||||
let mut dst: Destination = Box::new(buf.clone());
|
||||
let short = je.json_rendered.short();
|
||||
|
|
|
|||
|
|
@ -367,8 +367,6 @@ language_item_table! {
|
|||
TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
|
||||
TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
|
||||
|
||||
PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
||||
ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ pub(super) fn check_trait<'tcx>(
|
|||
checker.check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)?;
|
||||
checker
|
||||
.check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
|
||||
checker.check(lang_items.pointer_like(), visit_implementation_of_pointer_like)?;
|
||||
checker.check(
|
||||
lang_items.coerce_pointee_validated_trait(),
|
||||
visit_implementation_of_coerce_pointee_validity,
|
||||
|
|
@ -707,104 +706,6 @@ fn infringing_fields_error<'tcx>(
|
|||
err.emit()
|
||||
}
|
||||
|
||||
fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
let tcx = checker.tcx;
|
||||
let typing_env = ty::TypingEnv::non_body_analysis(tcx, checker.impl_def_id);
|
||||
let impl_span = tcx.def_span(checker.impl_def_id);
|
||||
let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
|
||||
|
||||
let is_permitted_primitive = match *self_ty.kind() {
|
||||
ty::Adt(def, _) => def.is_box(),
|
||||
ty::Uint(..) | ty::Int(..) | ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
if is_permitted_primitive
|
||||
&& let Ok(layout) = tcx.layout_of(typing_env.as_query_input(self_ty))
|
||||
&& layout.layout.is_pointer_like(&tcx.data_layout)
|
||||
{
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let why_disqualified = match *self_ty.kind() {
|
||||
// If an ADT is repr(transparent)
|
||||
ty::Adt(self_ty_def, args) => {
|
||||
if self_ty_def.repr().transparent() {
|
||||
// FIXME(compiler-errors): This should and could be deduplicated into a query.
|
||||
// Find the nontrivial field.
|
||||
let adt_typing_env = ty::TypingEnv::non_body_analysis(tcx, self_ty_def.did());
|
||||
let nontrivial_field = self_ty_def.all_fields().find(|field_def| {
|
||||
let field_ty = tcx.type_of(field_def.did).instantiate_identity();
|
||||
!tcx.layout_of(adt_typing_env.as_query_input(field_ty))
|
||||
.is_ok_and(|layout| layout.layout.is_1zst())
|
||||
});
|
||||
|
||||
if let Some(nontrivial_field) = nontrivial_field {
|
||||
// Check that the nontrivial field implements `PointerLike`.
|
||||
let nontrivial_field_ty = nontrivial_field.ty(tcx, args);
|
||||
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
ocx.register_bound(
|
||||
ObligationCause::misc(impl_span, checker.impl_def_id),
|
||||
param_env,
|
||||
nontrivial_field_ty,
|
||||
tcx.require_lang_item(LangItem::PointerLike, impl_span),
|
||||
);
|
||||
// FIXME(dyn-star): We should regionck this implementation.
|
||||
if ocx.select_all_or_error().is_empty() {
|
||||
return Ok(());
|
||||
} else {
|
||||
format!(
|
||||
"the field `{field_name}` of {descr} `{self_ty}` \
|
||||
does not implement `PointerLike`",
|
||||
field_name = nontrivial_field.name,
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
} else {
|
||||
format!(
|
||||
"the {descr} `{self_ty}` is `repr(transparent)`, \
|
||||
but does not have a non-trivial field (it is zero-sized)",
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
} else if self_ty_def.is_box() {
|
||||
// If we got here, then the `layout.is_pointer_like()` check failed
|
||||
// and this box is not a thin pointer.
|
||||
|
||||
String::from("boxes of dynamically-sized types are too large to be `PointerLike`")
|
||||
} else {
|
||||
format!(
|
||||
"the {descr} `{self_ty}` is not `repr(transparent)`",
|
||||
descr = self_ty_def.descr()
|
||||
)
|
||||
}
|
||||
}
|
||||
ty::Ref(..) => {
|
||||
// If we got here, then the `layout.is_pointer_like()` check failed
|
||||
// and this reference is not a thin pointer.
|
||||
String::from("references to dynamically-sized types are too large to be `PointerLike`")
|
||||
}
|
||||
ty::Dynamic(..) | ty::Foreign(..) => {
|
||||
String::from("types of dynamic or unknown size may not implement `PointerLike`")
|
||||
}
|
||||
_ => {
|
||||
// This is a white lie; it is true everywhere outside the standard library.
|
||||
format!("only user-defined sized types are eligible for `impl PointerLike`")
|
||||
}
|
||||
};
|
||||
|
||||
Err(tcx
|
||||
.dcx()
|
||||
.struct_span_err(
|
||||
impl_span,
|
||||
"implementation must be applied to type that has the same ABI as a pointer, \
|
||||
or is `repr(transparent)` and whose field is `PointerLike`",
|
||||
)
|
||||
.with_note(why_disqualified)
|
||||
.emit())
|
||||
}
|
||||
|
||||
fn visit_implementation_of_coerce_pointee_validity(
|
||||
checker: &Checker<'_>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use rustc_attr_data_structures::{AttributeKind, find_attr};
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind};
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::lints::PassByValueDiag;
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
|
|
@ -45,14 +45,16 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
|
|||
fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<String> {
|
||||
if let TyKind::Path(QPath::Resolved(_, path)) = &ty.kind {
|
||||
match path.res {
|
||||
Res::Def(_, def_id) if cx.tcx.has_attr(def_id, sym::rustc_pass_by_value) => {
|
||||
Res::Def(_, def_id)
|
||||
if find_attr!(cx.tcx.get_all_attrs(def_id), AttributeKind::PassByValue(_)) =>
|
||||
{
|
||||
let name = cx.tcx.item_ident(def_id);
|
||||
let path_segment = path.segments.last().unwrap();
|
||||
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
|
||||
}
|
||||
Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
|
||||
if let ty::Adt(adt, args) = cx.tcx.type_of(did).instantiate_identity().kind() {
|
||||
if cx.tcx.has_attr(adt.did(), sym::rustc_pass_by_value) {
|
||||
if find_attr!(cx.tcx.get_all_attrs(adt.did()), AttributeKind::PassByValue(_)) {
|
||||
return Some(cx.tcx.def_path_str_with_args(adt.did(), args));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1149,12 +1149,16 @@ impl<'tcx> TypingEnv<'tcx> {
|
|||
{
|
||||
// FIXME(#132279): We should assert that the value does not contain any placeholders
|
||||
// as these placeholders are also local to the current inference context. However, we
|
||||
// currently use pseudo-canonical queries in the trait solver which replaces params with
|
||||
// placeholders. We should also simply not use pseudo-canonical queries in the trait
|
||||
// solver, at which point we can readd this assert. As of writing this comment, this is
|
||||
// only used by `fn layout_is_pointer_like` when calling `layout_of`.
|
||||
// currently use pseudo-canonical queries in the trait solver, which replaces params
|
||||
// with placeholders during canonicalization. We should also simply not use pseudo-
|
||||
// canonical queries in the trait solver, at which point we can readd this assert.
|
||||
//
|
||||
// debug_assert!(!value.has_placeholders());
|
||||
// As of writing this comment, this is only used when normalizing consts that mention
|
||||
// params.
|
||||
/* debug_assert!(
|
||||
!value.has_placeholders(),
|
||||
"{value:?} which has placeholder shouldn't be pseudo-canonicalized"
|
||||
); */
|
||||
PseudoCanonicalInput { typing_env: self, value }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -293,6 +293,7 @@ fn emit_malformed_attribute(
|
|||
| sym::rustc_force_inline
|
||||
| sym::rustc_confusables
|
||||
| sym::rustc_skip_during_method_dispatch
|
||||
| sym::rustc_pass_by_value
|
||||
| sym::repr
|
||||
| sym::align
|
||||
| sym::deprecated
|
||||
|
|
|
|||
|
|
@ -221,6 +221,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => {
|
||||
self.check_used(*attr_span, target, span);
|
||||
}
|
||||
&Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => {
|
||||
self.check_pass_by_value(attr_span, span, target)
|
||||
}
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
match attr.path().as_slice() {
|
||||
|
|
@ -283,7 +286,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target),
|
||||
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
|
||||
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
|
||||
[sym::rustc_pass_by_value, ..] => self.check_pass_by_value(attr, span, target),
|
||||
[sym::rustc_allow_incoherent_impl, ..] => {
|
||||
self.check_allow_incoherent_impl(attr, span, target)
|
||||
}
|
||||
|
|
@ -1465,11 +1467,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
/// Warns against some misuses of `#[pass_by_value]`
|
||||
fn check_pass_by_value(&self, attr: &Attribute, span: Span, target: Target) {
|
||||
fn check_pass_by_value(&self, attr_span: Span, span: Span, target: Target) {
|
||||
match target {
|
||||
Target::Struct | Target::Enum | Target::TyAlias => {}
|
||||
_ => {
|
||||
self.dcx().emit_err(errors::PassByValue { attr_span: attr.span(), span });
|
||||
self.dcx().emit_err(errors::PassByValue { attr_span, span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ rustc_macros = { path = "../rustc_macros" }
|
|||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
termize = "0.1.1"
|
||||
termize = "0.2"
|
||||
tracing = "0.1"
|
||||
# tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
|
|
@ -3340,7 +3340,7 @@ pub enum OomStrategy {
|
|||
}
|
||||
|
||||
impl OomStrategy {
|
||||
pub const SYMBOL: &'static str = "__rust_alloc_error_handler_should_panic";
|
||||
pub const SYMBOL: &'static str = "__rust_alloc_error_handler_should_panic_v2";
|
||||
|
||||
pub fn should_panic(self) -> u8 {
|
||||
match self {
|
||||
|
|
|
|||
|
|
@ -4,28 +4,17 @@
|
|||
//! until stable MIR is complete.
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Index;
|
||||
|
||||
use rustc_data_structures::fx;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_middle::mir::interpret::AllocId;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::{CrateNum, DefId};
|
||||
use rustc_span::def_id::CrateNum;
|
||||
use scoped_tls::scoped_thread_local;
|
||||
use stable_mir::Error;
|
||||
use stable_mir::abi::Layout;
|
||||
use stable_mir::compiler_interface::SmirInterface;
|
||||
use stable_mir::ty::IndexedVal;
|
||||
use stable_mir::unstable::{RustcInternal, Stable};
|
||||
|
||||
use crate::rustc_smir::context::SmirCtxt;
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use crate::rustc_smir::{Bridge, SmirContainer, Tables};
|
||||
use crate::stable_mir;
|
||||
|
||||
mod internal;
|
||||
pub mod pretty;
|
||||
|
||||
/// Convert an internal Rust compiler item into its stable counterpart, if one exists.
|
||||
|
|
@ -40,7 +29,7 @@ pub mod pretty;
|
|||
///
|
||||
/// This function will panic if StableMIR has not been properly initialized.
|
||||
pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T {
|
||||
with_tables(|tables| item.stable(tables))
|
||||
with_container(|tables, cx| item.stable(tables, cx))
|
||||
}
|
||||
|
||||
/// Convert a stable item into its internal Rust compiler counterpart, if one exists.
|
||||
|
|
@ -59,134 +48,9 @@ where
|
|||
S: RustcInternal,
|
||||
{
|
||||
// The tcx argument ensures that the item won't outlive the type context.
|
||||
with_tables(|tables| item.internal(tables, tcx))
|
||||
}
|
||||
|
||||
impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
|
||||
type Output = DefId;
|
||||
|
||||
#[inline(always)]
|
||||
fn index(&self, index: stable_mir::DefId) -> &Self::Output {
|
||||
&self.def_ids[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Index<stable_mir::ty::Span> for Tables<'tcx> {
|
||||
type Output = Span;
|
||||
|
||||
#[inline(always)]
|
||||
fn index(&self, index: stable_mir::ty::Span) -> &Self::Output {
|
||||
&self.spans[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Tables<'tcx> {
|
||||
pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem {
|
||||
stable_mir::CrateItem(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn adt_def(&mut self, did: DefId) -> stable_mir::ty::AdtDef {
|
||||
stable_mir::ty::AdtDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn foreign_module_def(&mut self, did: DefId) -> stable_mir::ty::ForeignModuleDef {
|
||||
stable_mir::ty::ForeignModuleDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn foreign_def(&mut self, did: DefId) -> stable_mir::ty::ForeignDef {
|
||||
stable_mir::ty::ForeignDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn fn_def(&mut self, did: DefId) -> stable_mir::ty::FnDef {
|
||||
stable_mir::ty::FnDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn closure_def(&mut self, did: DefId) -> stable_mir::ty::ClosureDef {
|
||||
stable_mir::ty::ClosureDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn coroutine_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineDef {
|
||||
stable_mir::ty::CoroutineDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn coroutine_closure_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineClosureDef {
|
||||
stable_mir::ty::CoroutineClosureDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn alias_def(&mut self, did: DefId) -> stable_mir::ty::AliasDef {
|
||||
stable_mir::ty::AliasDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn param_def(&mut self, did: DefId) -> stable_mir::ty::ParamDef {
|
||||
stable_mir::ty::ParamDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn br_named_def(&mut self, did: DefId) -> stable_mir::ty::BrNamedDef {
|
||||
stable_mir::ty::BrNamedDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn trait_def(&mut self, did: DefId) -> stable_mir::ty::TraitDef {
|
||||
stable_mir::ty::TraitDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn generic_def(&mut self, did: DefId) -> stable_mir::ty::GenericDef {
|
||||
stable_mir::ty::GenericDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn const_def(&mut self, did: DefId) -> stable_mir::ty::ConstDef {
|
||||
stable_mir::ty::ConstDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn impl_def(&mut self, did: DefId) -> stable_mir::ty::ImplDef {
|
||||
stable_mir::ty::ImplDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn region_def(&mut self, did: DefId) -> stable_mir::ty::RegionDef {
|
||||
stable_mir::ty::RegionDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn coroutine_witness_def(&mut self, did: DefId) -> stable_mir::ty::CoroutineWitnessDef {
|
||||
stable_mir::ty::CoroutineWitnessDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn assoc_def(&mut self, did: DefId) -> stable_mir::ty::AssocDef {
|
||||
stable_mir::ty::AssocDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn opaque_def(&mut self, did: DefId) -> stable_mir::ty::OpaqueDef {
|
||||
stable_mir::ty::OpaqueDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov {
|
||||
stable_mir::ty::Prov(self.create_alloc_id(aid))
|
||||
}
|
||||
|
||||
pub(crate) fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
|
||||
self.def_ids.create_or_fetch(did)
|
||||
}
|
||||
|
||||
pub(crate) fn create_alloc_id(&mut self, aid: AllocId) -> stable_mir::mir::alloc::AllocId {
|
||||
self.alloc_ids.create_or_fetch(aid)
|
||||
}
|
||||
|
||||
pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span {
|
||||
self.spans.create_or_fetch(span)
|
||||
}
|
||||
|
||||
pub(crate) fn instance_def(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) -> stable_mir::mir::mono::InstanceDef {
|
||||
self.instances.create_or_fetch(instance)
|
||||
}
|
||||
|
||||
pub(crate) fn static_def(&mut self, did: DefId) -> stable_mir::mir::mono::StaticDef {
|
||||
stable_mir::mir::mono::StaticDef(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub(crate) fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> Layout {
|
||||
self.layouts.create_or_fetch(layout)
|
||||
}
|
||||
// See https://github.com/rust-lang/rust/pull/120128/commits/9aace6723572438a94378451793ca37deb768e72
|
||||
// for more details.
|
||||
with_container(|tables, _| item.internal(tables, tcx))
|
||||
}
|
||||
|
||||
pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
|
||||
|
|
@ -197,25 +61,28 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
|
|||
// datastructures and stable MIR datastructures
|
||||
scoped_thread_local! (static TLV: Cell<*const ()>);
|
||||
|
||||
pub(crate) fn init<'tcx, F, T>(cx: &SmirCtxt<'tcx>, f: F) -> T
|
||||
pub(crate) fn init<'tcx, F, T, B: Bridge>(container: &SmirContainer<'tcx, B>, f: F) -> T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
assert!(!TLV.is_set());
|
||||
let ptr = cx as *const _ as *const ();
|
||||
let ptr = container as *const _ as *const ();
|
||||
TLV.set(&Cell::new(ptr), || f())
|
||||
}
|
||||
|
||||
/// Loads the current context and calls a function with it.
|
||||
/// Do not nest these, as that will ICE.
|
||||
pub(crate) fn with_tables<R>(f: impl for<'tcx> FnOnce(&mut Tables<'tcx>) -> R) -> R {
|
||||
pub(crate) fn with_container<R, B: Bridge>(
|
||||
f: impl for<'tcx> FnOnce(&mut Tables<'tcx, B>, &SmirCtxt<'tcx, B>) -> R,
|
||||
) -> R {
|
||||
assert!(TLV.is_set());
|
||||
TLV.with(|tlv| {
|
||||
let ptr = tlv.get();
|
||||
assert!(!ptr.is_null());
|
||||
let context = ptr as *const SmirCtxt<'_>;
|
||||
let mut tables = unsafe { (*context).0.borrow_mut() };
|
||||
f(&mut *tables)
|
||||
let container = ptr as *const SmirContainer<'_, B>;
|
||||
let mut tables = unsafe { (*container).tables.borrow_mut() };
|
||||
let cx = unsafe { (*container).cx.borrow() };
|
||||
f(&mut *tables, &*cx)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -223,23 +90,10 @@ pub fn run<F, T>(tcx: TyCtxt<'_>, f: F) -> Result<T, Error>
|
|||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
let tables = SmirCtxt(RefCell::new(Tables {
|
||||
tcx,
|
||||
def_ids: IndexMap::default(),
|
||||
alloc_ids: IndexMap::default(),
|
||||
spans: IndexMap::default(),
|
||||
types: IndexMap::default(),
|
||||
instances: IndexMap::default(),
|
||||
ty_consts: IndexMap::default(),
|
||||
mir_consts: IndexMap::default(),
|
||||
layouts: IndexMap::default(),
|
||||
}));
|
||||
let smir_cx = RefCell::new(SmirCtxt::new(tcx));
|
||||
let container = SmirContainer { tables: RefCell::new(Tables::default()), cx: smir_cx };
|
||||
|
||||
let interface = SmirInterface { cx: tables };
|
||||
|
||||
// Pass the `SmirInterface` to compiler_interface::run
|
||||
// and initialize the rustc-specific TLS with tables.
|
||||
stable_mir::compiler_interface::run(&interface, || init(&interface.cx, f))
|
||||
stable_mir::compiler_interface::run(&container, || init(&container, f))
|
||||
}
|
||||
|
||||
/// Instantiate and run the compiler with the provided arguments and callback.
|
||||
|
|
@ -417,43 +271,3 @@ macro_rules! run_driver {
|
|||
StableMir::new($callback).run($args)
|
||||
}};
|
||||
}
|
||||
|
||||
/// Similar to rustc's `FxIndexMap`, `IndexMap` with extra
|
||||
/// safety features added.
|
||||
pub struct IndexMap<K, V> {
|
||||
index_map: fx::FxIndexMap<K, V>,
|
||||
}
|
||||
|
||||
impl<K, V> Default for IndexMap<K, V> {
|
||||
fn default() -> Self {
|
||||
Self { index_map: FxIndexMap::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
|
||||
pub fn create_or_fetch(&mut self, key: K) -> V {
|
||||
let len = self.index_map.len();
|
||||
let v = self.index_map.entry(key).or_insert(V::to_val(len));
|
||||
*v
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V>
|
||||
for IndexMap<K, V>
|
||||
{
|
||||
type Output = K;
|
||||
|
||||
fn index(&self, index: V) -> &Self::Output {
|
||||
let (k, v) = self.index_map.get_index(index.to_index()).unwrap();
|
||||
assert_eq!(*v, index, "Provided value doesn't match with indexed value");
|
||||
k
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait used to translate a stable construct to its rustc counterpart.
|
||||
///
|
||||
/// This is basically a mirror of [crate::rustc_smir::Stable].
|
||||
pub trait RustcInternal {
|
||||
type T<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,102 +1,82 @@
|
|||
use rustc_abi::{Align, Size};
|
||||
use rustc_middle::mir::ConstValue;
|
||||
use rustc_middle::mir::interpret::{AllocInit, AllocRange, Pointer, alloc_range};
|
||||
use stable_mir::Error;
|
||||
use stable_mir::mir::Mutability;
|
||||
use stable_mir::ty::{Allocation, ProvenanceMap};
|
||||
//! Internal memory allocator implementation for StableMIR.
|
||||
//!
|
||||
//! This module handles all direct interactions with rustc queries and performs
|
||||
//! the actual memory allocations. The stable interface in `stable_mir::alloc`
|
||||
//! delegates all query-related operations to this implementation.
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use crate::stable_mir;
|
||||
use rustc_abi::{Size, TyAndLayout};
|
||||
use rustc_middle::mir::interpret::{
|
||||
AllocId, AllocInit, AllocRange, Allocation, ConstAllocation, Pointer, Scalar, alloc_range,
|
||||
};
|
||||
use rustc_middle::ty::{Ty, layout};
|
||||
|
||||
/// Creates new empty `Allocation` from given `Align`.
|
||||
fn new_empty_allocation(align: Align) -> Allocation {
|
||||
Allocation {
|
||||
bytes: Vec::new(),
|
||||
provenance: ProvenanceMap { ptrs: Vec::new() },
|
||||
align: align.bytes(),
|
||||
mutability: Mutability::Not,
|
||||
}
|
||||
use super::{SmirCtxt, Tables};
|
||||
use crate::rustc_smir::bridge::Allocation as _;
|
||||
use crate::rustc_smir::{Bridge, SmirError};
|
||||
|
||||
pub fn create_ty_and_layout<'tcx, B: Bridge>(
|
||||
cx: &SmirCtxt<'tcx, B>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Result<TyAndLayout<'tcx, Ty<'tcx>>, &'tcx layout::LayoutError<'tcx>> {
|
||||
use crate::rustc_smir::context::SmirTypingEnv;
|
||||
cx.tcx.layout_of(cx.fully_monomorphized().as_query_input(ty))
|
||||
}
|
||||
|
||||
// We need this method instead of a Stable implementation
|
||||
// because we need to get `Ty` of the const we are trying to create, to do that
|
||||
// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
|
||||
#[allow(rustc::usage_of_qualified_ty)]
|
||||
pub(crate) fn new_allocation<'tcx>(
|
||||
ty: rustc_middle::ty::Ty<'tcx>,
|
||||
const_value: ConstValue<'tcx>,
|
||||
tables: &mut Tables<'tcx>,
|
||||
) -> Allocation {
|
||||
try_new_allocation(ty, const_value, tables)
|
||||
.unwrap_or_else(|_| panic!("Failed to convert: {const_value:?} to {ty:?}"))
|
||||
pub fn try_new_scalar<'tcx, B: Bridge>(
|
||||
layout: TyAndLayout<'tcx, Ty<'tcx>>,
|
||||
scalar: Scalar,
|
||||
cx: &SmirCtxt<'tcx, B>,
|
||||
) -> Result<Allocation, B::Error> {
|
||||
let size = scalar.size();
|
||||
let mut allocation = Allocation::new(size, layout.align.abi, AllocInit::Uninit, ());
|
||||
allocation
|
||||
.write_scalar(&cx.tcx, alloc_range(Size::ZERO, size), scalar)
|
||||
.map_err(|e| B::Error::from_internal(e))?;
|
||||
|
||||
Ok(allocation)
|
||||
}
|
||||
|
||||
#[allow(rustc::usage_of_qualified_ty)]
|
||||
pub(crate) fn try_new_allocation<'tcx>(
|
||||
ty: rustc_middle::ty::Ty<'tcx>,
|
||||
const_value: ConstValue<'tcx>,
|
||||
tables: &mut Tables<'tcx>,
|
||||
) -> Result<Allocation, Error> {
|
||||
let layout = tables
|
||||
.tcx
|
||||
.layout_of(rustc_middle::ty::TypingEnv::fully_monomorphized().as_query_input(ty))
|
||||
.map_err(|e| e.stable(tables))?;
|
||||
Ok(match const_value {
|
||||
ConstValue::Scalar(scalar) => {
|
||||
let size = scalar.size();
|
||||
let mut allocation = rustc_middle::mir::interpret::Allocation::new(
|
||||
size,
|
||||
layout.align.abi,
|
||||
AllocInit::Uninit,
|
||||
(),
|
||||
);
|
||||
allocation
|
||||
.write_scalar(&tables.tcx, alloc_range(Size::ZERO, size), scalar)
|
||||
.map_err(|e| e.stable(tables))?;
|
||||
allocation.stable(tables)
|
||||
}
|
||||
ConstValue::ZeroSized => new_empty_allocation(layout.align.abi),
|
||||
ConstValue::Slice { data, meta } => {
|
||||
let alloc_id = tables.tcx.reserve_and_set_memory_alloc(data);
|
||||
let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
|
||||
let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
|
||||
let scalar_meta =
|
||||
rustc_middle::mir::interpret::Scalar::from_target_usize(meta, &tables.tcx);
|
||||
let mut allocation = rustc_middle::mir::interpret::Allocation::new(
|
||||
layout.size,
|
||||
layout.align.abi,
|
||||
AllocInit::Uninit,
|
||||
(),
|
||||
);
|
||||
allocation
|
||||
.write_scalar(
|
||||
&tables.tcx,
|
||||
alloc_range(Size::ZERO, tables.tcx.data_layout.pointer_size),
|
||||
scalar_ptr,
|
||||
)
|
||||
.map_err(|e| e.stable(tables))?;
|
||||
allocation
|
||||
.write_scalar(
|
||||
&tables.tcx,
|
||||
alloc_range(tables.tcx.data_layout.pointer_size, scalar_meta.size()),
|
||||
scalar_meta,
|
||||
)
|
||||
.map_err(|e| e.stable(tables))?;
|
||||
allocation.stable(tables)
|
||||
}
|
||||
ConstValue::Indirect { alloc_id, offset } => {
|
||||
let alloc = tables.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||
allocation_filter(&alloc.0, alloc_range(offset, layout.size), tables)
|
||||
}
|
||||
})
|
||||
pub fn try_new_slice<'tcx, B: Bridge>(
|
||||
layout: TyAndLayout<'tcx, Ty<'tcx>>,
|
||||
data: ConstAllocation<'tcx>,
|
||||
meta: u64,
|
||||
cx: &SmirCtxt<'tcx, B>,
|
||||
) -> Result<Allocation, B::Error> {
|
||||
let alloc_id = cx.tcx.reserve_and_set_memory_alloc(data);
|
||||
let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
|
||||
let scalar_ptr = Scalar::from_pointer(ptr, &cx.tcx);
|
||||
let scalar_meta: Scalar = Scalar::from_target_usize(meta, &cx.tcx);
|
||||
let mut allocation = Allocation::new(layout.size, layout.align.abi, AllocInit::Uninit, ());
|
||||
allocation
|
||||
.write_scalar(&cx.tcx, alloc_range(Size::ZERO, cx.tcx.data_layout.pointer_size), scalar_ptr)
|
||||
.map_err(|e| B::Error::from_internal(e))?;
|
||||
allocation
|
||||
.write_scalar(
|
||||
&cx.tcx,
|
||||
alloc_range(cx.tcx.data_layout.pointer_size, scalar_meta.size()),
|
||||
scalar_meta,
|
||||
)
|
||||
.map_err(|e| B::Error::from_internal(e))?;
|
||||
|
||||
Ok(allocation)
|
||||
}
|
||||
|
||||
pub fn try_new_indirect<'tcx, B: Bridge>(
|
||||
alloc_id: AllocId,
|
||||
cx: &SmirCtxt<'tcx, B>,
|
||||
) -> ConstAllocation<'tcx> {
|
||||
let alloc = cx.tcx.global_alloc(alloc_id).unwrap_memory();
|
||||
|
||||
alloc
|
||||
}
|
||||
|
||||
/// Creates an `Allocation` only from information within the `AllocRange`.
|
||||
pub(super) fn allocation_filter<'tcx>(
|
||||
pub fn allocation_filter<'tcx, B: Bridge>(
|
||||
alloc: &rustc_middle::mir::interpret::Allocation,
|
||||
alloc_range: AllocRange,
|
||||
tables: &mut Tables<'tcx>,
|
||||
) -> Allocation {
|
||||
tables: &mut Tables<'tcx, B>,
|
||||
cx: &SmirCtxt<'tcx, B>,
|
||||
) -> B::Allocation {
|
||||
let mut bytes: Vec<Option<u8>> = alloc
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(
|
||||
alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
|
||||
|
|
@ -117,15 +97,8 @@ pub(super) fn allocation_filter<'tcx>(
|
|||
.iter()
|
||||
.filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
|
||||
{
|
||||
ptrs.push((
|
||||
offset.bytes_usize() - alloc_range.start.bytes_usize(),
|
||||
tables.prov(prov.alloc_id()),
|
||||
));
|
||||
}
|
||||
Allocation {
|
||||
bytes,
|
||||
provenance: ProvenanceMap { ptrs },
|
||||
align: alloc.align.bytes(),
|
||||
mutability: alloc.mutability.stable(tables),
|
||||
ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), prov.alloc_id()));
|
||||
}
|
||||
|
||||
B::Allocation::new(bytes, ptrs, alloc.align.bytes(), alloc.mutability, tables, cx)
|
||||
}
|
||||
|
|
|
|||
59
compiler/rustc_smir/src/rustc_smir/bridge.rs
Normal file
59
compiler/rustc_smir/src/rustc_smir/bridge.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//! Defines a set of traits that is used for abstracting
|
||||
//! stable_mir's components that are needed in rustc_smir.
|
||||
//!
|
||||
//! These traits are really useful when programming
|
||||
//! in stable_mir-agnostic settings.
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::context::SmirCtxt;
|
||||
use super::{Bridge, Tables};
|
||||
|
||||
pub trait SmirError {
|
||||
fn new(msg: String) -> Self;
|
||||
fn from_internal<T: Debug>(err: T) -> Self;
|
||||
}
|
||||
|
||||
pub trait Prov<B: Bridge> {
|
||||
fn new(aid: B::AllocId) -> Self;
|
||||
}
|
||||
|
||||
pub trait Allocation<B: Bridge> {
|
||||
fn new<'tcx>(
|
||||
bytes: Vec<Option<u8>>,
|
||||
ptrs: Vec<(usize, rustc_middle::mir::interpret::AllocId)>,
|
||||
align: u64,
|
||||
mutability: rustc_middle::mir::Mutability,
|
||||
tables: &mut Tables<'tcx, B>,
|
||||
cx: &SmirCtxt<'tcx, B>,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! make_bridge_trait {
|
||||
($name:ident) => {
|
||||
pub trait $name<B: Bridge> {
|
||||
fn new(did: B::DefId) -> Self;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
make_bridge_trait!(CrateItem);
|
||||
make_bridge_trait!(AdtDef);
|
||||
make_bridge_trait!(ForeignModuleDef);
|
||||
make_bridge_trait!(ForeignDef);
|
||||
make_bridge_trait!(FnDef);
|
||||
make_bridge_trait!(ClosureDef);
|
||||
make_bridge_trait!(CoroutineDef);
|
||||
make_bridge_trait!(CoroutineClosureDef);
|
||||
make_bridge_trait!(AliasDef);
|
||||
make_bridge_trait!(ParamDef);
|
||||
make_bridge_trait!(BrNamedDef);
|
||||
make_bridge_trait!(TraitDef);
|
||||
make_bridge_trait!(GenericDef);
|
||||
make_bridge_trait!(ConstDef);
|
||||
make_bridge_trait!(ImplDef);
|
||||
make_bridge_trait!(RegionDef);
|
||||
make_bridge_trait!(CoroutineWitnessDef);
|
||||
make_bridge_trait!(AssocDef);
|
||||
make_bridge_trait!(OpaqueDef);
|
||||
make_bridge_trait!(StaticDef);
|
||||
|
|
@ -9,9 +9,6 @@ use rustc_middle::mir;
|
|||
use rustc_middle::mir::visit::MutVisitor;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use crate::stable_mir;
|
||||
|
||||
/// Builds a monomorphic body for a given instance.
|
||||
pub(crate) struct BodyBuilder<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
|
@ -31,8 +28,8 @@ impl<'tcx> BodyBuilder<'tcx> {
|
|||
/// Build a stable monomorphic body for a given instance based on the MIR body.
|
||||
///
|
||||
/// All constants are also evaluated.
|
||||
pub(crate) fn build(mut self, tables: &mut Tables<'tcx>) -> stable_mir::mir::Body {
|
||||
let body = tables.tcx.instance_mir(self.instance.def).clone();
|
||||
pub(crate) fn build(mut self) -> mir::Body<'tcx> {
|
||||
let body = self.tcx.instance_mir(self.instance.def).clone();
|
||||
let mono_body = if !self.instance.args.is_empty()
|
||||
// Without the `generic_const_exprs` feature gate, anon consts in signatures do not
|
||||
// get generic parameters. Which is wrong, but also not a problem without
|
||||
|
|
@ -40,7 +37,7 @@ impl<'tcx> BodyBuilder<'tcx> {
|
|||
|| self.tcx.def_kind(self.instance.def_id()) != DefKind::AnonConst
|
||||
{
|
||||
let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions(
|
||||
tables.tcx,
|
||||
self.tcx,
|
||||
ty::TypingEnv::fully_monomorphized(),
|
||||
ty::EarlyBinder::bind(body),
|
||||
);
|
||||
|
|
@ -50,7 +47,8 @@ impl<'tcx> BodyBuilder<'tcx> {
|
|||
// Already monomorphic.
|
||||
body
|
||||
};
|
||||
mono_body.stable(tables)
|
||||
|
||||
mono_body
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
762
compiler/rustc_smir/src/rustc_smir/context/impls.rs
Normal file
762
compiler/rustc_smir/src/rustc_smir/context/impls.rs
Normal file
|
|
@ -0,0 +1,762 @@
|
|||
//! Implementation of StableMIR Context.
|
||||
|
||||
#![allow(rustc::usage_of_qualified_ty)]
|
||||
|
||||
use std::iter;
|
||||
|
||||
use rustc_abi::{Endian, Layout, ReprOptions};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::{Attribute, LangItem};
|
||||
use rustc_middle::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar};
|
||||
use rustc_middle::mir::{BinOp, Body, Const as MirConst, ConstValue, UnOp};
|
||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
|
||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::util::Discr;
|
||||
use rustc_middle::ty::{
|
||||
AdtDef, AdtKind, AssocItem, Binder, ClosureKind, CoroutineArgsExt, EarlyBinder,
|
||||
ExistentialTraitRef, FnSig, GenericArgsRef, Instance, InstanceKind, IntrinsicDef, List,
|
||||
PolyFnSig, ScalarInt, TraitDef, TraitRef, Ty, TyCtxt, TyKind, TypeVisitableExt, UintTy,
|
||||
ValTree, VariantDef,
|
||||
};
|
||||
use rustc_middle::{mir, ty};
|
||||
use rustc_session::cstore::ForeignModule;
|
||||
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use rustc_span::{FileNameDisplayPreference, Span, Symbol};
|
||||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
use super::{SmirAllocRange, SmirCtxt, SmirTy, SmirTypingEnv};
|
||||
use crate::rustc_smir::builder::BodyBuilder;
|
||||
use crate::rustc_smir::{Bridge, SmirError, Tables, filter_def_ids};
|
||||
|
||||
impl<'tcx, B: Bridge> SmirTy<'tcx> for SmirCtxt<'tcx, B> {
|
||||
fn new_foreign(&self, def_id: DefId) -> ty::Ty<'tcx> {
|
||||
ty::Ty::new_foreign(self.tcx, def_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> SmirTypingEnv<'tcx> for SmirCtxt<'tcx, B> {
|
||||
fn fully_monomorphized(&self) -> ty::TypingEnv<'tcx> {
|
||||
ty::TypingEnv::fully_monomorphized()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> SmirAllocRange<'tcx> for SmirCtxt<'tcx, B> {
|
||||
fn alloc_range(
|
||||
&self,
|
||||
offset: rustc_abi::Size,
|
||||
size: rustc_abi::Size,
|
||||
) -> mir::interpret::AllocRange {
|
||||
rustc_middle::mir::interpret::alloc_range(offset, size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
|
||||
pub fn lift<T: ty::Lift<TyCtxt<'tcx>>>(&self, value: T) -> Option<T::Lifted> {
|
||||
self.tcx.lift(value)
|
||||
}
|
||||
|
||||
pub fn adt_def(&self, def_id: DefId) -> AdtDef<'tcx> {
|
||||
self.tcx.adt_def(def_id)
|
||||
}
|
||||
|
||||
pub fn coroutine_movability(&self, def_id: DefId) -> ty::Movability {
|
||||
self.tcx.coroutine_movability(def_id)
|
||||
}
|
||||
|
||||
pub fn valtree_to_const_val(&self, key: ty::Value<'tcx>) -> ConstValue<'tcx> {
|
||||
self.tcx.valtree_to_const_val(key)
|
||||
}
|
||||
|
||||
/// Return whether the instance as a body available.
|
||||
///
|
||||
/// Items and intrinsics may have a body available from its definition.
|
||||
/// Shims body may be generated depending on their type.
|
||||
pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool {
|
||||
let def_id = instance.def_id();
|
||||
self.item_has_body(def_id)
|
||||
|| !matches!(
|
||||
instance.def,
|
||||
ty::InstanceKind::Virtual(..)
|
||||
| ty::InstanceKind::Intrinsic(..)
|
||||
| ty::InstanceKind::Item(..)
|
||||
)
|
||||
}
|
||||
|
||||
/// Return whether the item has a body defined by the user.
|
||||
///
|
||||
/// Note that intrinsics may have a placeholder body that shouldn't be used in practice.
|
||||
/// In StableMIR, we handle this case as if the body is not available.
|
||||
pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
|
||||
let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) {
|
||||
intrinsic.must_be_overridden
|
||||
} else {
|
||||
false
|
||||
};
|
||||
!must_override && self.tcx.is_mir_available(def_id)
|
||||
}
|
||||
|
||||
fn filter_fn_def(&self, def_id: DefId) -> Option<DefId> {
|
||||
if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
|
||||
Some(def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_static_def(&self, def_id: DefId) -> Option<DefId> {
|
||||
matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| def_id)
|
||||
}
|
||||
|
||||
pub fn target_endian(&self) -> Endian {
|
||||
self.tcx.data_layout.endian
|
||||
}
|
||||
|
||||
pub fn target_pointer_size(&self) -> usize {
|
||||
self.tcx.data_layout.pointer_size.bits().try_into().unwrap()
|
||||
}
|
||||
|
||||
pub fn entry_fn(&self) -> Option<DefId> {
|
||||
Some(self.tcx.entry_fn(())?.0)
|
||||
}
|
||||
|
||||
/// Retrieve all items of the local crate that have a MIR associated with them.
|
||||
pub fn all_local_items(&self) -> Vec<DefId> {
|
||||
self.tcx.mir_keys(()).iter().map(|item| item.to_def_id()).collect()
|
||||
}
|
||||
|
||||
/// Retrieve the body of a function.
|
||||
/// This function will panic if the body is not available.
|
||||
pub fn mir_body(&self, item: DefId) -> &'tcx Body<'tcx> {
|
||||
self.tcx.instance_mir(InstanceKind::Item(item))
|
||||
}
|
||||
|
||||
/// Check whether the body of a function is available.
|
||||
pub fn has_body(&self, def: DefId) -> bool {
|
||||
self.item_has_body(def)
|
||||
}
|
||||
|
||||
pub fn foreign_modules(&self, crate_num: CrateNum) -> Vec<DefId> {
|
||||
self.tcx.foreign_modules(crate_num).keys().map(|mod_def_id| *mod_def_id).collect()
|
||||
}
|
||||
|
||||
/// Retrieve all functions defined in this crate.
|
||||
pub fn crate_functions(&self, crate_num: CrateNum) -> Vec<DefId> {
|
||||
filter_def_ids(self.tcx, crate_num, |def_id| self.filter_fn_def(def_id))
|
||||
}
|
||||
|
||||
/// Retrieve all static items defined in this crate.
|
||||
pub fn crate_statics(&self, crate_num: CrateNum) -> Vec<DefId> {
|
||||
filter_def_ids(self.tcx, crate_num, |def_id| self.filter_static_def(def_id))
|
||||
}
|
||||
|
||||
pub fn foreign_module(&self, mod_def: DefId) -> &ForeignModule {
|
||||
self.tcx.foreign_modules(mod_def.krate).get(&mod_def).unwrap()
|
||||
}
|
||||
|
||||
pub fn foreign_items(&self, mod_def: DefId) -> Vec<DefId> {
|
||||
self.tcx
|
||||
.foreign_modules(mod_def.krate)
|
||||
.get(&mod_def)
|
||||
.unwrap()
|
||||
.foreign_items
|
||||
.iter()
|
||||
.map(|item_def| *item_def)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn all_trait_decls(&self) -> impl Iterator<Item = DefId> {
|
||||
self.tcx.all_traits_including_private()
|
||||
}
|
||||
|
||||
pub fn trait_decls(&self, crate_num: CrateNum) -> Vec<DefId> {
|
||||
self.tcx.traits(crate_num).iter().map(|trait_def_id| *trait_def_id).collect()
|
||||
}
|
||||
|
||||
pub fn trait_decl(&self, trait_def: DefId) -> &'tcx TraitDef {
|
||||
self.tcx.trait_def(trait_def)
|
||||
}
|
||||
|
||||
pub fn all_trait_impls(&self) -> Vec<DefId> {
|
||||
iter::once(LOCAL_CRATE)
|
||||
.chain(self.tcx.crates(()).iter().copied())
|
||||
.flat_map(|cnum| self.tcx.trait_impls_in_crate(cnum).iter())
|
||||
.map(|impl_def_id| *impl_def_id)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn trait_impls(&self, crate_num: CrateNum) -> Vec<DefId> {
|
||||
self.tcx.trait_impls_in_crate(crate_num).iter().map(|impl_def_id| *impl_def_id).collect()
|
||||
}
|
||||
|
||||
pub fn trait_impl(&self, impl_def: DefId) -> EarlyBinder<'tcx, TraitRef<'tcx>> {
|
||||
self.tcx.impl_trait_ref(impl_def).unwrap()
|
||||
}
|
||||
|
||||
pub fn generics_of(&self, def_id: DefId) -> &'tcx ty::Generics {
|
||||
self.tcx.generics_of(def_id)
|
||||
}
|
||||
|
||||
pub fn predicates_of(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
) -> (Option<DefId>, Vec<(ty::PredicateKind<'tcx>, Span)>) {
|
||||
let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(def_id);
|
||||
(
|
||||
parent,
|
||||
predicates
|
||||
.iter()
|
||||
.map(|(clause, span)| (clause.as_predicate().kind().skip_binder(), *span))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn explicit_predicates_of(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
) -> (Option<DefId>, Vec<(ty::PredicateKind<'tcx>, Span)>) {
|
||||
let ty::GenericPredicates { parent, predicates } = self.tcx.explicit_predicates_of(def_id);
|
||||
(
|
||||
parent,
|
||||
predicates
|
||||
.iter()
|
||||
.map(|(clause, span)| (clause.as_predicate().kind().skip_binder(), *span))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn crate_name(&self, crate_num: CrateNum) -> String {
|
||||
self.tcx.crate_name(crate_num).to_string()
|
||||
}
|
||||
|
||||
pub fn crate_is_local(&self, crate_num: CrateNum) -> bool {
|
||||
crate_num == LOCAL_CRATE
|
||||
}
|
||||
|
||||
pub fn crate_num_id(&self, crate_num: CrateNum) -> usize {
|
||||
crate_num.into()
|
||||
}
|
||||
|
||||
pub fn local_crate_num(&self) -> CrateNum {
|
||||
LOCAL_CRATE
|
||||
}
|
||||
|
||||
/// Retrieve a list of all external crates.
|
||||
pub fn external_crates(&self) -> Vec<CrateNum> {
|
||||
self.tcx.crates(()).iter().map(|crate_num| *crate_num).collect()
|
||||
}
|
||||
|
||||
/// Find a crate with the given name.
|
||||
pub fn find_crates(&self, name: &str) -> Vec<CrateNum> {
|
||||
let crates: Vec<CrateNum> = [LOCAL_CRATE]
|
||||
.iter()
|
||||
.chain(self.tcx.crates(()).iter())
|
||||
.filter_map(|crate_num| {
|
||||
let crate_name = self.tcx.crate_name(*crate_num).to_string();
|
||||
(name == crate_name).then(|| *crate_num)
|
||||
})
|
||||
.collect();
|
||||
crates
|
||||
}
|
||||
|
||||
/// Returns the name of given `DefId`.
|
||||
pub fn def_name(&self, def_id: DefId, trimmed: bool) -> String {
|
||||
if trimmed {
|
||||
with_forced_trimmed_paths!(self.tcx.def_path_str(def_id))
|
||||
} else {
|
||||
with_no_trimmed_paths!(self.tcx.def_path_str(def_id))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return registered tool attributes with the given attribute name.
|
||||
///
|
||||
/// FIXME(jdonszelmann): may panic on non-tool attributes. After more attribute work, non-tool
|
||||
/// attributes will simply return an empty list.
|
||||
///
|
||||
/// Single segmented name like `#[clippy]` is specified as `&["clippy".to_string()]`.
|
||||
/// Multi-segmented name like `#[rustfmt::skip]` is specified as `&["rustfmt".to_string(), "skip".to_string()]`.
|
||||
pub fn tool_attrs(&self, def_id: DefId, attr: &[String]) -> Vec<(String, Span)> {
|
||||
let attr_name: Vec<_> = attr.iter().map(|seg| Symbol::intern(&seg)).collect();
|
||||
self.tcx
|
||||
.get_attrs_by_path(def_id, &attr_name)
|
||||
.filter_map(|attribute| {
|
||||
if let Attribute::Unparsed(u) = attribute {
|
||||
let attr_str = rustc_hir_pretty::attribute_to_string(&self.tcx, attribute);
|
||||
Some((attr_str, u.span))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Get all tool attributes of a definition.
|
||||
pub fn all_tool_attrs(&self, did: DefId) -> Vec<(String, Span)> {
|
||||
let attrs_iter = if let Some(did) = did.as_local() {
|
||||
self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(did)).iter()
|
||||
} else {
|
||||
self.tcx.attrs_for_def(did).iter()
|
||||
};
|
||||
attrs_iter
|
||||
.filter_map(|attribute| {
|
||||
if let Attribute::Unparsed(u) = attribute {
|
||||
let attr_str = rustc_hir_pretty::attribute_to_string(&self.tcx, attribute);
|
||||
Some((attr_str, u.span))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Returns printable, human readable form of `Span`.
|
||||
pub fn span_to_string(&self, span: Span) -> String {
|
||||
self.tcx.sess.source_map().span_to_diagnostic_string(span)
|
||||
}
|
||||
|
||||
/// Return filename from given `Span`, for diagnostic purposes.
|
||||
pub fn get_filename(&self, span: Span) -> String {
|
||||
self.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_to_filename(span)
|
||||
.display(FileNameDisplayPreference::Local)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
/// Return lines corresponding to this `Span`.
|
||||
pub fn get_lines(&self, span: Span) -> (usize, usize, usize, usize) {
|
||||
let lines = &self.tcx.sess.source_map().span_to_location_info(span);
|
||||
(lines.1, lines.2, lines.3, lines.4)
|
||||
}
|
||||
|
||||
/// Returns the `kind` of given `DefId`.
|
||||
pub fn def_kind(&self, item: DefId) -> DefKind {
|
||||
self.tcx.def_kind(item)
|
||||
}
|
||||
|
||||
/// Returns whether this is a foreign item.
|
||||
pub fn is_foreign_item(&self, item: DefId) -> bool {
|
||||
self.tcx.is_foreign_item(item)
|
||||
}
|
||||
|
||||
/// Returns the kind of a given foreign item.
|
||||
pub fn foreign_item_kind(&self, def_id: DefId) -> DefKind {
|
||||
self.tcx.def_kind(def_id)
|
||||
}
|
||||
|
||||
/// Returns the kind of a given algebraic data type.
|
||||
pub fn adt_kind(&self, def: AdtDef<'tcx>) -> AdtKind {
|
||||
def.adt_kind()
|
||||
}
|
||||
|
||||
/// Returns if the ADT is a box.
|
||||
pub fn adt_is_box(&self, def: AdtDef<'tcx>) -> bool {
|
||||
def.is_box()
|
||||
}
|
||||
|
||||
/// Returns whether this ADT is simd.
|
||||
pub fn adt_is_simd(&self, def: AdtDef<'tcx>) -> bool {
|
||||
def.repr().simd()
|
||||
}
|
||||
|
||||
/// Returns whether this definition is a C string.
|
||||
pub fn adt_is_cstr(&self, def_id: DefId) -> bool {
|
||||
self.tcx.is_lang_item(def_id, LangItem::CStr)
|
||||
}
|
||||
|
||||
/// Returns the representation options for this ADT.
|
||||
pub fn adt_repr(&self, def: AdtDef<'tcx>) -> ReprOptions {
|
||||
def.repr()
|
||||
}
|
||||
|
||||
/// Retrieve the function signature for the given generic arguments.
|
||||
pub fn fn_sig(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
args_ref: GenericArgsRef<'tcx>,
|
||||
) -> Binder<'tcx, FnSig<'tcx>> {
|
||||
let sig = self.tcx.fn_sig(def_id).instantiate(self.tcx, args_ref);
|
||||
sig
|
||||
}
|
||||
|
||||
/// Retrieve the intrinsic definition if the item corresponds one.
|
||||
pub fn intrinsic(&self, def_id: DefId) -> Option<IntrinsicDef> {
|
||||
let intrinsic = self.tcx.intrinsic_raw(def_id);
|
||||
intrinsic
|
||||
}
|
||||
|
||||
/// Retrieve the plain function name of an intrinsic.
|
||||
pub fn intrinsic_name(&self, def_id: DefId) -> String {
|
||||
self.tcx.intrinsic(def_id).unwrap().name.to_string()
|
||||
}
|
||||
|
||||
/// Retrieve the closure signature for the given generic arguments.
|
||||
pub fn closure_sig(&self, args_ref: GenericArgsRef<'tcx>) -> Binder<'tcx, FnSig<'tcx>> {
|
||||
args_ref.as_closure().sig()
|
||||
}
|
||||
|
||||
/// The number of variants in this ADT.
|
||||
pub fn adt_variants_len(&self, def: AdtDef<'tcx>) -> usize {
|
||||
def.variants().len()
|
||||
}
|
||||
|
||||
/// Discriminant for a given variant index of AdtDef.
|
||||
pub fn adt_discr_for_variant(
|
||||
&self,
|
||||
adt: AdtDef<'tcx>,
|
||||
variant: rustc_abi::VariantIdx,
|
||||
) -> Discr<'tcx> {
|
||||
adt.discriminant_for_variant(self.tcx, variant)
|
||||
}
|
||||
|
||||
/// Discriminant for a given variand index and args of a coroutine.
|
||||
pub fn coroutine_discr_for_variant(
|
||||
&self,
|
||||
coroutine: DefId,
|
||||
args: GenericArgsRef<'tcx>,
|
||||
variant: rustc_abi::VariantIdx,
|
||||
) -> Discr<'tcx> {
|
||||
args.as_coroutine().discriminant_for_variant(coroutine, self.tcx, variant)
|
||||
}
|
||||
|
||||
/// The name of a variant.
|
||||
pub fn variant_name(&self, def: &'tcx VariantDef) -> String {
|
||||
def.name.to_string()
|
||||
}
|
||||
|
||||
/// Evaluate constant as a target usize.
|
||||
pub fn eval_target_usize(&self, cnst: MirConst<'tcx>) -> Result<u64, B::Error> {
|
||||
use crate::rustc_smir::context::SmirTypingEnv;
|
||||
cnst.try_eval_target_usize(self.tcx, self.fully_monomorphized())
|
||||
.ok_or_else(|| B::Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
|
||||
}
|
||||
|
||||
pub fn eval_target_usize_ty(&self, cnst: ty::Const<'tcx>) -> Result<u64, B::Error> {
|
||||
cnst.try_to_target_usize(self.tcx)
|
||||
.ok_or_else(|| B::Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
|
||||
}
|
||||
|
||||
pub(crate) fn try_new_const_zst(
|
||||
&self,
|
||||
ty_internal: Ty<'tcx>,
|
||||
) -> Result<MirConst<'tcx>, B::Error> {
|
||||
let size = self
|
||||
.tcx
|
||||
.layout_of(self.fully_monomorphized().as_query_input(ty_internal))
|
||||
.map_err(|err| {
|
||||
B::Error::new(format!(
|
||||
"Cannot create a zero-sized constant for type `{ty_internal}`: {err}"
|
||||
))
|
||||
})?
|
||||
.size;
|
||||
if size.bytes() != 0 {
|
||||
return Err(B::Error::new(format!(
|
||||
"Cannot create a zero-sized constant for type `{ty_internal}`: \
|
||||
Type `{ty_internal}` has {} bytes",
|
||||
size.bytes()
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(MirConst::Ty(ty_internal, self.const_zero_sized(ty_internal)))
|
||||
}
|
||||
|
||||
pub fn const_zero_sized(&self, ty_internal: Ty<'tcx>) -> ty::Const<'tcx> {
|
||||
ty::Const::zero_sized(self.tcx, ty_internal)
|
||||
}
|
||||
|
||||
/// Create a new constant that represents the given string value.
|
||||
pub fn new_const_str(&self, value: &str) -> MirConst<'tcx> {
|
||||
let ty = Ty::new_static_str(self.tcx);
|
||||
let bytes = value.as_bytes();
|
||||
let valtree = ValTree::from_raw_bytes(self.tcx, bytes);
|
||||
let cv = ty::Value { ty, valtree };
|
||||
let val = self.tcx.valtree_to_const_val(cv);
|
||||
MirConst::from_value(val, ty)
|
||||
}
|
||||
|
||||
/// Create a new constant that represents the given boolean value.
|
||||
pub fn new_const_bool(&self, value: bool) -> MirConst<'tcx> {
|
||||
MirConst::from_bool(self.tcx, value)
|
||||
}
|
||||
|
||||
pub fn try_new_const_uint(
|
||||
&self,
|
||||
value: u128,
|
||||
ty_internal: Ty<'tcx>,
|
||||
) -> Result<MirConst<'tcx>, B::Error> {
|
||||
let size = self
|
||||
.tcx
|
||||
.layout_of(self.fully_monomorphized().as_query_input(ty_internal))
|
||||
.unwrap()
|
||||
.size;
|
||||
let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
|
||||
B::Error::new(format!("Value overflow: cannot convert `{value}` to `{ty_internal}`."))
|
||||
})?;
|
||||
Ok(self.mir_const_from_scalar(Scalar::Int(scalar), ty_internal))
|
||||
}
|
||||
|
||||
pub fn try_new_ty_const_uint(
|
||||
&self,
|
||||
value: u128,
|
||||
ty_internal: Ty<'tcx>,
|
||||
) -> Result<ty::Const<'tcx>, B::Error> {
|
||||
let size = self
|
||||
.tcx
|
||||
.layout_of(self.fully_monomorphized().as_query_input(ty_internal))
|
||||
.unwrap()
|
||||
.size;
|
||||
let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| {
|
||||
B::Error::new(format!("Value overflow: cannot convert `{value}` to `{ty_internal}`."))
|
||||
})?;
|
||||
|
||||
Ok(self.ty_const_new_value(ValTree::from_scalar_int(self.tcx, scalar), ty_internal))
|
||||
}
|
||||
|
||||
pub fn ty_new_uint(&self, ty: UintTy) -> Ty<'tcx> {
|
||||
Ty::new_uint(self.tcx, ty)
|
||||
}
|
||||
|
||||
pub fn mir_const_from_scalar(&self, s: Scalar, ty: Ty<'tcx>) -> MirConst<'tcx> {
|
||||
MirConst::from_scalar(self.tcx, s, ty)
|
||||
}
|
||||
|
||||
pub fn ty_const_new_value(&self, valtree: ValTree<'tcx>, ty: Ty<'tcx>) -> ty::Const<'tcx> {
|
||||
ty::Const::new_value(self.tcx, valtree, ty)
|
||||
}
|
||||
|
||||
pub fn ty_valtree_from_scalar_int(&self, i: ScalarInt) -> ValTree<'tcx> {
|
||||
ValTree::from_scalar_int(self.tcx, i)
|
||||
}
|
||||
|
||||
/// Create a new type from the given kind.
|
||||
pub fn new_rigid_ty(&self, internal_kind: TyKind<'tcx>) -> Ty<'tcx> {
|
||||
self.tcx.mk_ty_from_kind(internal_kind)
|
||||
}
|
||||
|
||||
/// Create a new box type, `Box<T>`, for the given inner type `T`.
|
||||
pub fn new_box_ty(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
ty::Ty::new_box(self.tcx, ty)
|
||||
}
|
||||
|
||||
/// Returns the type of given crate item.
|
||||
pub fn def_ty(&self, item: DefId) -> Ty<'tcx> {
|
||||
self.tcx.type_of(item).instantiate_identity()
|
||||
}
|
||||
|
||||
/// Returns the type of given definition instantiated with the given arguments.
|
||||
pub fn def_ty_with_args(&self, item: DefId, args_ref: GenericArgsRef<'tcx>) -> Ty<'tcx> {
|
||||
let def_ty = self.tcx.type_of(item);
|
||||
self.tcx.instantiate_and_normalize_erasing_regions(
|
||||
args_ref,
|
||||
self.fully_monomorphized(),
|
||||
def_ty,
|
||||
)
|
||||
}
|
||||
|
||||
/// `Span` of an item.
|
||||
pub fn span_of_an_item(&self, def_id: DefId) -> Span {
|
||||
self.tcx.def_span(def_id)
|
||||
}
|
||||
|
||||
pub fn ty_const_pretty(&self, ct: ty::Const<'tcx>) -> String {
|
||||
ct.to_string()
|
||||
}
|
||||
|
||||
/// Obtain the representation of a type.
|
||||
pub fn ty_pretty(&self, ty: Ty<'tcx>) -> String {
|
||||
ty.to_string()
|
||||
}
|
||||
|
||||
/// Obtain the kind of a type.
|
||||
pub fn ty_kind(&self, ty: Ty<'tcx>) -> &'tcx TyKind<'tcx> {
|
||||
ty.kind()
|
||||
}
|
||||
|
||||
/// Get the discriminant Ty for this Ty if there's one.
|
||||
pub fn rigid_ty_discriminant_ty(&self, internal_kind: TyKind<'tcx>) -> Ty<'tcx> {
|
||||
let internal_ty = self.tcx.mk_ty_from_kind(internal_kind);
|
||||
internal_ty.discriminant_ty(self.tcx)
|
||||
}
|
||||
|
||||
/// Get the body of an Instance which is already monomorphized.
|
||||
pub fn instance_body(&self, instance: ty::Instance<'tcx>) -> Option<Body<'tcx>> {
|
||||
self.instance_has_body(instance).then(|| BodyBuilder::new(self.tcx, instance).build())
|
||||
}
|
||||
|
||||
/// Get the instance type with generic instantiations applied and lifetimes erased.
|
||||
pub fn instance_ty(&self, instance: ty::Instance<'tcx>) -> Ty<'tcx> {
|
||||
assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation");
|
||||
instance.ty(self.tcx, self.fully_monomorphized())
|
||||
}
|
||||
|
||||
/// Get the instantiation types.
|
||||
pub fn instance_args(&self, instance: ty::Instance<'tcx>) -> GenericArgsRef<'tcx> {
|
||||
instance.args
|
||||
}
|
||||
|
||||
/// Get an instance ABI.
|
||||
pub fn instance_abi(
|
||||
&self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) -> Result<&FnAbi<'tcx, Ty<'tcx>>, B::Error> {
|
||||
Ok(self.fn_abi_of_instance(instance, List::empty())?)
|
||||
}
|
||||
|
||||
/// Get the ABI of a function pointer.
|
||||
pub fn fn_ptr_abi(&self, sig: PolyFnSig<'tcx>) -> Result<&FnAbi<'tcx, Ty<'tcx>>, B::Error> {
|
||||
Ok(self.fn_abi_of_fn_ptr(sig, List::empty())?)
|
||||
}
|
||||
|
||||
/// Get the instance.
|
||||
pub fn instance_def_id(
|
||||
&self,
|
||||
instances: ty::Instance<'tcx>,
|
||||
tables: &mut Tables<'_, B>,
|
||||
) -> B::DefId {
|
||||
let def_id = instances.def_id();
|
||||
tables.create_def_id(def_id)
|
||||
}
|
||||
|
||||
/// Get the instance mangled name.
|
||||
pub fn instance_mangled_name(&self, instance: ty::Instance<'tcx>) -> String {
|
||||
self.tcx.symbol_name(instance).name.to_string()
|
||||
}
|
||||
|
||||
/// Check if this is an empty DropGlue shim.
|
||||
pub fn is_empty_drop_shim(&self, instance: ty::Instance<'tcx>) -> bool {
|
||||
matches!(instance.def, ty::InstanceKind::DropGlue(_, None))
|
||||
}
|
||||
|
||||
/// Convert a non-generic crate item into an instance.
|
||||
/// This function will panic if the item is generic.
|
||||
pub fn mono_instance(&self, def_id: DefId) -> Instance<'tcx> {
|
||||
Instance::mono(self.tcx, def_id)
|
||||
}
|
||||
|
||||
/// Item requires monomorphization.
|
||||
pub fn requires_monomorphization(&self, def_id: DefId) -> bool {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let result = generics.requires_monomorphization(self.tcx);
|
||||
result
|
||||
}
|
||||
|
||||
/// Resolve an instance from the given function definition and generic arguments.
|
||||
pub fn resolve_instance(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
args_ref: GenericArgsRef<'tcx>,
|
||||
) -> Option<Instance<'tcx>> {
|
||||
match Instance::try_resolve(self.tcx, self.fully_monomorphized(), def_id, args_ref) {
|
||||
Ok(Some(instance)) => Some(instance),
|
||||
Ok(None) | Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve an instance for drop_in_place for the given type.
|
||||
pub fn resolve_drop_in_place(&self, internal_ty: Ty<'tcx>) -> Instance<'tcx> {
|
||||
let instance = Instance::resolve_drop_in_place(self.tcx, internal_ty);
|
||||
instance
|
||||
}
|
||||
|
||||
/// Resolve instance for a function pointer.
|
||||
pub fn resolve_for_fn_ptr(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
args_ref: GenericArgsRef<'tcx>,
|
||||
) -> Option<Instance<'tcx>> {
|
||||
Instance::resolve_for_fn_ptr(self.tcx, self.fully_monomorphized(), def_id, args_ref)
|
||||
}
|
||||
|
||||
/// Resolve instance for a closure with the requested type.
|
||||
pub fn resolve_closure(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
args_ref: GenericArgsRef<'tcx>,
|
||||
closure_kind: ClosureKind,
|
||||
) -> Option<Instance<'tcx>> {
|
||||
Some(Instance::resolve_closure(self.tcx, def_id, args_ref, closure_kind))
|
||||
}
|
||||
|
||||
/// Try to evaluate an instance into a constant.
|
||||
pub fn eval_instance(
|
||||
&self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
||||
self.tcx.const_eval_instance(
|
||||
self.fully_monomorphized(),
|
||||
instance,
|
||||
self.tcx.def_span(instance.def_id()),
|
||||
)
|
||||
}
|
||||
|
||||
/// Evaluate a static's initializer.
|
||||
pub fn eval_static_initializer(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
) -> Result<ConstAllocation<'tcx>, ErrorHandled> {
|
||||
self.tcx.eval_static_initializer(def_id)
|
||||
}
|
||||
|
||||
/// Retrieve global allocation for the given allocation ID.
|
||||
pub fn global_alloc(&self, alloc_id: AllocId) -> GlobalAlloc<'tcx> {
|
||||
self.tcx.global_alloc(alloc_id)
|
||||
}
|
||||
|
||||
/// Retrieve the id for the virtual table.
|
||||
pub fn vtable_allocation(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
trait_ref: Option<Binder<'tcx, ExistentialTraitRef<'tcx>>>,
|
||||
) -> AllocId {
|
||||
let alloc_id = self.tcx.vtable_allocation((
|
||||
ty,
|
||||
trait_ref.map(|principal| self.tcx.instantiate_bound_regions_with_erased(principal)),
|
||||
));
|
||||
alloc_id
|
||||
}
|
||||
|
||||
/// Retrieve the instance name for diagnostic messages.
|
||||
///
|
||||
/// This will return the specialized name, e.g., `Vec<char>::new`.
|
||||
pub fn instance_name(&self, instance: ty::Instance<'tcx>, trimmed: bool) -> String {
|
||||
if trimmed {
|
||||
with_forced_trimmed_paths!(
|
||||
self.tcx.def_path_str_with_args(instance.def_id(), instance.args)
|
||||
)
|
||||
} else {
|
||||
with_no_trimmed_paths!(
|
||||
self.tcx.def_path_str_with_args(instance.def_id(), instance.args)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the layout of a type.
|
||||
pub fn ty_layout(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, B::Error> {
|
||||
let layout = self.layout_of(ty)?.layout;
|
||||
Ok(layout)
|
||||
}
|
||||
|
||||
/// Get the resulting type of binary operation.
|
||||
pub fn binop_ty(&self, bin_op: BinOp, rhs: Ty<'tcx>, lhs: Ty<'tcx>) -> Ty<'tcx> {
|
||||
bin_op.ty(self.tcx, rhs, lhs)
|
||||
}
|
||||
|
||||
/// Get the resulting type of unary operation.
|
||||
pub fn unop_ty(&self, un_op: UnOp, arg: Ty<'tcx>) -> Ty<'tcx> {
|
||||
un_op.ty(self.tcx, arg)
|
||||
}
|
||||
|
||||
/// Get all associated items of a definition.
|
||||
pub fn associated_items(&self, def_id: DefId) -> Vec<AssocItem> {
|
||||
let assoc_items = if self.tcx.is_trait_alias(def_id) {
|
||||
Vec::new()
|
||||
} else {
|
||||
self.tcx
|
||||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.map(|did| self.tcx.associated_item(*did))
|
||||
.collect()
|
||||
};
|
||||
assoc_items
|
||||
}
|
||||
}
|
||||
79
compiler/rustc_smir/src/rustc_smir/context/mod.rs
Normal file
79
compiler/rustc_smir/src/rustc_smir/context/mod.rs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
//! Implementation of StableMIR Context.
|
||||
|
||||
#![allow(rustc::usage_of_qualified_ty)]
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rustc_abi::HasDataLayout;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::{FnAbiOfHelpers, HasTyCtxt, HasTypingEnv, LayoutOfHelpers};
|
||||
use rustc_middle::ty::{Ty, TyCtxt};
|
||||
|
||||
use crate::rustc_smir::{Bridge, SmirError};
|
||||
|
||||
mod impls;
|
||||
mod traits;
|
||||
|
||||
pub use traits::*;
|
||||
|
||||
/// Provides direct access to rustc's internal queries.
|
||||
///
|
||||
/// The [`crate::stable_mir::compiler_interface::SmirInterface`] must go through
|
||||
/// this context to obtain rustc-level information.
|
||||
pub struct SmirCtxt<'tcx, B: Bridge> {
|
||||
pub tcx: TyCtxt<'tcx>,
|
||||
_marker: PhantomData<B>,
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> SmirCtxt<'tcx, B> {
|
||||
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||
Self { tcx, _marker: Default::default() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement error handling for extracting function ABI information.
|
||||
impl<'tcx, B: Bridge> FnAbiOfHelpers<'tcx> for SmirCtxt<'tcx, B> {
|
||||
type FnAbiOfResult = Result<&'tcx rustc_target::callconv::FnAbi<'tcx, Ty<'tcx>>, B::Error>;
|
||||
|
||||
#[inline]
|
||||
fn handle_fn_abi_err(
|
||||
&self,
|
||||
err: ty::layout::FnAbiError<'tcx>,
|
||||
_span: rustc_span::Span,
|
||||
fn_abi_request: ty::layout::FnAbiRequest<'tcx>,
|
||||
) -> B::Error {
|
||||
B::Error::new(format!("Failed to get ABI for `{fn_abi_request:?}`: {err:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> LayoutOfHelpers<'tcx> for SmirCtxt<'tcx, B> {
|
||||
type LayoutOfResult = Result<ty::layout::TyAndLayout<'tcx>, B::Error>;
|
||||
|
||||
#[inline]
|
||||
fn handle_layout_err(
|
||||
&self,
|
||||
err: ty::layout::LayoutError<'tcx>,
|
||||
_span: rustc_span::Span,
|
||||
ty: Ty<'tcx>,
|
||||
) -> B::Error {
|
||||
B::Error::new(format!("Failed to get layout for `{ty}`: {err}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> HasTypingEnv<'tcx> for SmirCtxt<'tcx, B> {
|
||||
fn typing_env(&self) -> ty::TypingEnv<'tcx> {
|
||||
ty::TypingEnv::fully_monomorphized()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> HasTyCtxt<'tcx> for SmirCtxt<'tcx, B> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> HasDataLayout for SmirCtxt<'tcx, B> {
|
||||
fn data_layout(&self) -> &rustc_abi::TargetDataLayout {
|
||||
self.tcx.data_layout()
|
||||
}
|
||||
}
|
||||
46
compiler/rustc_smir/src/rustc_smir/context/traits.rs
Normal file
46
compiler/rustc_smir/src/rustc_smir/context/traits.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
//! A set of traits that define a stable interface to rustc's internals.
|
||||
//!
|
||||
//! These traits abstract rustc's internal APIs, allowing StableMIR to maintain a stable
|
||||
//! interface regardless of internal compiler changes.
|
||||
|
||||
use rustc_middle::mir::interpret::AllocRange;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::Ty;
|
||||
use rustc_span::def_id::DefId;
|
||||
|
||||
pub trait SmirExistentialProjection<'tcx> {
|
||||
fn new_from_args(
|
||||
&self,
|
||||
def_id: DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
term: ty::Term<'tcx>,
|
||||
) -> ty::ExistentialProjection<'tcx>;
|
||||
}
|
||||
|
||||
pub trait SmirExistentialTraitRef<'tcx> {
|
||||
fn new_from_args(
|
||||
&self,
|
||||
trait_def_id: DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> ty::ExistentialTraitRef<'tcx>;
|
||||
}
|
||||
|
||||
pub trait SmirTraitRef<'tcx> {
|
||||
fn new_from_args(
|
||||
&self,
|
||||
trait_def_id: DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> ty::TraitRef<'tcx>;
|
||||
}
|
||||
|
||||
pub trait SmirTy<'tcx> {
|
||||
fn new_foreign(&self, def_id: DefId) -> Ty<'tcx>;
|
||||
}
|
||||
|
||||
pub trait SmirTypingEnv<'tcx> {
|
||||
fn fully_monomorphized(&self) -> ty::TypingEnv<'tcx>;
|
||||
}
|
||||
|
||||
pub trait SmirAllocRange<'tcx> {
|
||||
fn alloc_range(&self, offset: rustc_abi::Size, size: rustc_abi::Size) -> AllocRange;
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
//! Handle the conversion of different internal errors into a stable version.
|
||||
//!
|
||||
//! Currently we encode everything as [stable_mir::Error], which is represented as a string.
|
||||
|
||||
use rustc_middle::mir::interpret::AllocError;
|
||||
use rustc_middle::ty::layout::LayoutError;
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use crate::stable_mir;
|
||||
|
||||
impl<'tcx> Stable<'tcx> for LayoutError<'tcx> {
|
||||
type T = stable_mir::Error;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
stable_mir::Error::new(format!("{self:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for AllocError {
|
||||
type T = stable_mir::Error;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
stable_mir::Error::new(format!("{self:?}"))
|
||||
}
|
||||
}
|
||||
|
|
@ -7,91 +7,263 @@
|
|||
//!
|
||||
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.
|
||||
|
||||
use std::marker::PointeeSized;
|
||||
use std::ops::RangeInclusive;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Index;
|
||||
|
||||
use rustc_hir::def::DefKind;
|
||||
use bridge::*;
|
||||
use context::SmirCtxt;
|
||||
use rustc_data_structures::fx::{self, FxIndexMap};
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::AllocId;
|
||||
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
|
||||
use stable_mir::abi::Layout;
|
||||
use stable_mir::mir::mono::{InstanceDef, StaticDef};
|
||||
use stable_mir::ty::{FnDef, MirConstId, Span, TyConstId};
|
||||
use stable_mir::{CtorKind, ItemKind};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::rustc_internal::IndexMap;
|
||||
use crate::stable_mir;
|
||||
|
||||
mod alloc;
|
||||
pub mod alloc;
|
||||
pub mod bridge;
|
||||
mod builder;
|
||||
pub mod context;
|
||||
mod convert;
|
||||
|
||||
pub struct Tables<'tcx> {
|
||||
pub(crate) tcx: TyCtxt<'tcx>,
|
||||
pub(crate) def_ids: IndexMap<DefId, stable_mir::DefId>,
|
||||
pub(crate) alloc_ids: IndexMap<AllocId, stable_mir::mir::alloc::AllocId>,
|
||||
pub(crate) spans: IndexMap<rustc_span::Span, Span>,
|
||||
pub(crate) types: IndexMap<Ty<'tcx>, stable_mir::ty::Ty>,
|
||||
pub(crate) instances: IndexMap<ty::Instance<'tcx>, InstanceDef>,
|
||||
pub(crate) ty_consts: IndexMap<ty::Const<'tcx>, TyConstId>,
|
||||
pub(crate) mir_consts: IndexMap<mir::Const<'tcx>, MirConstId>,
|
||||
pub(crate) layouts: IndexMap<rustc_abi::Layout<'tcx>, Layout>,
|
||||
/// A container which is used for TLS.
|
||||
pub struct SmirContainer<'tcx, B: Bridge> {
|
||||
pub tables: RefCell<Tables<'tcx, B>>,
|
||||
pub cx: RefCell<SmirCtxt<'tcx, B>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Tables<'tcx> {
|
||||
pub(crate) fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty {
|
||||
pub struct Tables<'tcx, B: Bridge> {
|
||||
pub def_ids: IndexMap<DefId, B::DefId>,
|
||||
pub alloc_ids: IndexMap<AllocId, B::AllocId>,
|
||||
pub spans: IndexMap<rustc_span::Span, B::Span>,
|
||||
pub types: IndexMap<Ty<'tcx>, B::Ty>,
|
||||
pub instances: IndexMap<ty::Instance<'tcx>, B::InstanceDef>,
|
||||
pub ty_consts: IndexMap<ty::Const<'tcx>, B::TyConstId>,
|
||||
pub mir_consts: IndexMap<mir::Const<'tcx>, B::MirConstId>,
|
||||
pub layouts: IndexMap<rustc_abi::Layout<'tcx>, B::Layout>,
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> Default for Tables<'tcx, B> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
def_ids: IndexMap::default(),
|
||||
alloc_ids: IndexMap::default(),
|
||||
spans: IndexMap::default(),
|
||||
types: IndexMap::default(),
|
||||
instances: IndexMap::default(),
|
||||
ty_consts: IndexMap::default(),
|
||||
mir_consts: IndexMap::default(),
|
||||
layouts: IndexMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> Index<B::DefId> for Tables<'tcx, B> {
|
||||
type Output = DefId;
|
||||
|
||||
#[inline(always)]
|
||||
fn index(&self, index: B::DefId) -> &Self::Output {
|
||||
&self.def_ids[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, B: Bridge> Tables<'tcx, B> {
|
||||
pub fn intern_ty(&mut self, ty: Ty<'tcx>) -> B::Ty {
|
||||
self.types.create_or_fetch(ty)
|
||||
}
|
||||
|
||||
pub(crate) fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> TyConstId {
|
||||
pub fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> B::TyConstId {
|
||||
self.ty_consts.create_or_fetch(ct)
|
||||
}
|
||||
|
||||
pub(crate) fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> MirConstId {
|
||||
pub fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> B::MirConstId {
|
||||
self.mir_consts.create_or_fetch(constant)
|
||||
}
|
||||
|
||||
/// Return whether the instance as a body available.
|
||||
///
|
||||
/// Items and intrinsics may have a body available from its definition.
|
||||
/// Shims body may be generated depending on their type.
|
||||
pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool {
|
||||
let def_id = instance.def_id();
|
||||
self.item_has_body(def_id)
|
||||
|| !matches!(
|
||||
instance.def,
|
||||
ty::InstanceKind::Virtual(..)
|
||||
| ty::InstanceKind::Intrinsic(..)
|
||||
| ty::InstanceKind::Item(..)
|
||||
)
|
||||
pub fn create_def_id(&mut self, did: DefId) -> B::DefId {
|
||||
self.def_ids.create_or_fetch(did)
|
||||
}
|
||||
|
||||
/// Return whether the item has a body defined by the user.
|
||||
///
|
||||
/// Note that intrinsics may have a placeholder body that shouldn't be used in practice.
|
||||
/// In StableMIR, we handle this case as if the body is not available.
|
||||
pub(crate) fn item_has_body(&self, def_id: DefId) -> bool {
|
||||
let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) {
|
||||
intrinsic.must_be_overridden
|
||||
} else {
|
||||
false
|
||||
};
|
||||
!must_override && self.tcx.is_mir_available(def_id)
|
||||
pub fn create_alloc_id(&mut self, aid: AllocId) -> B::AllocId {
|
||||
self.alloc_ids.create_or_fetch(aid)
|
||||
}
|
||||
|
||||
fn to_fn_def(&mut self, def_id: DefId) -> Option<FnDef> {
|
||||
if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) {
|
||||
Some(self.fn_def(def_id))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
pub fn create_span(&mut self, span: Span) -> B::Span {
|
||||
self.spans.create_or_fetch(span)
|
||||
}
|
||||
|
||||
fn to_static(&mut self, def_id: DefId) -> Option<StaticDef> {
|
||||
matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| self.static_def(def_id))
|
||||
pub fn instance_def(&mut self, instance: ty::Instance<'tcx>) -> B::InstanceDef {
|
||||
self.instances.create_or_fetch(instance)
|
||||
}
|
||||
|
||||
pub fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> B::Layout {
|
||||
self.layouts.create_or_fetch(layout)
|
||||
}
|
||||
|
||||
pub fn crate_item(&mut self, did: rustc_span::def_id::DefId) -> B::CrateItem {
|
||||
B::CrateItem::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn adt_def(&mut self, did: rustc_span::def_id::DefId) -> B::AdtDef {
|
||||
B::AdtDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn foreign_module_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignModuleDef {
|
||||
B::ForeignModuleDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn foreign_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignDef {
|
||||
B::ForeignDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn fn_def(&mut self, did: rustc_span::def_id::DefId) -> B::FnDef {
|
||||
B::FnDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn closure_def(&mut self, did: rustc_span::def_id::DefId) -> B::ClosureDef {
|
||||
B::ClosureDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn coroutine_def(&mut self, did: rustc_span::def_id::DefId) -> B::CoroutineDef {
|
||||
B::CoroutineDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn coroutine_closure_def(
|
||||
&mut self,
|
||||
did: rustc_span::def_id::DefId,
|
||||
) -> B::CoroutineClosureDef {
|
||||
B::CoroutineClosureDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn alias_def(&mut self, did: rustc_span::def_id::DefId) -> B::AliasDef {
|
||||
B::AliasDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn param_def(&mut self, did: rustc_span::def_id::DefId) -> B::ParamDef {
|
||||
B::ParamDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn br_named_def(&mut self, did: rustc_span::def_id::DefId) -> B::BrNamedDef {
|
||||
B::BrNamedDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn trait_def(&mut self, did: rustc_span::def_id::DefId) -> B::TraitDef {
|
||||
B::TraitDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn generic_def(&mut self, did: rustc_span::def_id::DefId) -> B::GenericDef {
|
||||
B::GenericDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn const_def(&mut self, did: rustc_span::def_id::DefId) -> B::ConstDef {
|
||||
B::ConstDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn impl_def(&mut self, did: rustc_span::def_id::DefId) -> B::ImplDef {
|
||||
B::ImplDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn region_def(&mut self, did: rustc_span::def_id::DefId) -> B::RegionDef {
|
||||
B::RegionDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn coroutine_witness_def(
|
||||
&mut self,
|
||||
did: rustc_span::def_id::DefId,
|
||||
) -> B::CoroutineWitnessDef {
|
||||
B::CoroutineWitnessDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn assoc_def(&mut self, did: rustc_span::def_id::DefId) -> B::AssocDef {
|
||||
B::AssocDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn opaque_def(&mut self, did: rustc_span::def_id::DefId) -> B::OpaqueDef {
|
||||
B::OpaqueDef::new(self.create_def_id(did))
|
||||
}
|
||||
|
||||
pub fn prov(&mut self, aid: rustc_middle::mir::interpret::AllocId) -> B::Prov {
|
||||
B::Prov::new(self.create_alloc_id(aid))
|
||||
}
|
||||
|
||||
pub fn static_def(&mut self, did: rustc_span::def_id::DefId) -> B::StaticDef {
|
||||
B::StaticDef::new(self.create_def_id(did))
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait defining types that are used to emulate StableMIR components, which is really
|
||||
/// useful when programming in stable_mir-agnostic settings.
|
||||
pub trait Bridge: Sized {
|
||||
type DefId: Copy + Debug + PartialEq + IndexedVal;
|
||||
type AllocId: Copy + Debug + PartialEq + IndexedVal;
|
||||
type Span: Copy + Debug + PartialEq + IndexedVal;
|
||||
type Ty: Copy + Debug + PartialEq + IndexedVal;
|
||||
type InstanceDef: Copy + Debug + PartialEq + IndexedVal;
|
||||
type TyConstId: Copy + Debug + PartialEq + IndexedVal;
|
||||
type MirConstId: Copy + Debug + PartialEq + IndexedVal;
|
||||
type Layout: Copy + Debug + PartialEq + IndexedVal;
|
||||
|
||||
type Error: SmirError;
|
||||
type CrateItem: CrateItem<Self>;
|
||||
type AdtDef: AdtDef<Self>;
|
||||
type ForeignModuleDef: ForeignModuleDef<Self>;
|
||||
type ForeignDef: ForeignDef<Self>;
|
||||
type FnDef: FnDef<Self>;
|
||||
type ClosureDef: ClosureDef<Self>;
|
||||
type CoroutineDef: CoroutineDef<Self>;
|
||||
type CoroutineClosureDef: CoroutineClosureDef<Self>;
|
||||
type AliasDef: AliasDef<Self>;
|
||||
type ParamDef: ParamDef<Self>;
|
||||
type BrNamedDef: BrNamedDef<Self>;
|
||||
type TraitDef: TraitDef<Self>;
|
||||
type GenericDef: GenericDef<Self>;
|
||||
type ConstDef: ConstDef<Self>;
|
||||
type ImplDef: ImplDef<Self>;
|
||||
type RegionDef: RegionDef<Self>;
|
||||
type CoroutineWitnessDef: CoroutineWitnessDef<Self>;
|
||||
type AssocDef: AssocDef<Self>;
|
||||
type OpaqueDef: OpaqueDef<Self>;
|
||||
type Prov: Prov<Self>;
|
||||
type StaticDef: StaticDef<Self>;
|
||||
|
||||
type Allocation: Allocation<Self>;
|
||||
}
|
||||
|
||||
pub trait IndexedVal {
|
||||
fn to_val(index: usize) -> Self;
|
||||
|
||||
fn to_index(&self) -> usize;
|
||||
}
|
||||
|
||||
/// Similar to rustc's `FxIndexMap`, `IndexMap` with extra
|
||||
/// safety features added.
|
||||
pub struct IndexMap<K, V> {
|
||||
index_map: fx::FxIndexMap<K, V>,
|
||||
}
|
||||
|
||||
impl<K, V> Default for IndexMap<K, V> {
|
||||
fn default() -> Self {
|
||||
Self { index_map: FxIndexMap::default() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
|
||||
pub fn create_or_fetch(&mut self, key: K) -> V {
|
||||
let len = self.index_map.len();
|
||||
let v = self.index_map.entry(key).or_insert(V::to_val(len));
|
||||
*v
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V>
|
||||
for IndexMap<K, V>
|
||||
{
|
||||
type Output = K;
|
||||
|
||||
fn index(&self, index: V) -> &Self::Output {
|
||||
let (k, v) = self.index_map.get_index(index.to_index()).unwrap();
|
||||
assert_eq!(*v, index, "Provided value doesn't match with indexed value");
|
||||
k
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,124 +284,3 @@ where
|
|||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a stable mir crate from a given crate number.
|
||||
pub(crate) fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
|
||||
let crate_name = tcx.crate_name(crate_num).to_string();
|
||||
let is_local = crate_num == LOCAL_CRATE;
|
||||
debug!(?crate_name, ?crate_num, "smir_crate");
|
||||
stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local }
|
||||
}
|
||||
|
||||
pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind {
|
||||
match kind {
|
||||
DefKind::Mod
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::TyParam
|
||||
| DefKind::ConstParam
|
||||
| DefKind::Macro(_)
|
||||
| DefKind::ExternCrate
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::Field
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::GlobalAsm => {
|
||||
unreachable!("Not a valid item kind: {kind:?}");
|
||||
}
|
||||
DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => {
|
||||
ItemKind::Fn
|
||||
}
|
||||
DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => {
|
||||
ItemKind::Const
|
||||
}
|
||||
DefKind::Static { .. } => ItemKind::Static,
|
||||
DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const),
|
||||
DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn),
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait used to convert between an internal MIR type to a Stable MIR type.
|
||||
pub trait Stable<'cx>: PointeeSized {
|
||||
/// The stable representation of the type implementing Stable.
|
||||
type T;
|
||||
/// Converts an object to the equivalent Stable MIR representation.
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T;
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for &T
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = T::T;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
(*self).stable(tables)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for Option<T>
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = Option<T::T>;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
self.as_ref().map(|value| value.stable(tables))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T, E> Stable<'tcx> for Result<T, E>
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
E: Stable<'tcx>,
|
||||
{
|
||||
type T = Result<T::T, E::T>;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
match self {
|
||||
Ok(val) => Ok(val.stable(tables)),
|
||||
Err(error) => Err(error.stable(tables)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for &[T]
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = Vec<T::T>;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
self.iter().map(|e| e.stable(tables)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T, U> Stable<'tcx> for (T, U)
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
U: Stable<'tcx>,
|
||||
{
|
||||
type T = (T::T, U::T);
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
(self.0.stable(tables), self.1.stable(tables))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for RangeInclusive<T>
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = RangeInclusive<T::T>;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
RangeInclusive::new(self.start().stable(tables), self.end().stable(tables))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use serde::Serialize;
|
|||
use stable_mir::compiler_interface::with;
|
||||
use stable_mir::mir::FieldIdx;
|
||||
use stable_mir::target::{MachineInfo, MachineSize as Size};
|
||||
use stable_mir::ty::{Align, IndexedVal, Ty, VariantIdx};
|
||||
use stable_mir::ty::{Align, Ty, VariantIdx};
|
||||
use stable_mir::{Error, Opaque, error};
|
||||
|
||||
use crate::stable_mir;
|
||||
|
|
@ -119,7 +119,7 @@ impl Layout {
|
|||
}
|
||||
}
|
||||
|
||||
impl IndexedVal for Layout {
|
||||
impl stable_mir::IndexedVal for Layout {
|
||||
fn to_val(index: usize) -> Self {
|
||||
Layout(index)
|
||||
}
|
||||
|
|
|
|||
77
compiler/rustc_smir/src/stable_mir/alloc.rs
Normal file
77
compiler/rustc_smir/src/stable_mir/alloc.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
//! Memory allocation implementation for StableMIR.
|
||||
//!
|
||||
//! This module is responsible for constructing stable components.
|
||||
//! All operations requiring rustc queries must be delegated
|
||||
//! to `rustc_smir::alloc` to maintain stability guarantees.
|
||||
|
||||
use rustc_abi::Align;
|
||||
use rustc_middle::mir::ConstValue;
|
||||
use rustc_middle::mir::interpret::AllocRange;
|
||||
use rustc_smir::bridge::SmirError;
|
||||
use rustc_smir::context::SmirCtxt;
|
||||
use rustc_smir::{Tables, alloc};
|
||||
|
||||
use super::Error;
|
||||
use super::compiler_interface::BridgeTys;
|
||||
use super::mir::Mutability;
|
||||
use super::ty::{Allocation, ProvenanceMap};
|
||||
use super::unstable::Stable;
|
||||
use crate::rustc_smir;
|
||||
|
||||
/// Creates new empty `Allocation` from given `Align`.
|
||||
fn new_empty_allocation(align: Align) -> Allocation {
|
||||
Allocation {
|
||||
bytes: Vec::new(),
|
||||
provenance: ProvenanceMap { ptrs: Vec::new() },
|
||||
align: align.bytes(),
|
||||
mutability: Mutability::Not,
|
||||
}
|
||||
}
|
||||
|
||||
// We need this method instead of a Stable implementation
|
||||
// because we need to get `Ty` of the const we are trying to create, to do that
|
||||
// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
|
||||
#[allow(rustc::usage_of_qualified_ty)]
|
||||
pub(crate) fn new_allocation<'tcx>(
|
||||
ty: rustc_middle::ty::Ty<'tcx>,
|
||||
const_value: ConstValue<'tcx>,
|
||||
tables: &mut Tables<'tcx, BridgeTys>,
|
||||
cx: &SmirCtxt<'tcx, BridgeTys>,
|
||||
) -> Allocation {
|
||||
try_new_allocation(ty, const_value, tables, cx)
|
||||
.unwrap_or_else(|_| panic!("Failed to convert: {const_value:?} to {ty:?}"))
|
||||
}
|
||||
|
||||
#[allow(rustc::usage_of_qualified_ty)]
|
||||
pub(crate) fn try_new_allocation<'tcx>(
|
||||
ty: rustc_middle::ty::Ty<'tcx>,
|
||||
const_value: ConstValue<'tcx>,
|
||||
tables: &mut Tables<'tcx, BridgeTys>,
|
||||
cx: &SmirCtxt<'tcx, BridgeTys>,
|
||||
) -> Result<Allocation, Error> {
|
||||
let layout = alloc::create_ty_and_layout(cx, ty).map_err(|e| Error::from_internal(e))?;
|
||||
match const_value {
|
||||
ConstValue::Scalar(scalar) => {
|
||||
alloc::try_new_scalar(layout, scalar, cx).map(|alloc| alloc.stable(tables, cx))
|
||||
}
|
||||
ConstValue::ZeroSized => Ok(new_empty_allocation(layout.align.abi)),
|
||||
ConstValue::Slice { data, meta } => {
|
||||
alloc::try_new_slice(layout, data, meta, cx).map(|alloc| alloc.stable(tables, cx))
|
||||
}
|
||||
ConstValue::Indirect { alloc_id, offset } => {
|
||||
let alloc = alloc::try_new_indirect(alloc_id, cx);
|
||||
use rustc_smir::context::SmirAllocRange;
|
||||
Ok(allocation_filter(&alloc.0, cx.alloc_range(offset, layout.size), tables, cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an `Allocation` only from information within the `AllocRange`.
|
||||
pub(super) fn allocation_filter<'tcx>(
|
||||
alloc: &rustc_middle::mir::interpret::Allocation,
|
||||
alloc_range: AllocRange,
|
||||
tables: &mut Tables<'tcx, BridgeTys>,
|
||||
cx: &SmirCtxt<'tcx, BridgeTys>,
|
||||
) -> Allocation {
|
||||
alloc::allocation_filter(alloc, alloc_range, tables, cx)
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -7,6 +7,10 @@
|
|||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::{fmt, io};
|
||||
|
||||
use rustc_smir::bridge::SmirError;
|
||||
|
||||
use crate::rustc_smir;
|
||||
|
||||
macro_rules! error {
|
||||
($fmt: literal $(,)?) => { Error(format!($fmt)) };
|
||||
($fmt: literal, $($arg:tt)*) => { Error(format!($fmt, $($arg)*)) };
|
||||
|
|
@ -30,10 +34,14 @@ pub enum CompilerError<T> {
|
|||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct Error(pub(crate) String);
|
||||
|
||||
impl Error {
|
||||
pub fn new(msg: String) -> Self {
|
||||
impl SmirError for Error {
|
||||
fn new(msg: String) -> Self {
|
||||
Self(msg)
|
||||
}
|
||||
|
||||
fn from_internal<T: Debug>(err: T) -> Self {
|
||||
Self(format!("{err:?}"))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Error {
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ use std::io::Read;
|
|||
use serde::Serialize;
|
||||
use stable_mir::mir::mono::{Instance, StaticDef};
|
||||
use stable_mir::target::{Endian, MachineInfo};
|
||||
use stable_mir::ty::{Allocation, Binder, ExistentialTraitRef, IndexedVal, Ty};
|
||||
use stable_mir::{Error, with};
|
||||
use stable_mir::ty::{Allocation, Binder, ExistentialTraitRef, Ty};
|
||||
use stable_mir::{Error, IndexedVal, with};
|
||||
|
||||
use crate::stable_mir;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::io;
|
||||
|
||||
use rustc_smir::bridge::SmirError;
|
||||
use serde::Serialize;
|
||||
use stable_mir::abi::FnAbi;
|
||||
use stable_mir::crate_def::CrateDef;
|
||||
use stable_mir::mir::Body;
|
||||
use stable_mir::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, IndexedVal, Ty};
|
||||
use stable_mir::{CrateItem, DefId, Error, ItemKind, Opaque, Symbol, with};
|
||||
use stable_mir::ty::{Allocation, ClosureDef, ClosureKind, FnDef, GenericArgs, Ty};
|
||||
use stable_mir::{CrateItem, DefId, Error, IndexedVal, ItemKind, Opaque, Symbol, with};
|
||||
|
||||
use crate::stable_mir;
|
||||
use crate::{rustc_smir, stable_mir};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
|
||||
pub enum MonoItem {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ use fmt::{Display, Formatter};
|
|||
use stable_mir::mir::{
|
||||
Operand, Place, RawPtrKind, Rvalue, StatementKind, UnwindAction, VarDebugInfoContents,
|
||||
};
|
||||
use stable_mir::ty::{AdtKind, AssocKind, IndexedVal, MirConst, Ty, TyConst};
|
||||
use stable_mir::{Body, CrateDef, Mutability, with};
|
||||
use stable_mir::ty::{AdtKind, AssocKind, MirConst, Ty, TyConst};
|
||||
use stable_mir::{Body, CrateDef, IndexedVal, Mutability, with};
|
||||
|
||||
use super::{AggregateKind, AssertMessage, BinOp, BorrowKind, FakeBorrowKind, TerminatorKind};
|
||||
use crate::stable_mir;
|
||||
|
|
|
|||
|
|
@ -27,17 +27,25 @@
|
|||
use std::fmt::Debug;
|
||||
use std::{fmt, io};
|
||||
|
||||
pub(crate) use rustc_smir::IndexedVal;
|
||||
use rustc_smir::Tables;
|
||||
use rustc_smir::context::SmirCtxt;
|
||||
use serde::Serialize;
|
||||
use stable_mir::compiler_interface::with;
|
||||
pub use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType, DefId};
|
||||
pub use stable_mir::error::*;
|
||||
use stable_mir::mir::mono::StaticDef;
|
||||
use stable_mir::mir::{Body, Mutability};
|
||||
use stable_mir::ty::{AssocItem, FnDef, ForeignModuleDef, ImplDef, IndexedVal, Span, TraitDef, Ty};
|
||||
use stable_mir::ty::{
|
||||
AssocItem, FnDef, ForeignModuleDef, ImplDef, ProvenanceMap, Span, TraitDef, Ty,
|
||||
};
|
||||
use stable_mir::unstable::Stable;
|
||||
|
||||
use crate::stable_mir;
|
||||
use crate::{rustc_smir, stable_mir};
|
||||
|
||||
pub mod abi;
|
||||
mod alloc;
|
||||
pub(crate) mod unstable;
|
||||
#[macro_use]
|
||||
pub mod crate_def;
|
||||
pub mod compiler_interface;
|
||||
|
|
@ -237,3 +245,60 @@ impl std::fmt::Debug for Opaque {
|
|||
pub fn opaque<T: Debug>(value: &T) -> Opaque {
|
||||
Opaque(format!("{value:?}"))
|
||||
}
|
||||
|
||||
macro_rules! bridge_impl {
|
||||
($name: ident, $ty: ty) => {
|
||||
impl rustc_smir::bridge::$name<compiler_interface::BridgeTys> for $ty {
|
||||
fn new(def: stable_mir::DefId) -> Self {
|
||||
Self(def)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bridge_impl!(CrateItem, stable_mir::CrateItem);
|
||||
bridge_impl!(AdtDef, stable_mir::ty::AdtDef);
|
||||
bridge_impl!(ForeignModuleDef, stable_mir::ty::ForeignModuleDef);
|
||||
bridge_impl!(ForeignDef, stable_mir::ty::ForeignDef);
|
||||
bridge_impl!(FnDef, stable_mir::ty::FnDef);
|
||||
bridge_impl!(ClosureDef, stable_mir::ty::ClosureDef);
|
||||
bridge_impl!(CoroutineDef, stable_mir::ty::CoroutineDef);
|
||||
bridge_impl!(CoroutineClosureDef, stable_mir::ty::CoroutineClosureDef);
|
||||
bridge_impl!(AliasDef, stable_mir::ty::AliasDef);
|
||||
bridge_impl!(ParamDef, stable_mir::ty::ParamDef);
|
||||
bridge_impl!(BrNamedDef, stable_mir::ty::BrNamedDef);
|
||||
bridge_impl!(TraitDef, stable_mir::ty::TraitDef);
|
||||
bridge_impl!(GenericDef, stable_mir::ty::GenericDef);
|
||||
bridge_impl!(ConstDef, stable_mir::ty::ConstDef);
|
||||
bridge_impl!(ImplDef, stable_mir::ty::ImplDef);
|
||||
bridge_impl!(RegionDef, stable_mir::ty::RegionDef);
|
||||
bridge_impl!(CoroutineWitnessDef, stable_mir::ty::CoroutineWitnessDef);
|
||||
bridge_impl!(AssocDef, stable_mir::ty::AssocDef);
|
||||
bridge_impl!(OpaqueDef, stable_mir::ty::OpaqueDef);
|
||||
bridge_impl!(StaticDef, stable_mir::mir::mono::StaticDef);
|
||||
|
||||
impl rustc_smir::bridge::Prov<compiler_interface::BridgeTys> for stable_mir::ty::Prov {
|
||||
fn new(aid: stable_mir::mir::alloc::AllocId) -> Self {
|
||||
Self(aid)
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_smir::bridge::Allocation<compiler_interface::BridgeTys> for stable_mir::ty::Allocation {
|
||||
fn new<'tcx>(
|
||||
bytes: Vec<Option<u8>>,
|
||||
ptrs: Vec<(usize, rustc_middle::mir::interpret::AllocId)>,
|
||||
align: u64,
|
||||
mutability: rustc_middle::mir::Mutability,
|
||||
tables: &mut Tables<'tcx, compiler_interface::BridgeTys>,
|
||||
cx: &SmirCtxt<'tcx, compiler_interface::BridgeTys>,
|
||||
) -> Self {
|
||||
Self {
|
||||
bytes,
|
||||
provenance: ProvenanceMap {
|
||||
ptrs: ptrs.iter().map(|(i, aid)| (*i, tables.prov(*aid))).collect(),
|
||||
},
|
||||
align,
|
||||
mutability: mutability.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType};
|
|||
use stable_mir::mir::alloc::{AllocId, read_target_int, read_target_uint};
|
||||
use stable_mir::mir::mono::StaticDef;
|
||||
use stable_mir::target::MachineInfo;
|
||||
use stable_mir::{Filename, Opaque};
|
||||
use stable_mir::{Filename, IndexedVal, Opaque};
|
||||
|
||||
use super::abi::ReprOptions;
|
||||
use super::mir::{Body, Mutability, Safety};
|
||||
|
|
@ -298,6 +298,12 @@ pub struct LineInfo {
|
|||
pub end_col: usize,
|
||||
}
|
||||
|
||||
impl LineInfo {
|
||||
pub fn from(lines: (usize, usize, usize, usize)) -> Self {
|
||||
LineInfo { start_line: lines.0, start_col: lines.1, end_line: lines.2, end_col: lines.3 }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
pub enum TyKind {
|
||||
RigidTy(RigidTy),
|
||||
|
|
@ -1557,15 +1563,9 @@ pub enum PredicatePolarity {
|
|||
Negative,
|
||||
}
|
||||
|
||||
pub trait IndexedVal {
|
||||
fn to_val(index: usize) -> Self;
|
||||
|
||||
fn to_index(&self) -> usize;
|
||||
}
|
||||
|
||||
macro_rules! index_impl {
|
||||
($name:ident) => {
|
||||
impl IndexedVal for $name {
|
||||
impl stable_mir::IndexedVal for $name {
|
||||
fn to_val(index: usize) -> Self {
|
||||
$name(index)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,55 +5,76 @@
|
|||
|
||||
// Prefer importing stable_mir over internal rustc constructs to make this file more readable.
|
||||
|
||||
use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy, TyCtxt};
|
||||
use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy};
|
||||
use rustc_smir::Tables;
|
||||
use rustc_span::Symbol;
|
||||
use stable_mir::abi::Layout;
|
||||
use stable_mir::compiler_interface::BridgeTys;
|
||||
use stable_mir::mir::alloc::AllocId;
|
||||
use stable_mir::mir::mono::{Instance, MonoItem, StaticDef};
|
||||
use stable_mir::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp};
|
||||
use stable_mir::ty::{
|
||||
Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind,
|
||||
ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig,
|
||||
GenericArgKind, GenericArgs, IndexedVal, IntTy, MirConst, Movability, Pattern, Region, RigidTy,
|
||||
Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx,
|
||||
GenericArgKind, GenericArgs, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span,
|
||||
TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx,
|
||||
};
|
||||
use stable_mir::{CrateItem, CrateNum, DefId};
|
||||
use stable_mir::unstable::{InternalCx, RustcInternal};
|
||||
use stable_mir::{CrateItem, CrateNum, DefId, IndexedVal};
|
||||
|
||||
use super::RustcInternal;
|
||||
use crate::rustc_smir::Tables;
|
||||
use crate::stable_mir;
|
||||
use crate::{rustc_smir, stable_mir};
|
||||
|
||||
impl RustcInternal for CrateItem {
|
||||
type T<'tcx> = rustc_span::def_id::DefId;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
self.0.internal(tables, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for CrateNum {
|
||||
type T<'tcx> = rustc_span::def_id::CrateNum;
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
rustc_span::def_id::CrateNum::from_usize(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for DefId {
|
||||
type T<'tcx> = rustc_span::def_id::DefId;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tcx.lift(tables.def_ids[*self]).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for GenericArgs {
|
||||
type T<'tcx> = rustc_ty::GenericArgsRef<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
tcx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables, tcx)))
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
InternalCx::mk_args_from_iter(tcx, self.0.iter().map(|arg| arg.internal(tables, tcx)))
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for GenericArgKind {
|
||||
type T<'tcx> = rustc_ty::GenericArg<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
let arg: rustc_ty::GenericArg<'tcx> = match self {
|
||||
GenericArgKind::Lifetime(reg) => reg.internal(tables, tcx).into(),
|
||||
GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(),
|
||||
|
|
@ -65,29 +86,45 @@ impl RustcInternal for GenericArgKind {
|
|||
|
||||
impl RustcInternal for Region {
|
||||
type T<'tcx> = rustc_ty::Region<'tcx>;
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
// Cannot recover region. Use erased for now.
|
||||
tcx.lifetimes.re_erased
|
||||
tcx.lifetimes_re_erased()
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for Ty {
|
||||
type T<'tcx> = InternalTy<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tcx.lift(tables.types[*self]).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for TyConst {
|
||||
type T<'tcx> = InternalConst<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tcx.lift(tables.ty_consts[self.id]).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for Pattern {
|
||||
type T<'tcx> = rustc_ty::Pattern<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tcx.mk_pat(match self {
|
||||
Pattern::Range { start, end, include_end: _ } => rustc_ty::PatternKind::Range {
|
||||
start: start.as_ref().unwrap().internal(tables, tcx),
|
||||
|
|
@ -100,7 +137,11 @@ impl RustcInternal for Pattern {
|
|||
impl RustcInternal for RigidTy {
|
||||
type T<'tcx> = rustc_ty::TyKind<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
RigidTy::Bool => rustc_ty::TyKind::Bool,
|
||||
RigidTy::Char => rustc_ty::TyKind::Char,
|
||||
|
|
@ -164,7 +205,11 @@ impl RustcInternal for RigidTy {
|
|||
impl RustcInternal for IntTy {
|
||||
type T<'tcx> = rustc_ty::IntTy;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
IntTy::Isize => rustc_ty::IntTy::Isize,
|
||||
IntTy::I8 => rustc_ty::IntTy::I8,
|
||||
|
|
@ -179,7 +224,11 @@ impl RustcInternal for IntTy {
|
|||
impl RustcInternal for UintTy {
|
||||
type T<'tcx> = rustc_ty::UintTy;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
UintTy::Usize => rustc_ty::UintTy::Usize,
|
||||
UintTy::U8 => rustc_ty::UintTy::U8,
|
||||
|
|
@ -194,7 +243,11 @@ impl RustcInternal for UintTy {
|
|||
impl RustcInternal for FloatTy {
|
||||
type T<'tcx> = rustc_ty::FloatTy;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
FloatTy::F16 => rustc_ty::FloatTy::F16,
|
||||
FloatTy::F32 => rustc_ty::FloatTy::F32,
|
||||
|
|
@ -207,7 +260,11 @@ impl RustcInternal for FloatTy {
|
|||
impl RustcInternal for Mutability {
|
||||
type T<'tcx> = rustc_ty::Mutability;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
Mutability::Not => rustc_ty::Mutability::Not,
|
||||
Mutability::Mut => rustc_ty::Mutability::Mut,
|
||||
|
|
@ -218,7 +275,11 @@ impl RustcInternal for Mutability {
|
|||
impl RustcInternal for Movability {
|
||||
type T<'tcx> = rustc_ty::Movability;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
Movability::Static => rustc_ty::Movability::Static,
|
||||
Movability::Movable => rustc_ty::Movability::Movable,
|
||||
|
|
@ -229,7 +290,11 @@ impl RustcInternal for Movability {
|
|||
impl RustcInternal for RawPtrKind {
|
||||
type T<'tcx> = rustc_middle::mir::RawPtrKind;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
RawPtrKind::Mut => rustc_middle::mir::RawPtrKind::Mut,
|
||||
RawPtrKind::Const => rustc_middle::mir::RawPtrKind::Const,
|
||||
|
|
@ -241,7 +306,11 @@ impl RustcInternal for RawPtrKind {
|
|||
impl RustcInternal for FnSig {
|
||||
type T<'tcx> = rustc_ty::FnSig<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tcx.lift(rustc_ty::FnSig {
|
||||
inputs_and_output: tcx.mk_type_list(&self.inputs_and_output.internal(tables, tcx)),
|
||||
c_variadic: self.c_variadic,
|
||||
|
|
@ -255,7 +324,11 @@ impl RustcInternal for FnSig {
|
|||
impl RustcInternal for VariantIdx {
|
||||
type T<'tcx> = rustc_abi::VariantIdx;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
rustc_abi::VariantIdx::from(self.to_index())
|
||||
}
|
||||
}
|
||||
|
|
@ -263,14 +336,22 @@ impl RustcInternal for VariantIdx {
|
|||
impl RustcInternal for VariantDef {
|
||||
type T<'tcx> = &'tcx rustc_ty::VariantDef;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
self.adt_def.internal(tables, tcx).variant(self.idx.internal(tables, tcx))
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for MirConst {
|
||||
type T<'tcx> = rustc_middle::mir::Const<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
let constant = tables.mir_consts[self.id];
|
||||
match constant {
|
||||
rustc_middle::mir::Const::Ty(ty, ct) => {
|
||||
|
|
@ -292,7 +373,11 @@ impl RustcInternal for MirConst {
|
|||
impl RustcInternal for MonoItem {
|
||||
type T<'tcx> = rustc_middle::mir::mono::MonoItem<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
use rustc_middle::mir::mono as rustc_mono;
|
||||
match self {
|
||||
MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables, tcx)),
|
||||
|
|
@ -307,7 +392,11 @@ impl RustcInternal for MonoItem {
|
|||
impl RustcInternal for Instance {
|
||||
type T<'tcx> = rustc_ty::Instance<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tcx.lift(tables.instances[self.def]).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
@ -315,7 +404,11 @@ impl RustcInternal for Instance {
|
|||
impl RustcInternal for StaticDef {
|
||||
type T<'tcx> = rustc_span::def_id::DefId;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
self.0.internal(tables, tcx)
|
||||
}
|
||||
}
|
||||
|
|
@ -328,7 +421,11 @@ where
|
|||
{
|
||||
type T<'tcx> = rustc_ty::Binder<'tcx, T::T<'tcx>>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
rustc_ty::Binder::bind_with_vars(
|
||||
self.value.internal(tables, tcx),
|
||||
tcx.mk_bound_variable_kinds_from_iter(
|
||||
|
|
@ -341,7 +438,11 @@ where
|
|||
impl RustcInternal for BoundVariableKind {
|
||||
type T<'tcx> = rustc_ty::BoundVariableKind;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
BoundVariableKind::Ty(kind) => rustc_ty::BoundVariableKind::Ty(match kind {
|
||||
BoundTyKind::Anon => rustc_ty::BoundTyKind::Anon,
|
||||
|
|
@ -366,7 +467,11 @@ impl RustcInternal for BoundVariableKind {
|
|||
impl RustcInternal for DynKind {
|
||||
type T<'tcx> = rustc_ty::DynKind;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
DynKind::Dyn => rustc_ty::DynKind::Dyn,
|
||||
}
|
||||
|
|
@ -376,7 +481,11 @@ impl RustcInternal for DynKind {
|
|||
impl RustcInternal for ExistentialPredicate {
|
||||
type T<'tcx> = rustc_ty::ExistentialPredicate<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
ExistentialPredicate::Trait(trait_ref) => {
|
||||
rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables, tcx))
|
||||
|
|
@ -394,9 +503,13 @@ impl RustcInternal for ExistentialPredicate {
|
|||
impl RustcInternal for ExistentialProjection {
|
||||
type T<'tcx> = rustc_ty::ExistentialProjection<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
rustc_ty::ExistentialProjection::new_from_args(
|
||||
tcx,
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
use rustc_smir::context::SmirExistentialProjection;
|
||||
tcx.new_from_args(
|
||||
self.def_id.0.internal(tables, tcx),
|
||||
self.generic_args.internal(tables, tcx),
|
||||
self.term.internal(tables, tcx),
|
||||
|
|
@ -407,7 +520,11 @@ impl RustcInternal for ExistentialProjection {
|
|||
impl RustcInternal for TermKind {
|
||||
type T<'tcx> = rustc_ty::Term<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
TermKind::Type(ty) => ty.internal(tables, tcx).into(),
|
||||
TermKind::Const(cnst) => cnst.internal(tables, tcx).into(),
|
||||
|
|
@ -418,9 +535,13 @@ impl RustcInternal for TermKind {
|
|||
impl RustcInternal for ExistentialTraitRef {
|
||||
type T<'tcx> = rustc_ty::ExistentialTraitRef<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
rustc_ty::ExistentialTraitRef::new_from_args(
|
||||
tcx,
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
use rustc_smir::context::SmirExistentialTraitRef;
|
||||
tcx.new_from_args(
|
||||
self.def_id.0.internal(tables, tcx),
|
||||
self.generic_args.internal(tables, tcx),
|
||||
)
|
||||
|
|
@ -430,18 +551,23 @@ impl RustcInternal for ExistentialTraitRef {
|
|||
impl RustcInternal for TraitRef {
|
||||
type T<'tcx> = rustc_ty::TraitRef<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
rustc_ty::TraitRef::new_from_args(
|
||||
tcx,
|
||||
self.def_id.0.internal(tables, tcx),
|
||||
self.args().internal(tables, tcx),
|
||||
)
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
use rustc_smir::context::SmirTraitRef;
|
||||
tcx.new_from_args(self.def_id.0.internal(tables, tcx), self.args().internal(tables, tcx))
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for AllocId {
|
||||
type T<'tcx> = rustc_middle::mir::interpret::AllocId;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tcx.lift(tables.alloc_ids[*self]).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
@ -449,7 +575,11 @@ impl RustcInternal for AllocId {
|
|||
impl RustcInternal for ClosureKind {
|
||||
type T<'tcx> = rustc_ty::ClosureKind;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
ClosureKind::Fn => rustc_ty::ClosureKind::Fn,
|
||||
ClosureKind::FnMut => rustc_ty::ClosureKind::FnMut,
|
||||
|
|
@ -460,15 +590,23 @@ impl RustcInternal for ClosureKind {
|
|||
|
||||
impl RustcInternal for AdtDef {
|
||||
type T<'tcx> = rustc_ty::AdtDef<'tcx>;
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
tcx.adt_def(self.0.internal(tables, tcx))
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
InternalCx::adt_def(tcx, self.0.internal(tables, tcx))
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for Abi {
|
||||
type T<'tcx> = rustc_abi::ExternAbi;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match *self {
|
||||
Abi::Rust => rustc_abi::ExternAbi::Rust,
|
||||
Abi::C { unwind } => rustc_abi::ExternAbi::C { unwind },
|
||||
|
|
@ -504,7 +642,11 @@ impl RustcInternal for Abi {
|
|||
impl RustcInternal for Safety {
|
||||
type T<'tcx> = rustc_hir::Safety;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
Safety::Unsafe => rustc_hir::Safety::Unsafe,
|
||||
Safety::Safe => rustc_hir::Safety::Safe,
|
||||
|
|
@ -514,15 +656,23 @@ impl RustcInternal for Safety {
|
|||
impl RustcInternal for Span {
|
||||
type T<'tcx> = rustc_span::Span;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
tables[*self]
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tables.spans[*self]
|
||||
}
|
||||
}
|
||||
|
||||
impl RustcInternal for Layout {
|
||||
type T<'tcx> = rustc_abi::Layout<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
tcx.lift(tables.layouts[*self]).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
@ -530,7 +680,11 @@ impl RustcInternal for Layout {
|
|||
impl RustcInternal for Place {
|
||||
type T<'tcx> = rustc_middle::mir::Place<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
rustc_middle::mir::Place {
|
||||
local: rustc_middle::mir::Local::from_usize(self.local),
|
||||
projection: tcx.mk_place_elems(&self.projection.internal(tables, tcx)),
|
||||
|
|
@ -541,7 +695,11 @@ impl RustcInternal for Place {
|
|||
impl RustcInternal for ProjectionElem {
|
||||
type T<'tcx> = rustc_middle::mir::PlaceElem<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
ProjectionElem::Deref => rustc_middle::mir::PlaceElem::Deref,
|
||||
ProjectionElem::Field(idx, ty) => {
|
||||
|
|
@ -574,7 +732,11 @@ impl RustcInternal for ProjectionElem {
|
|||
impl RustcInternal for BinOp {
|
||||
type T<'tcx> = rustc_middle::mir::BinOp;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
BinOp::Add => rustc_middle::mir::BinOp::Add,
|
||||
BinOp::AddUnchecked => rustc_middle::mir::BinOp::AddUnchecked,
|
||||
|
|
@ -606,7 +768,11 @@ impl RustcInternal for BinOp {
|
|||
impl RustcInternal for UnOp {
|
||||
type T<'tcx> = rustc_middle::mir::UnOp;
|
||||
|
||||
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'_, BridgeTys>,
|
||||
_tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
match self {
|
||||
UnOp::Not => rustc_middle::mir::UnOp::Not,
|
||||
UnOp::Neg => rustc_middle::mir::UnOp::Neg,
|
||||
|
|
@ -621,7 +787,11 @@ where
|
|||
{
|
||||
type T<'tcx> = T::T<'tcx>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
(*self).internal(tables, tcx)
|
||||
}
|
||||
}
|
||||
|
|
@ -632,7 +802,11 @@ where
|
|||
{
|
||||
type T<'tcx> = Option<T::T<'tcx>>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
self.as_ref().map(|inner| inner.internal(tables, tcx))
|
||||
}
|
||||
}
|
||||
|
|
@ -643,7 +817,11 @@ where
|
|||
{
|
||||
type T<'tcx> = Vec<T::T<'tcx>>;
|
||||
|
||||
fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx> {
|
||||
self.iter().map(|e| e.internal(tables, tcx)).collect()
|
||||
}
|
||||
}
|
||||
111
compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs
Normal file
111
compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
//! This module holds the logic to convert rustc internal ADTs into stable mir ADTs.
|
||||
//!
|
||||
//! The conversion from stable to internal is not meant to be complete,
|
||||
//! and it should be added as when needed to be passed as input to rustc_smir functions.
|
||||
//!
|
||||
//! For contributors, please make sure to avoid calling rustc's internal functions and queries.
|
||||
//! These should be done via `rustc_smir` APIs, but it's possible to access ADT fields directly.
|
||||
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use rustc_smir::Tables;
|
||||
use rustc_smir::context::SmirCtxt;
|
||||
use stable_mir::compiler_interface::BridgeTys;
|
||||
|
||||
use super::Stable;
|
||||
use crate::{rustc_smir, stable_mir};
|
||||
|
||||
mod internal;
|
||||
mod stable;
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for &T
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = T::T;
|
||||
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
(*self).stable(tables, cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for Option<T>
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = Option<T::T>;
|
||||
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
self.as_ref().map(|value| value.stable(tables, cx))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T, E> Stable<'tcx> for Result<T, E>
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
E: Stable<'tcx>,
|
||||
{
|
||||
type T = Result<T::T, E::T>;
|
||||
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
Ok(val) => Ok(val.stable(tables, cx)),
|
||||
Err(error) => Err(error.stable(tables, cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for &[T]
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = Vec<T::T>;
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
self.iter().map(|e| e.stable(tables, cx)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T, U> Stable<'tcx> for (T, U)
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
U: Stable<'tcx>,
|
||||
{
|
||||
type T = (T::T, U::T);
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
(self.0.stable(tables, cx), self.1.stable(tables, cx))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Stable<'tcx> for RangeInclusive<T>
|
||||
where
|
||||
T: Stable<'tcx>,
|
||||
{
|
||||
type T = RangeInclusive<T::T>;
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
RangeInclusive::new(self.start().stable(tables, cx), self.end().stable(tables, cx))
|
||||
}
|
||||
}
|
||||
|
|
@ -4,22 +4,25 @@
|
|||
|
||||
use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
|
||||
use rustc_middle::ty;
|
||||
use rustc_smir::Tables;
|
||||
use rustc_smir::context::SmirCtxt;
|
||||
use rustc_target::callconv;
|
||||
use stable_mir::abi::{
|
||||
AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,
|
||||
IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar,
|
||||
TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange,
|
||||
};
|
||||
use stable_mir::opaque;
|
||||
use stable_mir::compiler_interface::BridgeTys;
|
||||
use stable_mir::target::MachineSize as Size;
|
||||
use stable_mir::ty::{Align, IndexedVal, VariantIdx};
|
||||
use stable_mir::ty::{Align, VariantIdx};
|
||||
use stable_mir::unstable::Stable;
|
||||
use stable_mir::{IndexedVal, opaque};
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use crate::stable_mir;
|
||||
use crate::{rustc_smir, stable_mir};
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx {
|
||||
type T = VariantIdx;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
VariantIdx::to_val(self.as_usize())
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +30,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
|
||||
type T = stable_mir::target::Endian;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::Endian::Little => stable_mir::target::Endian::Little,
|
||||
rustc_abi::Endian::Big => stable_mir::target::Endian::Big,
|
||||
|
|
@ -38,29 +41,41 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
|
||||
type T = TyAndLayout;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
TyAndLayout { ty: self.ty.stable(tables), layout: self.layout.stable(tables) }
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
TyAndLayout { ty: self.ty.stable(tables, cx), layout: self.layout.stable(tables, cx) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_abi::Layout<'tcx> {
|
||||
type T = Layout;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
tables.layout_id(tables.tcx.lift(*self).unwrap())
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
tables.layout_id(cx.lift(*self).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
|
||||
type T = LayoutShape;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
LayoutShape {
|
||||
fields: self.fields.stable(tables),
|
||||
variants: self.variants.stable(tables),
|
||||
abi: self.backend_repr.stable(tables),
|
||||
abi_align: self.align.abi.stable(tables),
|
||||
size: self.size.stable(tables),
|
||||
fields: self.fields.stable(tables, cx),
|
||||
variants: self.variants.stable(tables, cx),
|
||||
abi: self.backend_repr.stable(tables, cx),
|
||||
abi_align: self.align.abi.stable(tables, cx),
|
||||
size: self.size.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -68,14 +83,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi
|
|||
impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> {
|
||||
type T = FnAbi;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
assert!(self.args.len() >= self.fixed_count as usize);
|
||||
assert!(!self.c_variadic || matches!(self.conv, CanonAbi::C));
|
||||
FnAbi {
|
||||
args: self.args.as_ref().stable(tables),
|
||||
ret: self.ret.stable(tables),
|
||||
args: self.args.as_ref().stable(tables, cx),
|
||||
ret: self.ret.stable(tables, cx),
|
||||
fixed_count: self.fixed_count,
|
||||
conv: self.conv.stable(tables),
|
||||
conv: self.conv.stable(tables, cx),
|
||||
c_variadic: self.c_variadic,
|
||||
}
|
||||
}
|
||||
|
|
@ -84,11 +103,15 @@ impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> {
|
|||
impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> {
|
||||
type T = ArgAbi;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
ArgAbi {
|
||||
ty: self.layout.ty.stable(tables),
|
||||
layout: self.layout.layout.stable(tables),
|
||||
mode: self.mode.stable(tables),
|
||||
ty: self.layout.ty.stable(tables, cx),
|
||||
layout: self.layout.layout.stable(tables, cx),
|
||||
mode: self.mode.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -96,7 +119,7 @@ impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> {
|
|||
impl<'tcx> Stable<'tcx> for CanonAbi {
|
||||
type T = CallConvention;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
match self {
|
||||
CanonAbi::C => CallConvention::C,
|
||||
CanonAbi::Rust => CallConvention::Rust,
|
||||
|
|
@ -132,7 +155,7 @@ impl<'tcx> Stable<'tcx> for CanonAbi {
|
|||
impl<'tcx> Stable<'tcx> for callconv::PassMode {
|
||||
type T = PassMode;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
match self {
|
||||
callconv::PassMode::Ignore => PassMode::Ignore,
|
||||
callconv::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)),
|
||||
|
|
@ -154,15 +177,19 @@ impl<'tcx> Stable<'tcx> for callconv::PassMode {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> {
|
||||
type T = FieldsShape;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::FieldsShape::Primitive => FieldsShape::Primitive,
|
||||
rustc_abi::FieldsShape::Union(count) => FieldsShape::Union(*count),
|
||||
rustc_abi::FieldsShape::Array { stride, count } => {
|
||||
FieldsShape::Array { stride: stride.stable(tables), count: *count }
|
||||
FieldsShape::Array { stride: stride.stable(tables, cx), count: *count }
|
||||
}
|
||||
rustc_abi::FieldsShape::Arbitrary { offsets, .. } => {
|
||||
FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables) }
|
||||
FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables, cx) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -171,18 +198,22 @@ impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
|
||||
type T = VariantsShape;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::Variants::Single { index } => {
|
||||
VariantsShape::Single { index: index.stable(tables) }
|
||||
VariantsShape::Single { index: index.stable(tables, cx) }
|
||||
}
|
||||
rustc_abi::Variants::Empty => VariantsShape::Empty,
|
||||
rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => {
|
||||
VariantsShape::Multiple {
|
||||
tag: tag.stable(tables),
|
||||
tag_encoding: tag_encoding.stable(tables),
|
||||
tag_field: tag_field.stable(tables),
|
||||
variants: variants.iter().as_slice().stable(tables),
|
||||
tag: tag.stable(tables, cx),
|
||||
tag_encoding: tag_encoding.stable(tables, cx),
|
||||
tag_field: tag_field.stable(tables, cx),
|
||||
variants: variants.iter().as_slice().stable(tables, cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -192,13 +223,17 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
|
||||
type T = TagEncoding;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::TagEncoding::Direct => TagEncoding::Direct,
|
||||
rustc_abi::TagEncoding::Niche { untagged_variant, niche_variants, niche_start } => {
|
||||
TagEncoding::Niche {
|
||||
untagged_variant: untagged_variant.stable(tables),
|
||||
niche_variants: niche_variants.stable(tables),
|
||||
untagged_variant: untagged_variant.stable(tables, cx),
|
||||
niche_variants: niche_variants.stable(tables, cx),
|
||||
niche_start: *niche_start,
|
||||
}
|
||||
}
|
||||
|
|
@ -209,14 +244,18 @@ impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
|
||||
type T = ValueAbi;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match *self {
|
||||
rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)),
|
||||
rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables, cx)),
|
||||
rustc_abi::BackendRepr::ScalarPair(first, second) => {
|
||||
ValueAbi::ScalarPair(first.stable(tables), second.stable(tables))
|
||||
ValueAbi::ScalarPair(first.stable(tables, cx), second.stable(tables, cx))
|
||||
}
|
||||
rustc_abi::BackendRepr::SimdVector { element, count } => {
|
||||
ValueAbi::Vector { element: element.stable(tables), count }
|
||||
ValueAbi::Vector { element: element.stable(tables, cx), count }
|
||||
}
|
||||
rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized },
|
||||
}
|
||||
|
|
@ -226,7 +265,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::Size {
|
||||
type T = Size;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
Size::from_bits(self.bits_usize())
|
||||
}
|
||||
}
|
||||
|
|
@ -234,7 +273,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Size {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::Align {
|
||||
type T = Align;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
self.bytes()
|
||||
}
|
||||
}
|
||||
|
|
@ -242,13 +281,17 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Align {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::Scalar {
|
||||
type T = Scalar;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::Scalar::Initialized { value, valid_range } => Scalar::Initialized {
|
||||
value: value.stable(tables),
|
||||
valid_range: valid_range.stable(tables),
|
||||
value: value.stable(tables, cx),
|
||||
valid_range: valid_range.stable(tables, cx),
|
||||
},
|
||||
rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables) },
|
||||
rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables, cx) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -256,15 +299,19 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Scalar {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
|
||||
type T = Primitive;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::Primitive::Int(length, signed) => {
|
||||
Primitive::Int { length: length.stable(tables), signed: *signed }
|
||||
Primitive::Int { length: length.stable(tables, cx), signed: *signed }
|
||||
}
|
||||
rustc_abi::Primitive::Float(length) => {
|
||||
Primitive::Float { length: length.stable(tables) }
|
||||
Primitive::Float { length: length.stable(tables, cx) }
|
||||
}
|
||||
rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables)),
|
||||
rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables, cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -272,7 +319,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace {
|
||||
type T = AddressSpace;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
AddressSpace(self.0)
|
||||
}
|
||||
}
|
||||
|
|
@ -280,7 +327,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
|
||||
type T = IntegerLength;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::Integer::I8 => IntegerLength::I8,
|
||||
rustc_abi::Integer::I16 => IntegerLength::I16,
|
||||
|
|
@ -294,7 +341,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::Float {
|
||||
type T = FloatLength;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::Float::F16 => FloatLength::F16,
|
||||
rustc_abi::Float::F32 => FloatLength::F32,
|
||||
|
|
@ -307,7 +354,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Float {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
|
||||
type T = WrappingRange;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
WrappingRange { start: self.start, end: self.end }
|
||||
}
|
||||
}
|
||||
|
|
@ -315,7 +362,11 @@ impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::ReprFlags {
|
||||
type T = ReprFlags;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
_tables: &mut Tables<'cx, BridgeTys>,
|
||||
_cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
ReprFlags {
|
||||
is_simd: self.intersects(Self::IS_SIMD),
|
||||
is_c: self.intersects(Self::IS_C),
|
||||
|
|
@ -328,11 +379,15 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ReprFlags {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType {
|
||||
type T = IntegerType;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
rustc_abi::IntegerType::Pointer(signed) => IntegerType::Pointer { is_signed: *signed },
|
||||
rustc_abi::IntegerType::Fixed(integer, signed) => {
|
||||
IntegerType::Fixed { length: integer.stable(tables), is_signed: *signed }
|
||||
IntegerType::Fixed { length: integer.stable(tables, cx), is_signed: *signed }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -341,12 +396,16 @@ impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType {
|
|||
impl<'tcx> Stable<'tcx> for rustc_abi::ReprOptions {
|
||||
type T = ReprOptions;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
ReprOptions {
|
||||
int: self.int.map(|int| int.stable(tables)),
|
||||
align: self.align.map(|align| align.stable(tables)),
|
||||
pack: self.pack.map(|pack| pack.stable(tables)),
|
||||
flags: self.flags.stable(tables),
|
||||
int: self.int.map(|int| int.stable(tables, cx)),
|
||||
align: self.align.map(|align| align.stable(tables, cx)),
|
||||
pack: self.pack.map(|pack| pack.stable(tables, cx)),
|
||||
flags: self.flags.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,56 +1,67 @@
|
|||
//! Conversion of internal Rust compiler `mir` items to stable ones.
|
||||
|
||||
use rustc_middle::mir::interpret::alloc_range;
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
use rustc_middle::{bug, mir};
|
||||
use rustc_smir::Tables;
|
||||
use rustc_smir::bridge::SmirError;
|
||||
use rustc_smir::context::SmirCtxt;
|
||||
use stable_mir::compiler_interface::BridgeTys;
|
||||
use stable_mir::mir::alloc::GlobalAlloc;
|
||||
use stable_mir::mir::{ConstOperand, Statement, UserTypeProjection, VarDebugInfoFragment};
|
||||
use stable_mir::ty::{Allocation, ConstantKind, MirConst};
|
||||
use stable_mir::{Error, opaque};
|
||||
use stable_mir::unstable::Stable;
|
||||
use stable_mir::{Error, alloc, opaque};
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables, alloc};
|
||||
use crate::stable_mir;
|
||||
use crate::{rustc_smir, stable_mir};
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
|
||||
type T = stable_mir::mir::Body;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
stable_mir::mir::Body::new(
|
||||
self.basic_blocks
|
||||
.iter()
|
||||
.map(|block| stable_mir::mir::BasicBlock {
|
||||
terminator: block.terminator().stable(tables),
|
||||
terminator: block.terminator().stable(tables, cx),
|
||||
statements: block
|
||||
.statements
|
||||
.iter()
|
||||
.map(|statement| statement.stable(tables))
|
||||
.map(|statement| statement.stable(tables, cx))
|
||||
.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),
|
||||
ty: decl.ty.stable(tables, cx),
|
||||
span: decl.source_info.span.stable(tables, cx),
|
||||
mutability: decl.mutability.stable(tables, cx),
|
||||
})
|
||||
.collect(),
|
||||
self.arg_count,
|
||||
self.var_debug_info.iter().map(|info| info.stable(tables)).collect(),
|
||||
self.spread_arg.stable(tables),
|
||||
self.span.stable(tables),
|
||||
self.var_debug_info.iter().map(|info| info.stable(tables, cx)).collect(),
|
||||
self.spread_arg.stable(tables, cx),
|
||||
self.span.stable(tables, cx),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
|
||||
type T = stable_mir::mir::VarDebugInfo;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> 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),
|
||||
source_info: self.source_info.stable(tables, cx),
|
||||
composite: self.composite.as_ref().map(|composite| composite.stable(tables, cx)),
|
||||
value: self.value.stable(tables, cx),
|
||||
argument_index: self.argument_index,
|
||||
}
|
||||
}
|
||||
|
|
@ -58,40 +69,59 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
|
||||
type T = stable_mir::mir::Statement;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
Statement {
|
||||
kind: self.kind.stable(tables, cx),
|
||||
span: self.source_info.span.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::SourceInfo {
|
||||
type T = stable_mir::mir::SourceInfo;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
stable_mir::mir::SourceInfo { span: self.span.stable(tables), scope: self.scope.into() }
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
stable_mir::mir::SourceInfo { span: self.span.stable(tables, cx), scope: self.scope.into() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
|
||||
type T = stable_mir::mir::VarDebugInfoFragment;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
VarDebugInfoFragment {
|
||||
ty: self.ty.stable(tables),
|
||||
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
|
||||
ty: self.ty.stable(tables, cx),
|
||||
projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
|
||||
type T = stable_mir::mir::VarDebugInfoContents;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
mir::VarDebugInfoContents::Place(place) => {
|
||||
stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables))
|
||||
stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables, cx))
|
||||
}
|
||||
mir::VarDebugInfoContents::Const(const_operand) => {
|
||||
let op = ConstOperand {
|
||||
span: const_operand.span.stable(tables),
|
||||
span: const_operand.span.stable(tables, cx),
|
||||
user_ty: const_operand.user_ty.map(|index| index.as_usize()),
|
||||
const_: const_operand.const_.stable(tables),
|
||||
const_: const_operand.const_.stable(tables, cx),
|
||||
};
|
||||
stable_mir::mir::VarDebugInfoContents::Const(op)
|
||||
}
|
||||
|
|
@ -101,53 +131,58 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
|
||||
type T = stable_mir::mir::StatementKind;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign(
|
||||
assign.0.stable(tables),
|
||||
assign.1.stable(tables),
|
||||
assign.0.stable(tables, cx),
|
||||
assign.1.stable(tables, cx),
|
||||
),
|
||||
mir::StatementKind::FakeRead(fake_read_place) => {
|
||||
stable_mir::mir::StatementKind::FakeRead(
|
||||
fake_read_place.0.stable(tables),
|
||||
fake_read_place.1.stable(tables),
|
||||
fake_read_place.0.stable(tables, cx),
|
||||
fake_read_place.1.stable(tables, cx),
|
||||
)
|
||||
}
|
||||
mir::StatementKind::SetDiscriminant { place, variant_index } => {
|
||||
stable_mir::mir::StatementKind::SetDiscriminant {
|
||||
place: place.as_ref().stable(tables),
|
||||
variant_index: variant_index.stable(tables),
|
||||
place: place.as_ref().stable(tables, cx),
|
||||
variant_index: variant_index.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
mir::StatementKind::Deinit(place) => {
|
||||
stable_mir::mir::StatementKind::Deinit(place.stable(tables))
|
||||
stable_mir::mir::StatementKind::Deinit(place.stable(tables, cx))
|
||||
}
|
||||
|
||||
mir::StatementKind::StorageLive(place) => {
|
||||
stable_mir::mir::StatementKind::StorageLive(place.stable(tables))
|
||||
stable_mir::mir::StatementKind::StorageLive(place.stable(tables, cx))
|
||||
}
|
||||
|
||||
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))
|
||||
stable_mir::mir::StatementKind::StorageDead(place.stable(tables, cx))
|
||||
}
|
||||
mir::StatementKind::Retag(retag, place) => stable_mir::mir::StatementKind::Retag(
|
||||
retag.stable(tables, cx),
|
||||
place.stable(tables, cx),
|
||||
),
|
||||
mir::StatementKind::PlaceMention(place) => {
|
||||
stable_mir::mir::StatementKind::PlaceMention(place.stable(tables))
|
||||
stable_mir::mir::StatementKind::PlaceMention(place.stable(tables, cx))
|
||||
}
|
||||
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),
|
||||
place: place_projection.as_ref().0.stable(tables, cx),
|
||||
projections: place_projection.as_ref().1.stable(tables, cx),
|
||||
variance: variance.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
mir::StatementKind::Coverage(coverage) => {
|
||||
stable_mir::mir::StatementKind::Coverage(opaque(coverage))
|
||||
}
|
||||
mir::StatementKind::Intrinsic(intrinstic) => {
|
||||
stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables))
|
||||
stable_mir::mir::StatementKind::Intrinsic(intrinstic.stable(tables, cx))
|
||||
}
|
||||
mir::StatementKind::ConstEvalCounter => {
|
||||
stable_mir::mir::StatementKind::ConstEvalCounter
|
||||
|
|
@ -163,61 +198,68 @@ impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
|
||||
type T = stable_mir::mir::Rvalue;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
use rustc_middle::mir::Rvalue::*;
|
||||
match self {
|
||||
Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
|
||||
Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables, cx)),
|
||||
Repeat(op, len) => {
|
||||
let len = len.stable(tables);
|
||||
stable_mir::mir::Rvalue::Repeat(op.stable(tables), len)
|
||||
let len = len.stable(tables, cx);
|
||||
stable_mir::mir::Rvalue::Repeat(op.stable(tables, cx), len)
|
||||
}
|
||||
Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref(
|
||||
region.stable(tables),
|
||||
kind.stable(tables),
|
||||
place.stable(tables),
|
||||
region.stable(tables, cx),
|
||||
kind.stable(tables, cx),
|
||||
place.stable(tables, cx),
|
||||
),
|
||||
ThreadLocalRef(def_id) => {
|
||||
stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id))
|
||||
}
|
||||
RawPtr(mutability, place) => {
|
||||
stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables))
|
||||
}
|
||||
Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)),
|
||||
RawPtr(mutability, place) => stable_mir::mir::Rvalue::AddressOf(
|
||||
mutability.stable(tables, cx),
|
||||
place.stable(tables, cx),
|
||||
),
|
||||
Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables, cx)),
|
||||
Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast(
|
||||
cast_kind.stable(tables),
|
||||
op.stable(tables),
|
||||
ty.stable(tables),
|
||||
cast_kind.stable(tables, cx),
|
||||
op.stable(tables, cx),
|
||||
ty.stable(tables, cx),
|
||||
),
|
||||
BinaryOp(bin_op, ops) => {
|
||||
if let Some(bin_op) = bin_op.overflowing_to_wrapping() {
|
||||
stable_mir::mir::Rvalue::CheckedBinaryOp(
|
||||
bin_op.stable(tables),
|
||||
ops.0.stable(tables),
|
||||
ops.1.stable(tables),
|
||||
bin_op.stable(tables, cx),
|
||||
ops.0.stable(tables, cx),
|
||||
ops.1.stable(tables, cx),
|
||||
)
|
||||
} else {
|
||||
stable_mir::mir::Rvalue::BinaryOp(
|
||||
bin_op.stable(tables),
|
||||
ops.0.stable(tables),
|
||||
ops.1.stable(tables),
|
||||
bin_op.stable(tables, cx),
|
||||
ops.0.stable(tables, cx),
|
||||
ops.1.stable(tables, cx),
|
||||
)
|
||||
}
|
||||
}
|
||||
NullaryOp(null_op, ty) => {
|
||||
stable_mir::mir::Rvalue::NullaryOp(null_op.stable(tables), ty.stable(tables))
|
||||
}
|
||||
NullaryOp(null_op, ty) => stable_mir::mir::Rvalue::NullaryOp(
|
||||
null_op.stable(tables, cx),
|
||||
ty.stable(tables, cx),
|
||||
),
|
||||
UnaryOp(un_op, op) => {
|
||||
stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables))
|
||||
stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables, cx), op.stable(tables, cx))
|
||||
}
|
||||
Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables)),
|
||||
Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables, cx)),
|
||||
Aggregate(agg_kind, operands) => {
|
||||
let operands = operands.iter().map(|op| op.stable(tables)).collect();
|
||||
stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables), operands)
|
||||
let operands = operands.iter().map(|op| op.stable(tables, cx)).collect();
|
||||
stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables, cx), 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)),
|
||||
ShallowInitBox(op, ty) => stable_mir::mir::Rvalue::ShallowInitBox(
|
||||
op.stable(tables, cx),
|
||||
ty.stable(tables, cx),
|
||||
),
|
||||
CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables, cx)),
|
||||
WrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"),
|
||||
}
|
||||
}
|
||||
|
|
@ -225,7 +267,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::Mutability {
|
||||
type T = stable_mir::mir::Mutability;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_hir::Mutability::*;
|
||||
match *self {
|
||||
Not => stable_mir::mir::Mutability::Not,
|
||||
|
|
@ -236,7 +278,7 @@ impl<'tcx> Stable<'tcx> for mir::Mutability {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::RawPtrKind {
|
||||
type T = stable_mir::mir::RawPtrKind;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use mir::RawPtrKind::*;
|
||||
match *self {
|
||||
Const => stable_mir::mir::RawPtrKind::Const,
|
||||
|
|
@ -248,19 +290,23 @@ impl<'tcx> Stable<'tcx> for mir::RawPtrKind {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::BorrowKind {
|
||||
type T = stable_mir::mir::BorrowKind;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
use rustc_middle::mir::BorrowKind::*;
|
||||
match *self {
|
||||
Shared => stable_mir::mir::BorrowKind::Shared,
|
||||
Fake(kind) => stable_mir::mir::BorrowKind::Fake(kind.stable(tables)),
|
||||
Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables) },
|
||||
Fake(kind) => stable_mir::mir::BorrowKind::Fake(kind.stable(tables, cx)),
|
||||
Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable(tables, cx) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
|
||||
type T = stable_mir::mir::MutBorrowKind;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_middle::mir::MutBorrowKind::*;
|
||||
match *self {
|
||||
Default => stable_mir::mir::MutBorrowKind::Default,
|
||||
|
|
@ -272,7 +318,7 @@ impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind {
|
||||
type T = stable_mir::mir::FakeBorrowKind;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_middle::mir::FakeBorrowKind::*;
|
||||
match *self {
|
||||
Deep => stable_mir::mir::FakeBorrowKind::Deep,
|
||||
|
|
@ -283,13 +329,17 @@ impl<'tcx> Stable<'tcx> for mir::FakeBorrowKind {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
|
||||
type T = stable_mir::mir::NullOp;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> 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(),
|
||||
indices.iter().map(|idx| idx.stable(tables, cx)).collect(),
|
||||
),
|
||||
UbChecks => stable_mir::mir::NullOp::UbChecks,
|
||||
ContractChecks => stable_mir::mir::NullOp::ContractChecks,
|
||||
|
|
@ -299,12 +349,18 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::CastKind {
|
||||
type T = stable_mir::mir::CastKind;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
use rustc_middle::mir::CastKind::*;
|
||||
match self {
|
||||
PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress,
|
||||
PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance,
|
||||
PointerCoercion(c, _) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
|
||||
PointerCoercion(c, _) => {
|
||||
stable_mir::mir::CastKind::PointerCoercion(c.stable(tables, cx))
|
||||
}
|
||||
IntToInt => stable_mir::mir::CastKind::IntToInt,
|
||||
FloatToInt => stable_mir::mir::CastKind::FloatToInt,
|
||||
FloatToFloat => stable_mir::mir::CastKind::FloatToFloat,
|
||||
|
|
@ -318,7 +374,7 @@ impl<'tcx> Stable<'tcx> for mir::CastKind {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
|
||||
type T = stable_mir::mir::FakeReadCause;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_middle::mir::FakeReadCause::*;
|
||||
match self {
|
||||
ForMatchGuard => stable_mir::mir::FakeReadCause::ForMatchGuard,
|
||||
|
|
@ -334,12 +390,16 @@ impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
|
||||
type T = stable_mir::mir::Operand;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> 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)),
|
||||
Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables, cx)),
|
||||
Move(place) => stable_mir::mir::Operand::Move(place.stable(tables, cx)),
|
||||
Constant(c) => stable_mir::mir::Operand::Constant(c.stable(tables, cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -347,35 +407,48 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
|
|||
impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
|
||||
type T = stable_mir::mir::ConstOperand;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
stable_mir::mir::ConstOperand {
|
||||
span: self.span.stable(tables),
|
||||
span: self.span.stable(tables, cx),
|
||||
user_ty: self.user_ty.map(|u| u.as_usize()).or(None),
|
||||
const_: self.const_.stable(tables),
|
||||
const_: self.const_.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
|
||||
type T = stable_mir::mir::Place;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
stable_mir::mir::Place {
|
||||
local: self.local.as_usize(),
|
||||
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
|
||||
projection: self.projection.iter().map(|e| e.stable(tables, cx)).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
|
||||
type T = stable_mir::mir::ProjectionElem;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> 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)),
|
||||
Field(idx, ty) => stable_mir::mir::ProjectionElem::Field(
|
||||
idx.stable(tables, cx),
|
||||
ty.stable(tables, cx),
|
||||
),
|
||||
Index(local) => stable_mir::mir::ProjectionElem::Index(local.stable(tables, cx)),
|
||||
ConstantIndex { offset, min_length, from_end } => {
|
||||
stable_mir::mir::ProjectionElem::ConstantIndex {
|
||||
offset: *offset,
|
||||
|
|
@ -393,9 +466,9 @@ impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
|
|||
// 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)),
|
||||
Downcast(_, idx) => stable_mir::mir::ProjectionElem::Downcast(idx.stable(tables, cx)),
|
||||
OpaqueCast(ty) => stable_mir::mir::ProjectionElem::OpaqueCast(ty.stable(tables, cx)),
|
||||
Subtype(ty) => stable_mir::mir::ProjectionElem::Subtype(ty.stable(tables, cx)),
|
||||
UnwrapUnsafeBinder(..) => todo!("FIXME(unsafe_binders):"),
|
||||
}
|
||||
}
|
||||
|
|
@ -404,21 +477,21 @@ impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
|
|||
impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
|
||||
type T = stable_mir::mir::UserTypeProjection;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> 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<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::RetagKind {
|
||||
type T = stable_mir::mir::RetagKind;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_middle::mir::RetagKind;
|
||||
match self {
|
||||
RetagKind::FnEntry => stable_mir::mir::RetagKind::FnEntry,
|
||||
|
|
@ -431,7 +504,7 @@ impl<'tcx> Stable<'tcx> for mir::RetagKind {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::UnwindAction {
|
||||
type T = stable_mir::mir::UnwindAction;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_middle::mir::UnwindAction;
|
||||
match self {
|
||||
UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
|
||||
|
|
@ -445,18 +518,22 @@ impl<'tcx> Stable<'tcx> for mir::UnwindAction {
|
|||
impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
|
||||
type T = stable_mir::mir::NonDivergingIntrinsic;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> 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))
|
||||
stable_mir::mir::NonDivergingIntrinsic::Assume(op.stable(tables, cx))
|
||||
}
|
||||
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),
|
||||
src: copy_non_overlapping.src.stable(tables, cx),
|
||||
dst: copy_non_overlapping.dst.stable(tables, cx),
|
||||
count: copy_non_overlapping.count.stable(tables, cx),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -465,47 +542,51 @@ impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
|
||||
type T = stable_mir::mir::AssertMessage;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> 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),
|
||||
len: len.stable(tables, cx),
|
||||
index: index.stable(tables, cx),
|
||||
},
|
||||
AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
|
||||
bin_op.stable(tables),
|
||||
op1.stable(tables),
|
||||
op2.stable(tables),
|
||||
bin_op.stable(tables, cx),
|
||||
op1.stable(tables, cx),
|
||||
op2.stable(tables, cx),
|
||||
),
|
||||
AssertKind::OverflowNeg(op) => {
|
||||
stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables))
|
||||
stable_mir::mir::AssertMessage::OverflowNeg(op.stable(tables, cx))
|
||||
}
|
||||
AssertKind::DivisionByZero(op) => {
|
||||
stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables))
|
||||
stable_mir::mir::AssertMessage::DivisionByZero(op.stable(tables, cx))
|
||||
}
|
||||
AssertKind::RemainderByZero(op) => {
|
||||
stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables))
|
||||
stable_mir::mir::AssertMessage::RemainderByZero(op.stable(tables, cx))
|
||||
}
|
||||
AssertKind::ResumedAfterReturn(coroutine) => {
|
||||
stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables))
|
||||
stable_mir::mir::AssertMessage::ResumedAfterReturn(coroutine.stable(tables, cx))
|
||||
}
|
||||
AssertKind::ResumedAfterPanic(coroutine) => {
|
||||
stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables))
|
||||
stable_mir::mir::AssertMessage::ResumedAfterPanic(coroutine.stable(tables, cx))
|
||||
}
|
||||
AssertKind::ResumedAfterDrop(coroutine) => {
|
||||
stable_mir::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables))
|
||||
stable_mir::mir::AssertMessage::ResumedAfterDrop(coroutine.stable(tables, cx))
|
||||
}
|
||||
AssertKind::MisalignedPointerDereference { required, found } => {
|
||||
stable_mir::mir::AssertMessage::MisalignedPointerDereference {
|
||||
required: required.stable(tables),
|
||||
found: found.stable(tables),
|
||||
required: required.stable(tables, cx),
|
||||
found: found.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
AssertKind::NullPointerDereference => {
|
||||
stable_mir::mir::AssertMessage::NullPointerDereference
|
||||
}
|
||||
AssertKind::InvalidEnumConstruction(source) => {
|
||||
stable_mir::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables))
|
||||
stable_mir::mir::AssertMessage::InvalidEnumConstruction(source.stable(tables, cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -513,7 +594,7 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::BinOp {
|
||||
type T = stable_mir::mir::BinOp;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_middle::mir::BinOp;
|
||||
match self {
|
||||
BinOp::Add => stable_mir::mir::BinOp::Add,
|
||||
|
|
@ -548,7 +629,7 @@ impl<'tcx> Stable<'tcx> for mir::BinOp {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::UnOp {
|
||||
type T = stable_mir::mir::UnOp;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_middle::mir::UnOp;
|
||||
match self {
|
||||
UnOp::Not => stable_mir::mir::UnOp::Not,
|
||||
|
|
@ -560,17 +641,21 @@ impl<'tcx> Stable<'tcx> for mir::UnOp {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
|
||||
type T = stable_mir::mir::AggregateKind;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
mir::AggregateKind::Array(ty) => {
|
||||
stable_mir::mir::AggregateKind::Array(ty.stable(tables))
|
||||
stable_mir::mir::AggregateKind::Array(ty.stable(tables, cx))
|
||||
}
|
||||
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.stable(tables),
|
||||
generic_arg.stable(tables),
|
||||
var_idx.stable(tables, cx),
|
||||
generic_arg.stable(tables, cx),
|
||||
user_ty_index.map(|idx| idx.index()),
|
||||
field_idx.map(|idx| idx.index()),
|
||||
)
|
||||
|
|
@ -578,39 +663,46 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
|
|||
mir::AggregateKind::Closure(def_id, generic_arg) => {
|
||||
stable_mir::mir::AggregateKind::Closure(
|
||||
tables.closure_def(*def_id),
|
||||
generic_arg.stable(tables),
|
||||
generic_arg.stable(tables, cx),
|
||||
)
|
||||
}
|
||||
mir::AggregateKind::Coroutine(def_id, generic_arg) => {
|
||||
stable_mir::mir::AggregateKind::Coroutine(
|
||||
tables.coroutine_def(*def_id),
|
||||
generic_arg.stable(tables),
|
||||
tables.tcx.coroutine_movability(*def_id).stable(tables),
|
||||
generic_arg.stable(tables, cx),
|
||||
cx.coroutine_movability(*def_id).stable(tables, cx),
|
||||
)
|
||||
}
|
||||
mir::AggregateKind::CoroutineClosure(def_id, generic_args) => {
|
||||
stable_mir::mir::AggregateKind::CoroutineClosure(
|
||||
tables.coroutine_closure_def(*def_id),
|
||||
generic_args.stable(tables),
|
||||
generic_args.stable(tables, cx),
|
||||
)
|
||||
}
|
||||
mir::AggregateKind::RawPtr(ty, mutability) => {
|
||||
stable_mir::mir::AggregateKind::RawPtr(ty.stable(tables), mutability.stable(tables))
|
||||
}
|
||||
mir::AggregateKind::RawPtr(ty, mutability) => stable_mir::mir::AggregateKind::RawPtr(
|
||||
ty.stable(tables, cx),
|
||||
mutability.stable(tables, cx),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
|
||||
type T = stable_mir::mir::InlineAsmOperand;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> 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::In { value, .. } => (Some(value.stable(tables, cx)), None),
|
||||
InlineAsmOperand::Out { place, .. } => {
|
||||
(None, place.map(|place| place.stable(tables, cx)))
|
||||
}
|
||||
InlineAsmOperand::InOut { in_value, out_place, .. } => {
|
||||
(Some(in_value.stable(tables)), out_place.map(|place| place.stable(tables)))
|
||||
(Some(in_value.stable(tables, cx)), out_place.map(|place| place.stable(tables, cx)))
|
||||
}
|
||||
InlineAsmOperand::Const { .. }
|
||||
| InlineAsmOperand::SymFn { .. }
|
||||
|
|
@ -624,22 +716,33 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
|
||||
type T = stable_mir::mir::Terminator;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
use stable_mir::mir::Terminator;
|
||||
Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
|
||||
Terminator {
|
||||
kind: self.kind.stable(tables, cx),
|
||||
span: self.source_info.span.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
||||
type T = stable_mir::mir::TerminatorKind;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> 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),
|
||||
discr: discr.stable(tables, cx),
|
||||
targets: {
|
||||
let branches = targets.iter().map(|(val, target)| (val, target.as_usize()));
|
||||
stable_mir::mir::SwitchTargets::new(
|
||||
|
|
@ -660,9 +763,9 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
|||
drop: _,
|
||||
async_fut: _,
|
||||
} => TerminatorKind::Drop {
|
||||
place: place.stable(tables),
|
||||
place: place.stable(tables, cx),
|
||||
target: target.as_usize(),
|
||||
unwind: unwind.stable(tables),
|
||||
unwind: unwind.stable(tables, cx),
|
||||
},
|
||||
mir::TerminatorKind::Call {
|
||||
func,
|
||||
|
|
@ -673,20 +776,20 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
|||
call_source: _,
|
||||
fn_span: _,
|
||||
} => TerminatorKind::Call {
|
||||
func: func.stable(tables),
|
||||
args: args.iter().map(|arg| arg.node.stable(tables)).collect(),
|
||||
destination: destination.stable(tables),
|
||||
func: func.stable(tables, cx),
|
||||
args: args.iter().map(|arg| arg.node.stable(tables, cx)).collect(),
|
||||
destination: destination.stable(tables, cx),
|
||||
target: target.map(|t| t.as_usize()),
|
||||
unwind: unwind.stable(tables),
|
||||
unwind: unwind.stable(tables, cx),
|
||||
},
|
||||
mir::TerminatorKind::TailCall { func: _, args: _, fn_span: _ } => todo!(),
|
||||
mir::TerminatorKind::Assert { cond, expected, msg, target, unwind } => {
|
||||
TerminatorKind::Assert {
|
||||
cond: cond.stable(tables),
|
||||
cond: cond.stable(tables, cx),
|
||||
expected: *expected,
|
||||
msg: msg.stable(tables),
|
||||
msg: msg.stable(tables, cx),
|
||||
target: target.as_usize(),
|
||||
unwind: unwind.stable(tables),
|
||||
unwind: unwind.stable(tables, cx),
|
||||
}
|
||||
}
|
||||
mir::TerminatorKind::InlineAsm {
|
||||
|
|
@ -699,12 +802,12 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
|||
unwind,
|
||||
} => TerminatorKind::InlineAsm {
|
||||
template: format!("{template:?}"),
|
||||
operands: operands.iter().map(|operand| operand.stable(tables)).collect(),
|
||||
operands: operands.iter().map(|operand| operand.stable(tables, cx)).collect(),
|
||||
options: format!("{options:?}"),
|
||||
line_spans: format!("{line_spans:?}"),
|
||||
// FIXME: Figure out how to do labels in SMIR
|
||||
destination: targets.first().map(|d| d.as_usize()),
|
||||
unwind: unwind.stable(tables),
|
||||
unwind: unwind.stable(tables, cx),
|
||||
},
|
||||
mir::TerminatorKind::Yield { .. }
|
||||
| mir::TerminatorKind::CoroutineDrop
|
||||
|
|
@ -717,22 +820,40 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
|
|||
impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
|
||||
type T = Allocation;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
self.inner().stable(tables)
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
self.inner().stable(tables, cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
|
||||
type T = stable_mir::ty::Allocation;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
alloc::allocation_filter(self, alloc_range(rustc_abi::Size::ZERO, self.size()), tables)
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
use rustc_smir::context::SmirAllocRange;
|
||||
alloc::allocation_filter(
|
||||
self,
|
||||
cx.alloc_range(rustc_abi::Size::ZERO, self.size()),
|
||||
tables,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
|
||||
type T = stable_mir::mir::alloc::AllocId;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
_: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
tables.create_alloc_id(*self)
|
||||
}
|
||||
}
|
||||
|
|
@ -740,19 +861,25 @@ impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
|
|||
impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
|
||||
type T = GlobalAlloc;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
match self {
|
||||
mir::interpret::GlobalAlloc::Function { instance, .. } => {
|
||||
GlobalAlloc::Function(instance.stable(tables))
|
||||
GlobalAlloc::Function(instance.stable(tables, cx))
|
||||
}
|
||||
mir::interpret::GlobalAlloc::VTable(ty, dyn_ty) => {
|
||||
// FIXME: Should we record the whole vtable?
|
||||
GlobalAlloc::VTable(ty.stable(tables), dyn_ty.principal().stable(tables))
|
||||
GlobalAlloc::VTable(ty.stable(tables, cx), dyn_ty.principal().stable(tables, cx))
|
||||
}
|
||||
mir::interpret::GlobalAlloc::Static(def) => {
|
||||
GlobalAlloc::Static(tables.static_def(*def))
|
||||
}
|
||||
mir::interpret::GlobalAlloc::Memory(alloc) => GlobalAlloc::Memory(alloc.stable(tables)),
|
||||
mir::interpret::GlobalAlloc::Memory(alloc) => {
|
||||
GlobalAlloc::Memory(alloc.stable(tables, cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -760,33 +887,37 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
|
|||
impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
|
||||
type T = stable_mir::ty::MirConst;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap());
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
let id = tables.intern_mir_const(cx.lift(*self).unwrap());
|
||||
match *self {
|
||||
mir::Const::Ty(ty, c) => MirConst::new(
|
||||
stable_mir::ty::ConstantKind::Ty(c.stable(tables)),
|
||||
ty.stable(tables),
|
||||
stable_mir::ty::ConstantKind::Ty(c.stable(tables, cx)),
|
||||
ty.stable(tables, cx),
|
||||
id,
|
||||
),
|
||||
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),
|
||||
args: unev_const.args.stable(tables, cx),
|
||||
promoted: unev_const.promoted.map(|u| u.as_u32()),
|
||||
});
|
||||
let ty = ty.stable(tables);
|
||||
let ty = ty.stable(tables, cx);
|
||||
MirConst::new(kind, ty, id)
|
||||
}
|
||||
mir::Const::Val(mir::ConstValue::ZeroSized, ty) => {
|
||||
let ty = ty.stable(tables);
|
||||
let ty = ty.stable(tables, cx);
|
||||
MirConst::new(ConstantKind::ZeroSized, ty, id)
|
||||
}
|
||||
mir::Const::Val(val, ty) => {
|
||||
let ty = tables.tcx.lift(ty).unwrap();
|
||||
let val = tables.tcx.lift(val).unwrap();
|
||||
let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables));
|
||||
let ty = ty.stable(tables);
|
||||
let ty = cx.lift(ty).unwrap();
|
||||
let val = cx.lift(val).unwrap();
|
||||
let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables, cx));
|
||||
let ty = ty.stable(tables, cx);
|
||||
MirConst::new(kind, ty, id)
|
||||
}
|
||||
}
|
||||
|
|
@ -796,7 +927,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
|
|||
impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
|
||||
type T = Error;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
Error::new(format!("{self:?}"))
|
||||
}
|
||||
}
|
||||
|
|
@ -804,10 +935,14 @@ impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
|
|||
impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
|
||||
type T = stable_mir::mir::mono::MonoItem;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
use stable_mir::mir::mono::MonoItem as StableMonoItem;
|
||||
match self {
|
||||
MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)),
|
||||
MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables, cx)),
|
||||
MonoItem::Static(def_id) => StableMonoItem::Static(tables.static_def(*def_id)),
|
||||
MonoItem::GlobalAsm(item_id) => StableMonoItem::GlobalAsm(opaque(item_id)),
|
||||
}
|
||||
|
|
@ -1,18 +1,20 @@
|
|||
//! Conversion of internal Rust compiler items to stable ones.
|
||||
|
||||
use rustc_abi::FieldIdx;
|
||||
use rustc_smir::Tables;
|
||||
use rustc_smir::context::SmirCtxt;
|
||||
use stable_mir::compiler_interface::BridgeTys;
|
||||
|
||||
use crate::rustc_smir::{Stable, Tables};
|
||||
use crate::stable_mir;
|
||||
use super::Stable;
|
||||
use crate::{rustc_smir, stable_mir};
|
||||
|
||||
mod abi;
|
||||
mod error;
|
||||
mod mir;
|
||||
mod ty;
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_hir::Safety {
|
||||
type T = stable_mir::mir::Safety;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
match self {
|
||||
rustc_hir::Safety::Unsafe => stable_mir::mir::Safety::Unsafe,
|
||||
rustc_hir::Safety::Safe => stable_mir::mir::Safety::Safe,
|
||||
|
|
@ -22,14 +24,14 @@ impl<'tcx> Stable<'tcx> for rustc_hir::Safety {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for FieldIdx {
|
||||
type T = usize;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
self.as_usize()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
|
||||
type T = stable_mir::mir::CoroutineSource;
|
||||
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
use rustc_hir::CoroutineSource;
|
||||
match self {
|
||||
CoroutineSource::Block => stable_mir::mir::CoroutineSource::Block,
|
||||
|
|
@ -41,28 +43,32 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
|
|||
|
||||
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
|
||||
type T = stable_mir::mir::CoroutineKind;
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
use rustc_hir::{CoroutineDesugaring, CoroutineKind};
|
||||
match *self {
|
||||
CoroutineKind::Desugared(CoroutineDesugaring::Async, source) => {
|
||||
stable_mir::mir::CoroutineKind::Desugared(
|
||||
stable_mir::mir::CoroutineDesugaring::Async,
|
||||
source.stable(tables),
|
||||
source.stable(tables, cx),
|
||||
)
|
||||
}
|
||||
CoroutineKind::Desugared(CoroutineDesugaring::Gen, source) => {
|
||||
stable_mir::mir::CoroutineKind::Desugared(
|
||||
stable_mir::mir::CoroutineDesugaring::Gen,
|
||||
source.stable(tables),
|
||||
source.stable(tables, cx),
|
||||
)
|
||||
}
|
||||
CoroutineKind::Coroutine(movability) => {
|
||||
stable_mir::mir::CoroutineKind::Coroutine(movability.stable(tables))
|
||||
stable_mir::mir::CoroutineKind::Coroutine(movability.stable(tables, cx))
|
||||
}
|
||||
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, source) => {
|
||||
stable_mir::mir::CoroutineKind::Desugared(
|
||||
stable_mir::mir::CoroutineDesugaring::AsyncGen,
|
||||
source.stable(tables),
|
||||
source.stable(tables, cx),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +78,7 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
|
|||
impl<'tcx> Stable<'tcx> for rustc_span::Symbol {
|
||||
type T = stable_mir::Symbol;
|
||||
|
||||
fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
|
||||
self.to_string()
|
||||
}
|
||||
}
|
||||
|
|
@ -80,7 +86,11 @@ impl<'tcx> Stable<'tcx> for rustc_span::Symbol {
|
|||
impl<'tcx> Stable<'tcx> for rustc_span::Span {
|
||||
type T = stable_mir::ty::Span;
|
||||
|
||||
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
_: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T {
|
||||
tables.create_span(*self)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
210
compiler/rustc_smir/src/stable_mir/unstable/mod.rs
Normal file
210
compiler/rustc_smir/src/stable_mir/unstable/mod.rs
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
//! Module that collects the things that have no stability guarantees.
|
||||
//!
|
||||
//! We want to keep StableMIR definitions and logic separate from
|
||||
//! any sort of conversion and usage of internal rustc code. So we
|
||||
//! restrict the usage of internal items to be inside this module.
|
||||
|
||||
use std::marker::PointeeSized;
|
||||
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_middle::ty::{List, Ty, TyCtxt};
|
||||
use rustc_middle::{mir, ty};
|
||||
use rustc_smir::Tables;
|
||||
use rustc_smir::context::{
|
||||
SmirCtxt, SmirExistentialProjection, SmirExistentialTraitRef, SmirTraitRef,
|
||||
};
|
||||
use stable_mir::{CtorKind, ItemKind};
|
||||
|
||||
use super::compiler_interface::BridgeTys;
|
||||
use crate::{rustc_smir, stable_mir};
|
||||
|
||||
pub(crate) mod convert;
|
||||
|
||||
impl<'tcx, T: InternalCx<'tcx>> SmirExistentialProjection<'tcx> for T {
|
||||
fn new_from_args(
|
||||
&self,
|
||||
def_id: rustc_span::def_id::DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
term: ty::Term<'tcx>,
|
||||
) -> ty::ExistentialProjection<'tcx> {
|
||||
ty::ExistentialProjection::new_from_args(self.tcx(), def_id, args, term)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: InternalCx<'tcx>> SmirExistentialTraitRef<'tcx> for T {
|
||||
fn new_from_args(
|
||||
&self,
|
||||
trait_def_id: rustc_span::def_id::DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> ty::ExistentialTraitRef<'tcx> {
|
||||
ty::ExistentialTraitRef::new_from_args(self.tcx(), trait_def_id, args)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: InternalCx<'tcx>> SmirTraitRef<'tcx> for T {
|
||||
fn new_from_args(
|
||||
&self,
|
||||
trait_def_id: rustc_span::def_id::DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
) -> ty::TraitRef<'tcx> {
|
||||
ty::TraitRef::new_from_args(self.tcx(), trait_def_id, args)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> InternalCx<'tcx> for TyCtxt<'tcx> {
|
||||
fn tcx(self) -> TyCtxt<'tcx> {
|
||||
self
|
||||
}
|
||||
|
||||
fn lift<T: ty::Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> {
|
||||
TyCtxt::lift(self, value)
|
||||
}
|
||||
|
||||
fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>,
|
||||
{
|
||||
TyCtxt::mk_args_from_iter(self, iter)
|
||||
}
|
||||
|
||||
fn mk_pat(self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx> {
|
||||
TyCtxt::mk_pat(self, v)
|
||||
}
|
||||
|
||||
fn mk_poly_existential_predicates(
|
||||
self,
|
||||
eps: &[ty::PolyExistentialPredicate<'tcx>],
|
||||
) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
|
||||
TyCtxt::mk_poly_existential_predicates(self, eps)
|
||||
}
|
||||
|
||||
fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>> {
|
||||
TyCtxt::mk_type_list(self, v)
|
||||
}
|
||||
|
||||
fn lifetimes_re_erased(self) -> ty::Region<'tcx> {
|
||||
self.lifetimes.re_erased
|
||||
}
|
||||
|
||||
fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>,
|
||||
{
|
||||
TyCtxt::mk_bound_variable_kinds_from_iter(self, iter)
|
||||
}
|
||||
|
||||
fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>> {
|
||||
TyCtxt::mk_place_elems(self, v)
|
||||
}
|
||||
|
||||
fn adt_def(self, def_id: rustc_hir::def_id::DefId) -> ty::AdtDef<'tcx> {
|
||||
self.adt_def(def_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait that defines the methods that are fine to call from [`RustcInternal`].
|
||||
///
|
||||
/// This trait is only for [`RustcInternal`]. Any other other access to rustc's internals
|
||||
/// should go through [`crate::rustc_smir::context::SmirCtxt`].
|
||||
pub trait InternalCx<'tcx>: Copy + Clone {
|
||||
fn tcx(self) -> TyCtxt<'tcx>;
|
||||
|
||||
fn lift<T: ty::Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted>;
|
||||
|
||||
fn mk_args_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: ty::CollectAndApply<ty::GenericArg<'tcx>, ty::GenericArgsRef<'tcx>>;
|
||||
|
||||
fn mk_pat(self, v: ty::PatternKind<'tcx>) -> ty::Pattern<'tcx>;
|
||||
|
||||
fn mk_poly_existential_predicates(
|
||||
self,
|
||||
eps: &[ty::PolyExistentialPredicate<'tcx>],
|
||||
) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>>;
|
||||
|
||||
fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List<Ty<'tcx>>;
|
||||
|
||||
fn lifetimes_re_erased(self) -> ty::Region<'tcx>;
|
||||
|
||||
fn mk_bound_variable_kinds_from_iter<I, T>(self, iter: I) -> T::Output
|
||||
where
|
||||
I: Iterator<Item = T>,
|
||||
T: ty::CollectAndApply<ty::BoundVariableKind, &'tcx List<ty::BoundVariableKind>>;
|
||||
|
||||
fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List<mir::PlaceElem<'tcx>>;
|
||||
|
||||
fn adt_def(self, def_id: rustc_hir::def_id::DefId) -> ty::AdtDef<'tcx>;
|
||||
}
|
||||
|
||||
/// Trait used to convert between an internal MIR type to a Stable MIR type.
|
||||
///
|
||||
/// This trait is currently exposed to users so they can have interoperability between internal MIR
|
||||
/// and StableMIR constructs. However, they should be used seldom and they have no influence
|
||||
/// in this crate semver.
|
||||
#[doc(hidden)]
|
||||
pub trait Stable<'tcx>: PointeeSized {
|
||||
/// The stable representation of the type implementing Stable.
|
||||
type T;
|
||||
/// Converts an object to the equivalent Stable MIR representation.
|
||||
fn stable<'cx>(
|
||||
&self,
|
||||
tables: &mut Tables<'cx, BridgeTys>,
|
||||
cx: &SmirCtxt<'cx, BridgeTys>,
|
||||
) -> Self::T;
|
||||
}
|
||||
|
||||
/// Trait used to translate a stable construct to its rustc counterpart.
|
||||
///
|
||||
/// This is basically a mirror of [Stable].
|
||||
///
|
||||
/// This trait is currently exposed to users so they can have interoperability between internal MIR
|
||||
/// and StableMIR constructs. They should be used seldom as they have no stability guarantees.
|
||||
#[doc(hidden)]
|
||||
pub trait RustcInternal {
|
||||
type T<'tcx>;
|
||||
fn internal<'tcx>(
|
||||
&self,
|
||||
tables: &mut Tables<'_, BridgeTys>,
|
||||
tcx: impl InternalCx<'tcx>,
|
||||
) -> Self::T<'tcx>;
|
||||
}
|
||||
|
||||
pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind {
|
||||
match kind {
|
||||
DefKind::Mod
|
||||
| DefKind::Struct
|
||||
| DefKind::Union
|
||||
| DefKind::Enum
|
||||
| DefKind::Variant
|
||||
| DefKind::Trait
|
||||
| DefKind::TyAlias
|
||||
| DefKind::ForeignTy
|
||||
| DefKind::TraitAlias
|
||||
| DefKind::AssocTy
|
||||
| DefKind::TyParam
|
||||
| DefKind::ConstParam
|
||||
| DefKind::Macro(_)
|
||||
| DefKind::ExternCrate
|
||||
| DefKind::Use
|
||||
| DefKind::ForeignMod
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::Field
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::Impl { .. }
|
||||
| DefKind::GlobalAsm => {
|
||||
unreachable!("Not a valid item kind: {kind:?}");
|
||||
}
|
||||
DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => {
|
||||
ItemKind::Fn
|
||||
}
|
||||
DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => {
|
||||
ItemKind::Const
|
||||
}
|
||||
DefKind::Static { .. } => ItemKind::Static,
|
||||
DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const),
|
||||
DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn),
|
||||
}
|
||||
}
|
||||
|
|
@ -1623,7 +1623,6 @@ symbols! {
|
|||
pointee_sized,
|
||||
pointee_trait,
|
||||
pointer,
|
||||
pointer_like,
|
||||
poll,
|
||||
poll_next,
|
||||
position,
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ use rustc_hir::lang_items::LangItem;
|
|||
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk};
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData};
|
||||
use rustc_middle::ty::{
|
||||
self, GenericArgsRef, Region, SizedTraitKind, Ty, TyCtxt, Upcast, elaborate,
|
||||
};
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Region, SizedTraitKind, Ty, TyCtxt, Upcast};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::def_id::DefId;
|
||||
use thin_vec::thin_vec;
|
||||
|
|
@ -1147,38 +1145,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ty::ClauseKind::TypeOutlives(outlives).upcast(tcx),
|
||||
));
|
||||
|
||||
// Require that all AFIT will return something that can be coerced into `dyn*`
|
||||
// -- a shim will be responsible for doing the actual coercion to `dyn*`.
|
||||
if let Some(principal) = data.principal() {
|
||||
for supertrait in
|
||||
elaborate::supertraits(tcx, principal.with_self_ty(tcx, source))
|
||||
{
|
||||
if tcx.is_trait_alias(supertrait.def_id()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for &assoc_item in tcx.associated_item_def_ids(supertrait.def_id()) {
|
||||
if !tcx.is_impl_trait_in_trait(assoc_item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// RPITITs with `Self: Sized` don't need to be checked.
|
||||
if tcx.generics_require_sized_self(assoc_item) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let pointer_like_goal = pointer_like_goal_for_rpitit(
|
||||
tcx,
|
||||
supertrait,
|
||||
assoc_item,
|
||||
&obligation.cause,
|
||||
);
|
||||
|
||||
nested.push(predicate_to_obligation(pointer_like_goal.upcast(tcx)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImplSource::Builtin(BuiltinImplSource::Misc, nested)
|
||||
}
|
||||
|
||||
|
|
@ -1344,46 +1310,3 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ImplSource::Builtin(BuiltinImplSource::Misc, obligations)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute a goal that some RPITIT (right now, only RPITITs corresponding to Futures)
|
||||
/// implements the `PointerLike` trait, which is a requirement for the RPITIT to be
|
||||
/// coercible to `dyn* Future`, which is itself a requirement for the RPITIT's parent
|
||||
/// trait to be coercible to `dyn Trait`.
|
||||
///
|
||||
/// We do this given a supertrait's substitutions, and then augment the substitutions
|
||||
/// with bound variables to compute the goal universally. Given that `PointerLike` has
|
||||
/// no region requirements (at least for the built-in pointer types), this shouldn't
|
||||
/// *really* matter, but it is the best choice for soundness.
|
||||
fn pointer_like_goal_for_rpitit<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
supertrait: ty::PolyTraitRef<'tcx>,
|
||||
rpitit_item: DefId,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
) -> ty::PolyTraitRef<'tcx> {
|
||||
let mut bound_vars = supertrait.bound_vars().to_vec();
|
||||
|
||||
let args = supertrait.skip_binder().args.extend_to(tcx, rpitit_item, |arg, _| match arg.kind {
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
let kind = ty::BoundRegionKind::Named(arg.def_id, tcx.item_name(arg.def_id));
|
||||
bound_vars.push(ty::BoundVariableKind::Region(kind));
|
||||
ty::Region::new_bound(
|
||||
tcx,
|
||||
ty::INNERMOST,
|
||||
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
|
||||
)
|
||||
.into()
|
||||
}
|
||||
ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Const { .. } => {
|
||||
unreachable!()
|
||||
}
|
||||
});
|
||||
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::TraitRef::new(
|
||||
tcx,
|
||||
tcx.require_lang_item(LangItem::PointerLike, cause.span),
|
||||
[Ty::new_projection_from_args(tcx, rpitit_item, args)],
|
||||
),
|
||||
tcx.mk_bound_variable_kinds(&bound_vars),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -429,10 +429,10 @@ pub mod __alloc_error_handler {
|
|||
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
|
||||
// Its value depends on the -Zoom={panic,abort} compiler option.
|
||||
#[rustc_std_internal_symbol]
|
||||
static __rust_alloc_error_handler_should_panic: u8;
|
||||
fn __rust_alloc_error_handler_should_panic_v2() -> u8;
|
||||
}
|
||||
|
||||
if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
|
||||
if unsafe { __rust_alloc_error_handler_should_panic_v2() != 0 } {
|
||||
panic!("memory allocation of {size} bytes failed")
|
||||
} else {
|
||||
core::panicking::panic_nounwind_fmt(
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ use core::error::{self, Error};
|
|||
use core::fmt;
|
||||
use core::future::Future;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::marker::{PointerLike, Tuple, Unsize};
|
||||
use core::marker::{Tuple, Unsize};
|
||||
use core::mem::{self, SizedTypeProperties};
|
||||
use core::ops::{
|
||||
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut,
|
||||
|
|
@ -2132,6 +2132,3 @@ impl<E: Error> Error for Box<E> {
|
|||
Error::provide(&**self, request);
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T> PointerLike for Box<T> {}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,6 @@
|
|||
#![feature(panic_internals)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pin_coerce_unsized_trait)]
|
||||
#![feature(pointer_like_trait)]
|
||||
#![feature(ptr_alignment_type)]
|
||||
#![feature(ptr_internals)]
|
||||
#![feature(ptr_metadata)]
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@
|
|||
|
||||
use crate::cmp::Ordering;
|
||||
use crate::fmt::{self, Debug, Display};
|
||||
use crate::marker::{PhantomData, PointerLike, Unsize};
|
||||
use crate::marker::{PhantomData, Unsize};
|
||||
use crate::mem;
|
||||
use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn};
|
||||
use crate::panic::const_panic;
|
||||
|
|
@ -669,9 +669,6 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {}
|
|||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Cell<U>> for Cell<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T: PointerLike> PointerLike for Cell<T> {}
|
||||
|
||||
impl<T> Cell<[T]> {
|
||||
/// Returns a `&[Cell<T>]` from a `&Cell<[T]>`
|
||||
///
|
||||
|
|
@ -2361,9 +2358,6 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafeCell<U>> for UnsafeCell<T> {}
|
|||
#[unstable(feature = "dispatch_from_dyn", issue = "none")]
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafeCell<U>> for UnsafeCell<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T: PointerLike> PointerLike for UnsafeCell<T> {}
|
||||
|
||||
/// [`UnsafeCell`], but [`Sync`].
|
||||
///
|
||||
/// This is just an `UnsafeCell`, except it implements `Sync`
|
||||
|
|
@ -2470,9 +2464,6 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<SyncUnsafeCell<U>> for SyncUnsafeCell
|
|||
//#[unstable(feature = "sync_unsafe_cell", issue = "95439")]
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<SyncUnsafeCell<U>> for SyncUnsafeCell<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T: PointerLike> PointerLike for SyncUnsafeCell<T> {}
|
||||
|
||||
#[allow(unused)]
|
||||
fn assert_coerce_unsized(
|
||||
a: UnsafeCell<&i32>,
|
||||
|
|
|
|||
|
|
@ -1066,37 +1066,6 @@ pub trait Destruct {}
|
|||
#[rustc_do_not_implement_via_object]
|
||||
pub trait Tuple {}
|
||||
|
||||
/// A marker for pointer-like types.
|
||||
///
|
||||
/// This trait can only be implemented for types that are certain to have
|
||||
/// the same size and alignment as a [`usize`] or [`*const ()`](pointer).
|
||||
/// To ensure this, there are special requirements on implementations
|
||||
/// of `PointerLike` (other than the already-provided implementations
|
||||
/// for built-in types):
|
||||
///
|
||||
/// * The type must have `#[repr(transparent)]`.
|
||||
/// * The type’s sole non-zero-sized field must itself implement `PointerLike`.
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
#[lang = "pointer_like"]
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "`{Self}` needs to have the same ABI as a pointer",
|
||||
label = "`{Self}` needs to be a pointer-like type"
|
||||
)]
|
||||
#[rustc_do_not_implement_via_object]
|
||||
pub trait PointerLike {}
|
||||
|
||||
marker_impls! {
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
PointerLike for
|
||||
isize,
|
||||
usize,
|
||||
{T} &T,
|
||||
{T} &mut T,
|
||||
{T} *const T,
|
||||
{T} *mut T,
|
||||
{T: PointerLike} crate::pin::Pin<T>,
|
||||
}
|
||||
|
||||
/// A marker for types which can be used as types of `const` generic parameters.
|
||||
///
|
||||
/// These types must have a proper equivalence relation (`Eq`) and it must be automatically
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::cell::UnsafeCell;
|
||||
use crate::marker::{PointerLike, Unpin};
|
||||
use crate::marker::Unpin;
|
||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||
use crate::pin::Pin;
|
||||
use crate::{fmt, ptr};
|
||||
|
|
@ -178,8 +178,4 @@ impl<T: CoerceUnsized<U>, U> CoerceUnsized<UnsafePinned<U>> for UnsafePinned<T>
|
|||
// #[unstable(feature = "unsafe_pinned", issue = "125735")]
|
||||
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<UnsafePinned<U>> for UnsafePinned<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
// #[unstable(feature = "unsafe_pinned", issue = "125735")]
|
||||
impl<T: PointerLike> PointerLike for UnsafePinned<T> {}
|
||||
|
||||
// FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned<T>?
|
||||
|
|
|
|||
|
|
@ -1628,9 +1628,6 @@ impl<T: PointeeSized, U: PointeeSized> DispatchFromDyn<NonNull<U>> for NonNull<T
|
|||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
unsafe impl<T: PointeeSized> PinCoerceUnsized for NonNull<T> {}
|
||||
|
||||
#[unstable(feature = "pointer_like_trait", issue = "none")]
|
||||
impl<T> core::marker::PointerLike for NonNull<T> {}
|
||||
|
||||
#[stable(feature = "nonnull", since = "1.25.0")]
|
||||
impl<T: PointeeSized> fmt::Debug for NonNull<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
|
|||
|
|
@ -349,10 +349,10 @@ fn default_alloc_error_hook(layout: Layout) {
|
|||
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
|
||||
// Its value depends on the -Zoom={panic,abort} compiler option.
|
||||
#[rustc_std_internal_symbol]
|
||||
static __rust_alloc_error_handler_should_panic: u8;
|
||||
fn __rust_alloc_error_handler_should_panic_v2() -> u8;
|
||||
}
|
||||
|
||||
if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
|
||||
if unsafe { __rust_alloc_error_handler_should_panic_v2() != 0 } {
|
||||
panic!("memory allocation of {} bytes failed", layout.size());
|
||||
} else {
|
||||
// This is the default path taken on OOM, and the only path taken on stable with std.
|
||||
|
|
|
|||
3
src/doc/rustc-dev-guide/josh-sync.toml
Normal file
3
src/doc/rustc-dev-guide/josh-sync.toml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
org = "rust-lang"
|
||||
repo = "rustc-dev-guide"
|
||||
path = "src/doc/rustc-dev-guide"
|
||||
|
|
@ -1 +1 @@
|
|||
d1d8e386c5e84c4ba857f56c3291f73c27e2d62a
|
||||
c96a69059ecc618b519da385a6ccd03155aa0237
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ The `std::autodiff` module in Rust allows differentiable programming:
|
|||
|
||||
```rust
|
||||
#![feature(autodiff)]
|
||||
use std::autodiff::autodiff;
|
||||
use std::autodiff::*;
|
||||
|
||||
// f(x) = x * x, f'(x) = 2.0 * x
|
||||
// bar therefore returns (x * x, 2.0 * x)
|
||||
#[autodiff(bar, Reverse, Active, Active)]
|
||||
#[autodiff_reverse(bar, Active, Active)]
|
||||
fn foo(x: f32) -> f32 { x * x }
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,24 @@
|
|||
|
||||
<!-- toc -->
|
||||
|
||||
<div class="warning">
|
||||
|
||||
For `profile = "library"` users, or users who use `download-rustc = true | "if-unchanged"`, please be advised that
|
||||
the `./x test library/std` flow where `download-rustc` is active (i.e. no compiler changes) is currently broken.
|
||||
This is tracked in <https://github.com/rust-lang/rust/issues/142505>. Only the `./x test` flow is affected in this
|
||||
case, `./x {check,build} library/std` should still work.
|
||||
|
||||
In the short-term, you may need to disable `download-rustc` for `./x test library/std`. This can be done either by:
|
||||
|
||||
1. `./x test library/std --set rust.download-rustc=false`
|
||||
2. Or set `rust.download-rustc=false` in `bootstrap.toml`.
|
||||
|
||||
Unfortunately that will require building the stage 1 compiler. The bootstrap team is working on this, but
|
||||
implementing a maintainable fix is taking some time.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
The compiler is built using a tool called `x.py`. You will need to
|
||||
have Python installed to run it.
|
||||
|
||||
|
|
|
|||
|
|
@ -434,6 +434,10 @@ Just a few things to keep in mind:
|
|||
it might benefit from having a Table of Contents at the beginning,
|
||||
which you can auto-generate by including the `<!-- toc -->` marker at the top.
|
||||
|
||||
#### ⚠️ Note: Where to contribute `rustc-dev-guide` changes
|
||||
|
||||
For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, see [the rustc-dev-guide working group documentation](https://forge.rust-lang.org/wg-rustc-dev-guide/index.html#where-to-contribute-rustc-dev-guide-changes).
|
||||
|
||||
## Issue triage
|
||||
|
||||
Please see <https://forge.rust-lang.org/release/issue-triaging.html>.
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
# Diagnostic and subdiagnostic structs
|
||||
rustc has three diagnostic traits that can be used to create diagnostics:
|
||||
`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`. For simple diagnostics,
|
||||
instead of using the `Diag` API to create and emit diagnostics,
|
||||
derived impls can be used. They are only suitable for simple diagnostics that
|
||||
`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`.
|
||||
|
||||
For simple diagnostics,
|
||||
derived impls can be used, e.g. `#[derive(Diagnostic)]`. They are only suitable for simple diagnostics that
|
||||
don't require much logic in deciding whether or not to add additional
|
||||
subdiagnostics.
|
||||
|
||||
Such diagnostic can be translated into
|
||||
different languages and each has a slug that uniquely identifies the
|
||||
diagnostic.
|
||||
In cases where diagnostics require more complex or dynamic behavior, such as conditionally adding subdiagnostics,
|
||||
customizing the rendering logic, or selecting messages at runtime, you will need to manually implement
|
||||
the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`).
|
||||
This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures.
|
||||
|
||||
Diagnostic can be translated into different languages and each has a slug that uniquely identifies the diagnostic.
|
||||
|
||||
## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
|
||||
|
||||
|
|
@ -142,7 +146,7 @@ tcx.dcx().emit_err(FieldAlreadyDeclared {
|
|||
});
|
||||
```
|
||||
|
||||
### Reference
|
||||
### Reference for `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]`
|
||||
`#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the
|
||||
following attributes:
|
||||
|
||||
|
|
@ -330,7 +334,34 @@ function ([example][subdiag_use_1] and [example][subdiag_use_2]) on a
|
|||
diagnostic or by assigning it to a `#[subdiagnostic]`-annotated field of a
|
||||
diagnostic struct.
|
||||
|
||||
### Reference
|
||||
### Argument sharing and isolation
|
||||
|
||||
Subdiagnostics add their own arguments (i.e., certain fields in their structure) to the `Diag` structure before rendering the information.
|
||||
`Diag` structure also stores the arguments from the main diagnostic, so the subdiagnostic can also use the arguments from the main diagnostic.
|
||||
|
||||
However, when a subdiagnostic is added to a main diagnostic by implementing `#[derive(Subdiagnostic)]`,
|
||||
the following rules, introduced in [rust-lang/rust#142724](https://github.com/rust-lang/rust/pull/142724)
|
||||
apply to the handling of arguments (i.e., variables used in Fluent messages):
|
||||
|
||||
**Argument isolation between sub diagnostics**:
|
||||
Arguments set by a subdiagnostic are only available during the rendering of that subdiagnostic.
|
||||
After the subdiagnostic is rendered, all arguments it introduced are restored from the main diagnostic.
|
||||
This ensures that multiple subdiagnostics do not pollute each other's argument scope.
|
||||
For example, when using a `Vec<Subdiag>`, it iteratively adds the same argument over and over again.
|
||||
|
||||
**Same argument override between sub and main diagnostics**:
|
||||
If a subdiagnostic sets a argument with the same name as a arguments already in the main diagnostic,
|
||||
it will report an error at runtime unless both have exactly the same value.
|
||||
It has two benefits:
|
||||
- preserves the flexibility that arguments in the main diagnostic are allowed to appear in the attributes of the subdiagnostic.
|
||||
For example, There is an attribute `#[suggestion(code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct.
|
||||
- prevents accidental overwriting or deletion of arguments required by the main diagnostic or other subdiagnostics.
|
||||
|
||||
These rules guarantee that arguments injected by subdiagnostics are strictly scoped to their own rendering.
|
||||
The main diagnostic's arguments remain unaffected by subdiagnostic logic, even in the presence of name collisions.
|
||||
Additionally, subdiagnostics can access arguments from the main diagnostic with the same name when needed.
|
||||
|
||||
### Reference for `#[derive(Subdiagnostic)]`
|
||||
`#[derive(Subdiagnostic)]` supports the following attributes:
|
||||
|
||||
- `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]`
|
||||
|
|
|
|||
|
|
@ -7,10 +7,8 @@ of such structures include but are not limited to
|
|||
|
||||
* Parenthesis
|
||||
* Removed without replacement, the tree structure makes order explicit
|
||||
* `for` loops and `while (let)` loops
|
||||
* Converted to `loop` + `match` and some `let` bindings
|
||||
* `if let`
|
||||
* Converted to `match`
|
||||
* `for` loops
|
||||
* Converted to `match` + `loop` + `match`
|
||||
* Universal `impl Trait`
|
||||
* Converted to generic arguments
|
||||
(but with some flags, to know that the user didn't write them)
|
||||
|
|
|
|||
|
|
@ -453,9 +453,9 @@ even run the resulting program. Just add one of the following
|
|||
- `//@ check-fail` — compilation should fail (the codegen phase is skipped).
|
||||
This is the default for UI tests.
|
||||
- `//@ build-fail` — compilation should fail during the codegen phase.
|
||||
This will run `rustc` twice, once to verify that it compiles successfully
|
||||
without the codegen phase, then a second time the full compile should
|
||||
fail.
|
||||
This will run `rustc` twice:
|
||||
- First time is to ensure that the compile succeeds without the codegen phase
|
||||
- Second time is to ensure that the full compile fails
|
||||
- `//@ run-fail` — compilation should succeed, but running the resulting
|
||||
binary should fail.
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ error: casting to the same type is unnecessary (`u32` -> `u32`)
|
|||
|
|
||||
LL | let b = a as u32;
|
||||
| ^^^^^^^^ help: try: `a`
|
||||
-Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs:LL:CC
|
||||
= note: `-D clippy::unnecessary-cast` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]`
|
||||
|
||||
|
|
@ -15,8 +15,8 @@ LL | let d = 42;
|
|||
| ----------- unnecessary `let` binding
|
||||
LL | d
|
||||
| ^
|
||||
-Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/returns.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/returns.rs:LL:CC
|
||||
= note: `-D clippy::let-and-return` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::let_and_return)]`
|
||||
help: return the expression directly
|
||||
|
|
|
|||
|
|
@ -8,5 +8,6 @@ struct A;
|
|||
struct B;
|
||||
const S: A = B;
|
||||
//~^ ERROR: mismatched types
|
||||
//~| NOTE: created at
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ error[E0308]: mismatched types
|
|||
|
|
||||
LL | const S: A = B;
|
||||
| ^ expected `A`, found `B`
|
||||
-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
//! Provides the `extern static` that this platform expects.
|
||||
|
||||
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||
|
||||
use crate::*;
|
||||
|
||||
impl<'tcx> MiriMachine<'tcx> {
|
||||
|
|
@ -45,15 +43,6 @@ impl<'tcx> MiriMachine<'tcx> {
|
|||
|
||||
/// Sets up the "extern statics" for this machine.
|
||||
pub fn init_extern_statics(ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx> {
|
||||
// "__rust_alloc_error_handler_should_panic"
|
||||
let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let val = ImmTy::from_int(val, ecx.machine.layouts.u8);
|
||||
Self::alloc_extern_static(
|
||||
ecx,
|
||||
&mangle_internal_symbol(*ecx.tcx, "__rust_alloc_error_handler_should_panic"),
|
||||
val,
|
||||
)?;
|
||||
|
||||
if ecx.target_os_is_unix() {
|
||||
// "environ" is mandated by POSIX.
|
||||
let environ = ecx.machine.env_vars.unix().environ();
|
||||
|
|
|
|||
|
|
@ -615,6 +615,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
// This is a no-op shim that only exists to prevent making the allocator shims instantly stable.
|
||||
let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
|
||||
}
|
||||
name if name == this.mangle_internal_symbol("__rust_alloc_error_handler_should_panic_v2") => {
|
||||
// Gets the value of the `oom` option.
|
||||
let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?;
|
||||
let val = this.tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
this.write_int(val, dest)?;
|
||||
}
|
||||
|
||||
// C memory handling functions
|
||||
"memcmp" => {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
//@compile-flags: -Zmiri-track-alloc-id=19 -Zmiri-track-alloc-accesses -Cpanic=abort
|
||||
//@normalize-stderr-test: "id 19" -> "id $$ALLOC"
|
||||
//@compile-flags: -Zmiri-track-alloc-id=18 -Zmiri-track-alloc-accesses -Cpanic=abort
|
||||
//@normalize-stderr-test: "id 18" -> "id $$ALLOC"
|
||||
//@only-target: linux # alloc IDs differ between OSes (due to extern static allocations)
|
||||
|
||||
extern "Rust" {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//@ compile-flags: -Z track-diagnostics
|
||||
//@ error-pattern: created at
|
||||
|
||||
// Normalize the emitted location so this doesn't need
|
||||
// updating everytime someone adds or removes a line.
|
||||
|
|
@ -8,4 +7,7 @@
|
|||
struct A;
|
||||
struct B;
|
||||
|
||||
pub const S: A = B; //~ ERROR mismatched types
|
||||
pub const S: A = B;
|
||||
//~^ ERROR mismatched types
|
||||
//~| NOTE created at
|
||||
//~| NOTE expected `A`, found `B`
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ error[E0308]: mismatched types
|
|||
|
|
||||
LL | pub const S: A = B;
|
||||
| ^ expected `A`, found `B`
|
||||
-Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//@ compile-flags: -Z track-diagnostics
|
||||
//@ error-pattern: created at
|
||||
//@ dont-require-annotations: NOTE
|
||||
//@ rustc-env:RUST_BACKTRACE=0
|
||||
//@ failure-status: 101
|
||||
|
||||
|
|
@ -16,6 +16,9 @@
|
|||
fn main() {
|
||||
break rust
|
||||
//~^ ERROR cannot find value `rust` in this scope
|
||||
//~| NOTE created at
|
||||
//~| ERROR `break` outside of a loop or labeled block
|
||||
//~| NOTE created at
|
||||
//~| ERROR It looks like you're trying to break rust; would you like some ICE?
|
||||
//~| NOTE created at
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,22 +3,24 @@ error[E0425]: cannot find value `rust` in this scope
|
|||
|
|
||||
LL | break rust
|
||||
| ^^^^ not found in this scope
|
||||
-Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC
|
||||
|
||||
error[E0268]: `break` outside of a loop or labeled block
|
||||
--> $DIR/track.rs:LL:CC
|
||||
|
|
||||
LL | break rust
|
||||
| ^^^^^^^^^^ cannot `break` outside of a loop or labeled block
|
||||
-Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/loops.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/loops.rs:LL:CC
|
||||
|
||||
error: internal compiler error: It looks like you're trying to break rust; would you like some ICE?
|
||||
--> $DIR/track.rs:LL:CC
|
||||
|
|
||||
LL | break rust
|
||||
| ^^^^^^^^^^
|
||||
-Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/lib.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/lib.rs:LL:CC
|
||||
= note: the compiler expectedly panicked. this is a feature.
|
||||
= note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675
|
||||
= note: rustc $VERSION running on $TARGET
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
//@ compile-flags: -Z track-diagnostics
|
||||
//@ error-pattern: created at
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
// Normalize the emitted location so this doesn't need
|
||||
// updating everytime someone adds or removes a line.
|
||||
//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC"
|
||||
|
||||
fn main() {
|
||||
let _moved @ _from = String::from("foo"); //~ ERROR use of moved value
|
||||
let _moved @ _from = String::from("foo");
|
||||
//~^ ERROR use of moved value
|
||||
//~| NOTE created at
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ LL | let _moved @ _from = String::from("foo");
|
|||
| | |
|
||||
| | value moved here
|
||||
| value used here after move
|
||||
-Ztrack-diagnostics: created at compiler/rustc_borrowck/src/borrowck_errors.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_borrowck/src/borrowck_errors.rs:LL:CC
|
||||
help: borrow this binding in the pattern to avoid moving the value
|
||||
|
|
||||
LL | let ref _moved @ ref _from = String::from("foo");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//@ compile-flags: -Z track-diagnostics
|
||||
//@ error-pattern: created at
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
// Normalize the emitted location so this doesn't need
|
||||
// updating everytime someone adds or removes a line.
|
||||
|
|
@ -8,5 +8,7 @@
|
|||
fn main() {
|
||||
let _unimported = Blah { field: u8 };
|
||||
//~^ ERROR cannot find struct, variant or union type `Blah` in this scope
|
||||
//~| NOTE created at
|
||||
//~| ERROR expected value, found builtin type `u8`
|
||||
//~| NOTE created at
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,16 @@ error[E0422]: cannot find struct, variant or union type `Blah` in this scope
|
|||
|
|
||||
LL | let _unimported = Blah { field: u8 };
|
||||
| ^^^^ not found in this scope
|
||||
-Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC
|
||||
|
||||
error[E0423]: expected value, found builtin type `u8`
|
||||
--> $DIR/track3.rs:LL:CC
|
||||
|
|
||||
LL | let _unimported = Blah { field: u8 };
|
||||
| ^^ not a value
|
||||
-Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
//@ compile-flags: -Z track-diagnostics
|
||||
//@ error-pattern: created at
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
// Normalize the emitted location so this doesn't need
|
||||
// updating everytime someone adds or removes a line.
|
||||
//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC"
|
||||
|
||||
pub onion { //~ ERROR missing `enum` for enum definition
|
||||
pub onion {
|
||||
//~^ ERROR missing `enum` for enum definition
|
||||
//~| NOTE created at
|
||||
Owo(u8),
|
||||
Uwu(i8),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ error: missing `enum` for enum definition
|
|||
|
|
||||
LL | pub onion {
|
||||
| ^^^^^^^^^
|
||||
-Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/item.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/item.rs:LL:CC
|
||||
help: add `enum` here to parse `onion` as an enum
|
||||
|
|
||||
LL | pub enum onion {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
//@ compile-flags: -Z track-diagnostics
|
||||
//@ error-pattern: created at
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
// Normalize the emitted location so this doesn't need
|
||||
// updating everytime someone adds or removes a line.
|
||||
//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC"
|
||||
|
||||
} //~ ERROR unexpected closing delimiter: `}`
|
||||
}
|
||||
//~^ ERROR unexpected closing delimiter: `}`
|
||||
//~| NOTE created at
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ error: unexpected closing delimiter: `}`
|
|||
|
|
||||
LL | }
|
||||
| ^ unexpected closing delimiter
|
||||
-Ztrack-diagnostics: created at compiler/rustc_parse/src/lexer/tokentrees.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_parse/src/lexer/tokentrees.rs:LL:CC
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//@ compile-flags: -Z track-diagnostics
|
||||
//@ error-pattern: created at
|
||||
//@ dont-require-annotations: NOTE
|
||||
|
||||
// Normalize the emitted location so this doesn't need
|
||||
// updating everytime someone adds or removes a line.
|
||||
|
|
@ -11,7 +11,9 @@ pub trait Foo {
|
|||
}
|
||||
|
||||
impl <T> Foo for T {
|
||||
default fn bar() {} //~ ERROR specialization is unstable
|
||||
default fn bar() {}
|
||||
//~^ ERROR specialization is unstable
|
||||
//~| NOTE created at
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ error[E0658]: specialization is unstable
|
|||
|
|
||||
LL | default fn bar() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
-Ztrack-diagnostics: created at compiler/rustc_ast_passes/src/feature_gate.rs:LL:CC
|
||||
|
|
||||
= note: -Ztrack-diagnostics: created at compiler/rustc_ast_passes/src/feature_gate.rs:LL:CC
|
||||
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
|
||||
= help: add `#![feature(specialization)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
|
||||
#![feature(pointer_like_trait)]
|
||||
|
||||
use std::marker::PointerLike;
|
||||
|
||||
fn require_(_: impl PointerLike) {}
|
||||
|
||||
fn main() {
|
||||
require_(1usize);
|
||||
require_(1u16);
|
||||
//~^ ERROR `u16` needs to have the same ABI as a pointer
|
||||
require_(&1i16);
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
error[E0277]: `u16` needs to have the same ABI as a pointer
|
||||
--> $DIR/pointer-like.rs:11:14
|
||||
|
|
||||
LL | require_(1u16);
|
||||
| -------- ^^^^ the trait `PointerLike` is not implemented for `u16`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: the trait bound `u16: PointerLike` is not satisfied
|
||||
note: required by a bound in `require_`
|
||||
--> $DIR/pointer-like.rs:7:21
|
||||
|
|
||||
LL | fn require_(_: impl PointerLike) {}
|
||||
| ^^^^^^^^^^^ required by this bound in `require_`
|
||||
help: consider borrowing here
|
||||
|
|
||||
LL | require_(&1u16);
|
||||
| +
|
||||
LL | require_(&mut 1u16);
|
||||
| ++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue