Merge pull request #4445 from RalfJung/rustup

Rustup
This commit is contained in:
Ralf Jung 2025-07-05 07:36:55 +00:00 committed by GitHub
commit 6e3e05befc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
158 changed files with 4737 additions and 3012 deletions

View file

@ -19,6 +19,7 @@ env:
PR_TITLE: Weekly `cargo update`
PR_MESSAGE: |
Automation to keep dependencies in `Cargo.lock` current.
r? dep-bumps
The following is the output from `cargo update`:
COMMIT_MESSAGE: "cargo update \n\n"

View file

@ -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",
]
@ -4133,6 +4133,7 @@ dependencies = [
"rustc_fs_util",
"rustc_hir",
"rustc_hir_pretty",
"rustc_incremental",
"rustc_index",
"rustc_macros",
"rustc_middle",
@ -4522,7 +4523,7 @@ dependencies = [
"rustc_serialize",
"rustc_span",
"rustc_target",
"termize",
"termize 0.2.0",
"tracing",
"windows 0.61.3",
]
@ -5294,6 +5295,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"

View file

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

View file

@ -278,12 +278,21 @@ pub enum AttributeKind {
/// Represents `#[naked]`
Naked(Span),
/// Represents `#[no_implicit_prelude]`
NoImplicitPrelude(Span),
/// Represents `#[no_mangle]`
NoMangle(Span),
/// Represents `#[non_exhaustive]`
NonExhaustive(Span),
/// 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),

View file

@ -12,39 +12,44 @@ 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,
NonExhaustive(..) => Yes,
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
}
}
}

View file

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

View file

@ -35,6 +35,8 @@ pub(crate) mod link_attrs;
pub(crate) mod lint_helpers;
pub(crate) mod loop_match;
pub(crate) mod must_use;
pub(crate) mod no_implicit_prelude;
pub(crate) mod non_exhaustive;
pub(crate) mod repr;
pub(crate) mod rustc_internal;
pub(crate) mod semantics;

View file

@ -0,0 +1,13 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_span::{Span, sym};
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::Stage;
pub(crate) struct NoImplicitPreludeParser;
impl<S: Stage> NoArgsAttributeParser<S> for NoImplicitPreludeParser {
const PATH: &[rustc_span::Symbol] = &[sym::no_implicit_prelude];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoImplicitPrelude;
}

View file

@ -0,0 +1,13 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_span::{Span, Symbol, sym};
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::Stage;
pub(crate) struct NonExhaustiveParser;
impl<S: Stage> NoArgsAttributeParser<S> for NonExhaustiveParser {
const PATH: &[Symbol] = &[sym::non_exhaustive];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive;
}

View file

@ -23,9 +23,11 @@ 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;
use crate::attributes::non_exhaustive::NonExhaustiveParser;
use crate::attributes::repr::{AlignParser, ReprParser};
use crate::attributes::rustc_internal::{
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
@ -141,7 +143,10 @@ attribute_parsers!(
Single<WithoutArgs<ConstStabilityIndirectParser>>,
Single<WithoutArgs<LoopMatchParser>>,
Single<WithoutArgs<MayDangleParser>>,
Single<WithoutArgs<NoImplicitPreludeParser>>,
Single<WithoutArgs<NoMangleParser>>,
Single<WithoutArgs<NonExhaustiveParser>>,
Single<WithoutArgs<PassByValueParser>>,
Single<WithoutArgs<PubTransparentParser>>,
Single<WithoutArgs<TrackCallerParser>>,
// tidy-alphabetical-end

View file

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

View file

@ -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<'_>,

View file

@ -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<'_>,

View file

@ -103,23 +103,25 @@ fn call_simple_intrinsic<'ll, 'tcx>(
sym::minnumf64 => ("llvm.minnum", &[bx.type_f64()]),
sym::minnumf128 => ("llvm.minnum", &[bx.type_f128()]),
sym::minimumf16 => ("llvm.minimum", &[bx.type_f16()]),
sym::minimumf32 => ("llvm.minimum", &[bx.type_f32()]),
sym::minimumf64 => ("llvm.minimum", &[bx.type_f64()]),
// There are issues on x86_64 and aarch64 with the f128 variant,
// let's instead use the intrinsic fallback body.
// sym::minimumf128 => ("llvm.minimum", &[cx.type_f128()]),
// FIXME: LLVM currently mis-compile those intrinsics, re-enable them
// when llvm/llvm-project#{139380,139381,140445} are fixed.
//sym::minimumf16 => ("llvm.minimum", &[bx.type_f16()]),
//sym::minimumf32 => ("llvm.minimum", &[bx.type_f32()]),
//sym::minimumf64 => ("llvm.minimum", &[bx.type_f64()]),
//sym::minimumf128 => ("llvm.minimum", &[cx.type_f128()]),
//
sym::maxnumf16 => ("llvm.maxnum", &[bx.type_f16()]),
sym::maxnumf32 => ("llvm.maxnum", &[bx.type_f32()]),
sym::maxnumf64 => ("llvm.maxnum", &[bx.type_f64()]),
sym::maxnumf128 => ("llvm.maxnum", &[bx.type_f128()]),
sym::maximumf16 => ("llvm.maximum", &[bx.type_f16()]),
sym::maximumf32 => ("llvm.maximum", &[bx.type_f32()]),
sym::maximumf64 => ("llvm.maximum", &[bx.type_f64()]),
// There are issues on x86_64 and aarch64 with the f128 variant,
// let's instead use the intrinsic fallback body.
// sym::maximumf128 => ("llvm.maximum", &[cx.type_f128()]),
// FIXME: LLVM currently mis-compile those intrinsics, re-enable them
// when llvm/llvm-project#{139380,139381,140445} are fixed.
//sym::maximumf16 => ("llvm.maximum", &[bx.type_f16()]),
//sym::maximumf32 => ("llvm.maximum", &[bx.type_f32()]),
//sym::maximumf64 => ("llvm.maximum", &[bx.type_f64()]),
//sym::maximumf128 => ("llvm.maximum", &[cx.type_f128()]),
//
sym::copysignf16 => ("llvm.copysign", &[bx.type_f16()]),
sym::copysignf32 => ("llvm.copysign", &[bx.type_f32()]),
sym::copysignf64 => ("llvm.copysign", &[bx.type_f64()]),

View file

@ -76,8 +76,8 @@ impl SlotIndex {
index_in_bucket: idx as usize,
};
}
// SAFETY: We already ruled out idx 0, so `checked_ilog2` can't return `None`.
let bucket = unsafe { idx.checked_ilog2().unwrap_unchecked() as usize };
// We already ruled out idx 0, so this `ilog2` never panics (and the check optimizes away)
let bucket = idx.ilog2() as usize;
let entries = 1 << bucket;
SlotIndex {
bucket_idx: bucket - FIRST_BUCKET_SHIFT + 1,

View file

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

View file

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

View file

@ -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(),

View file

@ -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();

View file

@ -411,6 +411,15 @@ pub fn compile_declarative_macro(
if let Err(e) = p.expect(exp!(FatArrow)) {
return dummy_syn_ext(e.emit());
}
if p.token == token::Eof {
let err_sp = p.token.span.shrink_to_hi();
let guar = sess
.dcx()
.struct_span_err(err_sp, "macro definition ended unexpectedly")
.with_span_label(err_sp, "expected right-hand side of macro rule")
.emit();
return dummy_syn_ext(guar);
}
let rhs_tt = p.parse_token_tree();
let rhs_tt = mbe::quoted::parse(
&TokenStream::new(vec![rhs_tt]),

View file

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

View file

@ -100,8 +100,8 @@ use self::compare_impl_item::collect_return_position_impl_trait_in_trait_tys;
use self::region::region_scope_tree;
use crate::{errors, require_c_abi_if_c_variadic};
pub fn provide(providers: &mut Providers) {
wfcheck::provide(providers);
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
pub(super) fn provide(providers: &mut Providers) {
*providers = Providers {
adt_destructor,
adt_async_destructor,
@ -109,6 +109,8 @@ pub fn provide(providers: &mut Providers) {
collect_return_position_impl_trait_in_trait_tys,
compare_impl_item: compare_impl_item::compare_impl_item,
check_coroutine_obligations: check::check_coroutine_obligations,
check_type_wf: wfcheck::check_type_wf,
check_well_formed: wfcheck::check_well_formed,
..*providers
};
}

View file

@ -15,7 +15,6 @@ use rustc_infer::infer::{self, InferCtxt, SubregionOrigin, TyCtxtInferExt};
use rustc_lint_defs::builtin::SUPERTRAIT_ITEM_SHADOWING_DEFINITION;
use rustc_macros::LintDiagnostic;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::query::Providers;
use rustc_middle::traits::solve::NoSolution;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
@ -189,7 +188,10 @@ where
}
}
fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
pub(super) fn check_well_formed(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
) -> Result<(), ErrorGuaranteed> {
let mut res = crate::check::check::check_item_type(tcx, def_id);
for param in &tcx.generics_of(def_id).own_params {
@ -2249,7 +2251,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
}
}
fn check_type_wf(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> {
pub(super) fn check_type_wf(tcx: TyCtxt<'_>, (): ()) -> Result<(), ErrorGuaranteed> {
let items = tcx.hir_crate_items(());
let res = items
.par_items(|item| tcx.ensure_ok().check_well_formed(item.owner_id.def_id))
@ -2397,7 +2399,3 @@ struct RedundantLifetimeArgsLint<'tcx> {
// The lifetime we can replace the victim with.
candidate: ty::Region<'tcx>,
}
pub fn provide(providers: &mut Providers) {
*providers = Providers { check_type_wf, check_well_formed, ..*providers };
}

View file

@ -1,16 +1,11 @@
use rustc_data_structures::unord::{ExtendUnord, UnordSet};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
use rustc_session::lint;
use tracing::debug;
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { check_unused_traits, ..*providers };
}
fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
pub(super) fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
let mut used_trait_imports = UnordSet::<LocalDefId>::default();
// FIXME: Use `tcx.hir_par_body_owners()` when we implement creating `DefId`s

View file

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

View file

@ -130,6 +130,7 @@ fn enforce_empty_impls_for_marker_traits(
.emit())
}
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`].
pub(crate) fn provide(providers: &mut Providers) {
use self::builtin::coerce_unsized_info;
use self::inherent_impls::{

View file

@ -61,6 +61,7 @@ mod type_of;
///////////////////////////////////////////////////////////////////////////
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
pub(crate) fn provide(providers: &mut Providers) {
resolve_bound_vars::provide(providers);
*providers = Providers {
@ -778,9 +779,11 @@ fn lower_variant<'tcx>(
fields,
parent_did.to_def_id(),
recovered,
adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
|| variant_did
.is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
adt_kind == AdtKind::Struct
&& find_attr!(tcx.get_all_attrs(parent_did), AttributeKind::NonExhaustive(..))
|| variant_did.is_some_and(|variant_did| {
find_attr!(tcx.get_all_attrs(variant_did), AttributeKind::NonExhaustive(..))
}),
)
}

View file

@ -222,6 +222,7 @@ enum BinderScopeType {
type ScopeRef<'a> = &'a Scope<'a>;
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers {
resolve_bound_vars,

View file

@ -4,7 +4,6 @@ use rustc_hir::{self as hir, AmbigArg, ForeignItem, ForeignItemKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{ObligationCause, ObligationCauseCode, WellFormedLoc};
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode, fold_regions};
use rustc_span::def_id::LocalDefId;
use rustc_trait_selection::traits::{self, ObligationCtxt};
@ -12,13 +11,9 @@ use tracing::debug;
use crate::collect::ItemCtxt;
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { diagnostic_hir_wf_check, ..*providers };
}
// Ideally, this would be in `rustc_trait_selection`, but we
// need access to `ItemCtxt`
fn diagnostic_hir_wf_check<'tcx>(
pub(super) fn diagnostic_hir_wf_check<'tcx>(
tcx: TyCtxt<'tcx>,
(predicate, loc): (ty::Predicate<'tcx>, WellFormedLoc),
) -> Option<ObligationCause<'tcx>> {

View file

@ -150,18 +150,21 @@ fn require_c_abi_if_c_variadic(
.emit();
}
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
pub fn provide(providers: &mut Providers) {
collect::provide(providers);
coherence::provide(providers);
check::provide(providers);
check_unused::provide(providers);
variance::provide(providers);
outlives::provide(providers);
hir_wf_check::provide(providers);
*providers = Providers {
check_unused_traits: check_unused::check_unused_traits,
diagnostic_hir_wf_check: hir_wf_check::diagnostic_hir_wf_check,
inferred_outlives_crate: outlives::inferred_outlives_crate,
inferred_outlives_of: outlives::inferred_outlives_of,
inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item,
enforce_impl_non_lifetime_params_are_constrained:
impl_wf_check::enforce_impl_non_lifetime_params_are_constrained,
crate_variances: variance::crate_variances,
variances_of: variance::variances_of,
..*providers
};
}

View file

@ -1,6 +1,5 @@
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, CratePredicatesMap, GenericArgKind, TyCtxt, Upcast};
use rustc_span::Span;
@ -9,11 +8,10 @@ mod explicit;
mod implicit_infer;
mod utils;
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { inferred_outlives_of, inferred_outlives_crate, ..*providers };
}
fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] {
pub(super) fn inferred_outlives_of(
tcx: TyCtxt<'_>,
item_def_id: LocalDefId,
) -> &[(ty::Clause<'_>, Span)] {
match tcx.def_kind(item_def_id) {
DefKind::Struct | DefKind::Enum | DefKind::Union => {
let crate_map = tcx.inferred_outlives_crate(());
@ -48,7 +46,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
}
}
fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
pub(super) fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
// Compute a map from each ADT (struct/enum/union) and lazy type alias to
// the **explicit** outlives predicates (`T: 'a`, `'a: 'b`) that the user wrote.
// Typically there won't be many of these, except in older code where

View file

@ -8,7 +8,6 @@ use rustc_arena::DroplessArena;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::{
self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
@ -27,18 +26,14 @@ mod solve;
pub(crate) mod dump;
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { variances_of, crate_variances, ..*providers };
}
fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> {
pub(super) fn crate_variances(tcx: TyCtxt<'_>, (): ()) -> CrateVariancesMap<'_> {
let arena = DroplessArena::default();
let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &arena);
let constraints_cx = constraints::add_constraints_from_crate(terms_cx);
solve::solve_constraints(constraints_cx)
}
fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
pub(super) fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
// Skip items with no generics - there's nothing to infer in them.
if tcx.generics_of(item_def_id).is_empty() {
return &[];

View file

@ -536,7 +536,12 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! {
diag.emit()
}
/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
pub fn provide(providers: &mut Providers) {
method::provide(providers);
*providers = Providers { typeck, used_trait_imports, ..*providers };
*providers = Providers {
method_autoderef_steps: method::probe::method_autoderef_steps,
typeck,
used_trait_imports,
..*providers
};
}

View file

@ -13,7 +13,6 @@ use rustc_hir::def::{CtorOf, DefKind, Namespace};
use rustc_hir::def_id::DefId;
use rustc_infer::infer::{BoundRegionConversionTime, InferOk};
use rustc_infer::traits::PredicateObligations;
use rustc_middle::query::Providers;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{
self, GenericArgs, GenericArgsRef, GenericParamDefKind, Ty, TypeVisitableExt,
@ -28,10 +27,6 @@ pub(crate) use self::MethodError::*;
use self::probe::{IsSuggestion, ProbeScope};
use crate::FnCtxt;
pub(crate) fn provide(providers: &mut Providers) {
probe::provide(providers);
}
#[derive(Clone, Copy, Debug)]
pub(crate) struct MethodCallee<'tcx> {
/// Impl method ID, for inherent methods, or trait method ID, otherwise.

View file

@ -15,7 +15,6 @@ use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryRespons
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TyCtxtInferExt};
use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::middle::stability;
use rustc_middle::query::Providers;
use rustc_middle::ty::elaborate::supertrait_def_ids;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
use rustc_middle::ty::{
@ -554,11 +553,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
pub(crate) fn provide(providers: &mut Providers) {
providers.method_autoderef_steps = method_autoderef_steps;
}
fn method_autoderef_steps<'tcx>(
pub(crate) fn method_autoderef_steps<'tcx>(
tcx: TyCtxt<'tcx>,
goal: CanonicalTyGoal<'tcx>,
) -> MethodAutoderefStepsResult<'tcx> {

View file

@ -871,8 +871,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
providers.analysis = analysis;
providers.hir_crate = rustc_ast_lowering::lower_to_hir;
providers.resolver_for_lowering_raw = resolver_for_lowering_raw;
providers.stripped_cfg_items =
|tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal());
providers.stripped_cfg_items = |tcx, _| &tcx.resolutions(()).stripped_cfg_items[..];
providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1;
providers.early_lint_checks = early_lint_checks;
providers.env_var_os = env_var_os;

View file

@ -45,11 +45,24 @@ impl Linker {
}
pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) {
let (codegen_results, work_products) = sess.time("finish_ongoing_codegen", || {
let (codegen_results, mut work_products) = sess.time("finish_ongoing_codegen", || {
codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)
});
sess.timings.end_section(sess.dcx(), TimingSection::Codegen);
if sess.opts.incremental.is_some()
&& let Some(path) = self.metadata.path()
&& let Some((id, product)) =
rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
sess,
"metadata",
&[("rmeta", path)],
&[],
)
{
work_products.insert(id, product);
}
sess.dcx().abort_if_errors();
let _timer = sess.timer("link");

View file

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

View file

@ -20,6 +20,7 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" }
rustc_fs_util = { path = "../rustc_fs_util" }
rustc_hir = { path = "../rustc_hir" }
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
rustc_incremental = { path = "../rustc_incremental" }
rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_middle = { path = "../rustc_middle" }

View file

@ -16,6 +16,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::{CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE, LocalDefId, LocalDefIdSet};
use rustc_hir::definitions::DefPathData;
use rustc_hir_pretty::id_to_string;
use rustc_middle::dep_graph::WorkProductId;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::metadata_symbol_name;
use rustc_middle::mir::interpret;
@ -2307,6 +2308,8 @@ pub struct EncodedMetadata {
// This is an optional stub metadata containing only the crate header.
// The header should be very small, so we load it directly into memory.
stub_metadata: Option<Vec<u8>>,
// The path containing the metadata, to record as work product.
path: Option<Box<Path>>,
// We need to carry MaybeTempDir to avoid deleting the temporary
// directory while accessing the Mmap.
_temp_dir: Option<MaybeTempDir>,
@ -2322,14 +2325,24 @@ impl EncodedMetadata {
let file = std::fs::File::open(&path)?;
let file_metadata = file.metadata()?;
if file_metadata.len() == 0 {
return Ok(Self { full_metadata: None, stub_metadata: None, _temp_dir: None });
return Ok(Self {
full_metadata: None,
stub_metadata: None,
path: None,
_temp_dir: None,
});
}
let full_mmap = unsafe { Some(Mmap::map(file)?) };
let stub =
if let Some(stub_path) = stub_path { Some(std::fs::read(stub_path)?) } else { None };
Ok(Self { full_metadata: full_mmap, stub_metadata: stub, _temp_dir: temp_dir })
Ok(Self {
full_metadata: full_mmap,
stub_metadata: stub,
path: Some(path.into()),
_temp_dir: temp_dir,
})
}
#[inline]
@ -2341,6 +2354,11 @@ impl EncodedMetadata {
pub fn stub_or_full(&self) -> &[u8] {
self.stub_metadata.as_deref().unwrap_or(self.full())
}
#[inline]
pub fn path(&self) -> Option<&Path> {
self.path.as_deref()
}
}
impl<S: Encoder> Encodable<S> for EncodedMetadata {
@ -2365,17 +2383,53 @@ impl<D: Decoder> Decodable<D> for EncodedMetadata {
None
};
Self { full_metadata, stub_metadata: stub, _temp_dir: None }
Self { full_metadata, stub_metadata: stub, path: None, _temp_dir: None }
}
}
#[instrument(level = "trace", skip(tcx))]
pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata");
// Since encoding metadata is not in a query, and nothing is cached,
// there's no need to do dep-graph tracking for any of it.
tcx.dep_graph.assert_ignored();
// Generate the metadata stub manually, as that is a small file compared to full metadata.
if let Some(ref_path) = ref_path {
let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata_stub");
with_encode_metadata_header(tcx, ref_path, |ecx| {
let header: LazyValue<CrateHeader> = ecx.lazy(CrateHeader {
name: tcx.crate_name(LOCAL_CRATE),
triple: tcx.sess.opts.target_triple.clone(),
hash: tcx.crate_hash(LOCAL_CRATE),
is_proc_macro_crate: false,
is_stub: true,
});
header.position.get()
})
}
let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata");
let dep_node = tcx.metadata_dep_node();
// If the metadata dep-node is green, try to reuse the saved work product.
if tcx.dep_graph.is_fully_enabled()
&& let work_product_id = WorkProductId::from_cgu_name("metadata")
&& let Some(work_product) = tcx.dep_graph.previous_work_product(&work_product_id)
&& tcx.try_mark_green(&dep_node)
{
let saved_path = &work_product.saved_files["rmeta"];
let incr_comp_session_dir = tcx.sess.incr_comp_session_dir_opt().unwrap();
let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, saved_path);
debug!("copying preexisting metadata from {source_file:?} to {path:?}");
match rustc_fs_util::link_or_copy(&source_file, path) {
Ok(_) => {}
Err(err) => tcx.dcx().emit_fatal(FailCreateFileEncoder { err }),
};
return;
};
if tcx.sess.threads() != 1 {
// Prefetch some queries used by metadata encoding.
// This is not necessary for correctness, but is only done for performance reasons.
@ -2389,35 +2443,32 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
);
}
with_encode_metadata_header(tcx, path, |ecx| {
// Encode all the entries and extra information in the crate,
// culminating in the `CrateRoot` which points to all of it.
let root = ecx.encode_crate_root();
// Perform metadata encoding inside a task, so the dep-graph can check if any encoded
// information changes, and maybe reuse the work product.
tcx.dep_graph.with_task(
dep_node,
tcx,
path,
|tcx, path| {
with_encode_metadata_header(tcx, path, |ecx| {
// Encode all the entries and extra information in the crate,
// culminating in the `CrateRoot` which points to all of it.
let root = ecx.encode_crate_root();
// Flush buffer to ensure backing file has the correct size.
ecx.opaque.flush();
// Record metadata size for self-profiling
tcx.prof.artifact_size(
"crate_metadata",
"crate_metadata",
ecx.opaque.file().metadata().unwrap().len(),
);
// Flush buffer to ensure backing file has the correct size.
ecx.opaque.flush();
// Record metadata size for self-profiling
tcx.prof.artifact_size(
"crate_metadata",
"crate_metadata",
ecx.opaque.file().metadata().unwrap().len(),
);
root.position.get()
});
if let Some(ref_path) = ref_path {
with_encode_metadata_header(tcx, ref_path, |ecx| {
let header: LazyValue<CrateHeader> = ecx.lazy(CrateHeader {
name: tcx.crate_name(LOCAL_CRATE),
triple: tcx.sess.opts.target_triple.clone(),
hash: tcx.crate_hash(LOCAL_CRATE),
is_proc_macro_crate: false,
is_stub: true,
});
header.position.get()
});
}
root.position.get()
})
},
None,
);
}
fn with_encode_metadata_header(

View file

@ -98,6 +98,7 @@ rustc_with_all_queries!(define_dep_nodes![
[] fn TraitSelect() -> (),
[] fn CompileCodegenUnit() -> (),
[] fn CompileMonoItem() -> (),
[] fn Metadata() -> (),
]);
// WARNING: `construct` is generic and does not know that `CompileCodegenUnit` takes `Symbol`s as keys.
@ -115,6 +116,12 @@ pub(crate) fn make_compile_mono_item<'tcx>(
DepNode::construct(tcx, dep_kinds::CompileMonoItem, mono_item)
}
// WARNING: `construct` is generic and does not know that `Metadata` takes `()`s as keys.
// Be very careful changing this type signature!
pub(crate) fn make_metadata(tcx: TyCtxt<'_>) -> DepNode {
DepNode::construct(tcx, dep_kinds::Metadata, &())
}
pub trait DepNodeExt: Sized {
fn extract_def_id(&self, tcx: TyCtxt<'_>) -> Option<DefId>;

View file

@ -9,7 +9,7 @@ use crate::ty::{self, TyCtxt};
mod dep_node;
pub use dep_node::{DepKind, DepNode, DepNodeExt, dep_kinds, label_strs};
pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item};
pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item, make_metadata};
pub use rustc_query_system::dep_graph::debug::{DepNodeFilter, EdgeFilter};
pub use rustc_query_system::dep_graph::{
DepContext, DepGraphQuery, DepNodeIndex, Deps, SerializedDepGraph, SerializedDepNodeIndex,

View file

@ -195,7 +195,6 @@ rustc_queries! {
}
query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
no_hash
desc { "getting the resolver outputs" }
}
@ -2265,9 +2264,6 @@ rustc_queries! {
query maybe_unused_trait_imports(_: ()) -> &'tcx FxIndexSet<LocalDefId> {
desc { "fetching potentially unused trait imports" }
}
query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxIndexSet<Symbol> {
desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id) }
}
query stability_index(_: ()) -> &'tcx stability::Index {
arena_cache

View file

@ -4,6 +4,7 @@ use std::ops::Range;
use std::str;
use rustc_abi::{FIRST_VARIANT, ReprOptions, VariantIdx};
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::intern::Interned;
@ -278,7 +279,9 @@ impl AdtDefData {
debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr);
let mut flags = AdtFlags::NO_ADT_FLAGS;
if kind == AdtKind::Enum && tcx.has_attr(did, sym::non_exhaustive) {
if kind == AdtKind::Enum
&& find_attr!(tcx.get_all_attrs(did), AttributeKind::NonExhaustive(..))
{
debug!("found non-exhaustive variant list for {:?}", did);
flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
}

View file

@ -2058,9 +2058,8 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn iter_local_def_id(self) -> impl Iterator<Item = LocalDefId> {
// Create a dependency to the red node to be sure we re-execute this when the amount of
// definitions change.
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
// Depend on the `analysis` query to ensure compilation if finished.
self.ensure_ok().analysis(());
let definitions = &self.untracked.definitions;
gen {
@ -2080,9 +2079,8 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn def_path_table(self) -> &'tcx rustc_hir::definitions::DefPathTable {
// Create a dependency to the crate to be sure we re-execute this when the amount of
// definitions change.
self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
// Depend on the `analysis` query to ensure compilation if finished.
self.ensure_ok().analysis(());
// Freeze definitions once we start iterating on them, to prevent adding new ones
// while iterating. If some query needs to add definitions, it should be `ensure`d above.
@ -3366,6 +3364,10 @@ impl<'tcx> TyCtxt<'tcx> {
self.resolver_for_lowering_raw(()).0
}
pub fn metadata_dep_node(self) -> crate::dep_graph::DepNode {
crate::dep_graph::make_metadata(self)
}
/// Given an `impl_id`, return the trait it implements.
/// Return `None` if this is an inherent impl.
pub fn impl_trait_ref(
@ -3415,10 +3417,6 @@ pub struct DeducedParamAttrs {
pub fn provide(providers: &mut Providers) {
providers.maybe_unused_trait_imports =
|tcx, ()| &tcx.resolutions(()).maybe_unused_trait_imports;
providers.names_imported_by_glob_use = |tcx, id| {
tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
};
providers.extern_mod_stmt_cnum =
|tcx, id| tcx.resolutions(()).extern_crate_map.get(&id).cloned();
providers.is_panic_runtime =

View file

@ -33,7 +33,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::unord::UnordMap;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::{Diag, ErrorGuaranteed};
use rustc_hir::LangItem;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res};
@ -176,11 +176,11 @@ pub struct ResolverOutputs {
pub ast_lowering: ResolverAstLowering,
}
#[derive(Debug)]
#[derive(Debug, HashStable)]
pub struct ResolverGlobalCtxt {
pub visibilities_for_hashing: Vec<(LocalDefId, Visibility)>,
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
pub expn_that_defined: UnordMap<LocalDefId, ExpnId>,
pub effective_visibilities: EffectiveVisibilities,
pub extern_crate_map: UnordMap<LocalDefId, CrateNum>,
pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
@ -196,8 +196,8 @@ pub struct ResolverGlobalCtxt {
pub confused_type_with_std_module: FxIndexMap<Span, Span>,
pub doc_link_resolutions: FxIndexMap<LocalDefId, DocLinkResMap>,
pub doc_link_traits_in_scope: FxIndexMap<LocalDefId, Vec<DefId>>,
pub all_macro_rules: FxHashSet<Symbol>,
pub stripped_cfg_items: Steal<Vec<StrippedCfgItem>>,
pub all_macro_rules: UnordSet<Symbol>,
pub stripped_cfg_items: Vec<StrippedCfgItem>,
}
/// Resolutions that should only be used for lowering.
@ -243,7 +243,7 @@ pub struct DelegationFnSig {
pub target_feature: bool,
}
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, HashStable)]
pub struct MainDefinition {
pub res: Res<ast::NodeId>,
pub is_import: bool,
@ -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 }
}
}

View file

@ -319,9 +319,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
}
PatKind::Deref { subpattern }
}
hir::PatKind::Box(subpattern) => {
PatKind::Deref { subpattern: self.lower_pattern(subpattern) }
}
hir::PatKind::Box(subpattern) => PatKind::DerefPattern {
subpattern: self.lower_pattern(subpattern),
borrow: hir::ByRef::No,
},
hir::PatKind::Slice(prefix, slice, suffix) => {
self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix)

View file

@ -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
@ -302,6 +303,7 @@ fn emit_malformed_attribute(
| sym::rustc_allow_const_fn_unstable
| sym::naked
| sym::no_mangle
| sym::non_exhaustive
| sym::must_use
| sym::track_caller
| sym::link_name
@ -310,6 +312,7 @@ fn emit_malformed_attribute(
| sym::link_section
| sym::rustc_layout_scalar_valid_range_start
| sym::rustc_layout_scalar_valid_range_end
| sym::no_implicit_prelude
) {
return;
}

View file

@ -183,9 +183,20 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Attribute::Parsed(AttributeKind::Naked(attr_span)) => {
self.check_naked(hir_id, *attr_span, span, target)
}
Attribute::Parsed(AttributeKind::NoImplicitPrelude(attr_span)) => self
.check_generic_attr(
hir_id,
sym::no_implicit_prelude,
*attr_span,
target,
Target::Mod,
),
Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => {
self.check_track_caller(hir_id, *attr_span, attrs, span, target)
}
Attribute::Parsed(AttributeKind::NonExhaustive(attr_span)) => {
self.check_non_exhaustive(hir_id, *attr_span, span, target, item)
}
Attribute::Parsed(
AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span)
| AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span),
@ -213,6 +224,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() {
@ -226,7 +240,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::no_sanitize, ..] => {
self.check_no_sanitize(attr, span, target)
}
[sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target, item),
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
[sym::doc, ..] => self.check_doc_attrs(
@ -275,7 +288,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)
}
@ -289,16 +301,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::macro_use, ..] | [sym::macro_escape, ..] => {
self.check_macro_use(hir_id, attr, target)
}
[sym::path, ..] => self.check_generic_attr(hir_id, attr, target, Target::Mod),
[sym::path, ..] => self.check_generic_attr_unparsed(hir_id, attr, target, Target::Mod),
[sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
[sym::ignore, ..] | [sym::should_panic, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Fn)
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn)
}
[sym::automatically_derived, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Impl)
}
[sym::no_implicit_prelude, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Mod)
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Impl)
}
[sym::proc_macro, ..] => {
self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
@ -307,7 +316,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
}
[sym::proc_macro_derive, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Fn);
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn);
self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
}
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
@ -616,7 +625,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_generic_attr(
/// FIXME: Remove when all attributes are ported to the new parser
fn check_generic_attr_unparsed(
&self,
hir_id: HirId,
attr: &Attribute,
@ -639,6 +649,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_generic_attr(
&self,
hir_id: HirId,
attr_name: Symbol,
attr_span: Span,
target: Target,
allowed_target: Target,
) {
if target != allowed_target {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr_span,
errors::OnlyHasEffectOn {
attr_name: attr_name.to_string(),
target_name: allowed_target.name().replace(' ', "_"),
},
);
}
}
/// Checks if `#[naked]` is applied to a function definition.
fn check_naked(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
match target {
@ -750,7 +781,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_non_exhaustive(
&self,
hir_id: HirId,
attr: &Attribute,
attr_span: Span,
span: Span,
target: Target,
item: Option<ItemLike<'_>>,
@ -765,7 +796,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&& fields.iter().any(|f| f.default.is_some())
{
self.dcx().emit_err(errors::NonExhaustiveWithDefaultFieldValues {
attr_span: attr.span(),
attr_span,
defn_span: span,
});
}
@ -776,13 +807,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "non_exhaustive");
self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "non_exhaustive");
}
_ => {
self.dcx().emit_err(errors::NonExhaustiveWrongLocation {
attr_span: attr.span(),
defn_span: span,
});
self.dcx()
.emit_err(errors::NonExhaustiveWrongLocation { attr_span, defn_span: span });
}
}
}
@ -1438,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 });
}
}
}

View file

@ -221,27 +221,19 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
let slice = match ctor {
Struct | Variant(_) | UnionField => match ty.kind() {
ty::Tuple(fs) => reveal_and_alloc(cx, fs.iter()),
ty::Adt(adt, args) => {
if adt.is_box() {
// The only legal patterns of type `Box` (outside `std`) are `_` and box
// patterns. If we're here we can assume this is a box pattern.
reveal_and_alloc(cx, once(args.type_at(0)))
} else {
let variant =
&adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt));
let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| {
let is_visible =
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
let is_uninhabited = cx.is_uninhabited(*ty);
let is_unstable =
cx.tcx.lookup_stability(field.did).is_some_and(|stab| {
stab.is_unstable() && stab.feature != sym::rustc_private
});
let skip = is_uninhabited && (!is_visible || is_unstable);
(ty, PrivateUninhabitedField(skip))
ty::Adt(adt, _) => {
let variant = &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt));
let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| {
let is_visible =
adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx);
let is_uninhabited = cx.is_uninhabited(*ty);
let is_unstable = cx.tcx.lookup_stability(field.did).is_some_and(|stab| {
stab.is_unstable() && stab.feature != sym::rustc_private
});
cx.dropless_arena.alloc_from_iter(tys)
}
let skip = is_uninhabited && (!is_visible || is_unstable);
(ty, PrivateUninhabitedField(skip))
});
cx.dropless_arena.alloc_from_iter(tys)
}
_ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
},
@ -273,14 +265,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
Struct | Variant(_) | UnionField => match ty.kind() {
ty::Tuple(fs) => fs.len(),
ty::Adt(adt, ..) => {
if adt.is_box() {
// The only legal patterns of type `Box` (outside `std`) are `_` and box
// patterns. If we're here we can assume this is a box pattern.
1
} else {
let variant_idx = RustcPatCtxt::variant_index_for_adt(&ctor, *adt);
adt.variant(variant_idx).fields.len()
}
let variant_idx = RustcPatCtxt::variant_index_for_adt(&ctor, *adt);
adt.variant(variant_idx).fields.len()
}
_ => bug!("Unexpected type for constructor `{ctor:?}`: {ty:?}"),
},
@ -470,8 +456,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
fields = vec![self.lower_pat(subpattern).at_index(0)];
arity = 1;
ctor = match ty.kind() {
// This is a box pattern.
ty::Adt(adt, ..) if adt.is_box() => Struct,
ty::Ref(..) => Ref,
_ => span_bug!(
pat.span,
@ -501,28 +485,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
.map(|ipat| self.lower_pat(&ipat.pattern).at_index(ipat.field.index()))
.collect();
}
ty::Adt(adt, _) if adt.is_box() => {
// The only legal patterns of type `Box` (outside `std`) are `_` and box
// patterns. If we're here we can assume this is a box pattern.
// FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
// _)` or a box pattern. As a hack to avoid an ICE with the former, we
// ignore other fields than the first one. This will trigger an error later
// anyway.
// See https://github.com/rust-lang/rust/issues/82772,
// explanation: https://github.com/rust-lang/rust/pull/82789#issuecomment-796921977
// The problem is that we can't know from the type whether we'll match
// normally or through box-patterns. We'll have to figure out a proper
// solution when we introduce generalized deref patterns. Also need to
// prevent mixing of those two options.
let pattern = subpatterns.into_iter().find(|pat| pat.field.index() == 0);
if let Some(pat) = pattern {
fields = vec![self.lower_pat(&pat.pattern).at_index(0)];
} else {
fields = vec![];
}
ctor = Struct;
arity = 1;
}
ty::Adt(adt, _) => {
ctor = match pat.kind {
PatKind::Leaf { .. } if adt.is_union() => UnionField,
@ -825,11 +787,6 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
Bool(b) => b.to_string(),
Str(s) => s.to_string(),
IntRange(range) => return self.print_pat_range(range, *pat.ty()),
Struct if pat.ty().is_box() => {
// Outside of the `alloc` crate, the only way to create a struct pattern
// of type `Box` is to use a `box` pattern via #[feature(box_patterns)].
format!("box {}", print(&pat.fields[0]))
}
Struct | Variant(_) | UnionField => {
let enum_info = match *pat.ty().kind() {
ty::Adt(adt_def, _) if adt_def.is_enum() => EnumInfo::Enum {
@ -866,6 +823,14 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
print::write_ref_like(&mut s, pat.ty().inner(), &print(&pat.fields[0])).unwrap();
s
}
DerefPattern(_) if pat.ty().is_box() && !self.tcx.features().deref_patterns() => {
// FIXME(deref_patterns): Remove this special handling once `box_patterns` is gone.
// HACK(@dianne): `box _` syntax is exposed on stable in diagnostics, e.g. to
// witness non-exhaustiveness of `match Box::new(0) { Box { .. } if false => {} }`.
// To avoid changing diagnostics before deref pattern syntax is finalized, let's use
// `box _` syntax unless `deref_patterns` is enabled.
format!("box {}", print(&pat.fields[0]))
}
DerefPattern(_) => format!("deref!({})", print(&pat.fields[0])),
Slice(slice) => {
let (prefix_len, has_dot_dot) = match slice.kind {
@ -964,12 +929,8 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
ty: &Self::Ty,
) -> fmt::Result {
if let ty::Adt(adt, _) = ty.kind() {
if adt.is_box() {
write!(f, "Box")?
} else {
let variant = adt.variant(Self::variant_index_for_adt(ctor, *adt));
write!(f, "{}", variant.name)?;
}
let variant = adt.variant(Self::variant_index_for_adt(ctor, *adt));
write!(f, "{}", variant.name)?;
}
Ok(())
}

View file

@ -923,6 +923,17 @@ macro_rules! define_queries {
}
}
pub(crate) fn Metadata<'tcx>() -> DepKindStruct<'tcx> {
DepKindStruct {
is_anon: false,
is_eval_always: false,
fingerprint_style: FingerprintStyle::Unit,
force_from_dep_node: None,
try_load_from_on_disk_cache: None,
name: &"Metadata",
}
}
$(pub(crate) fn $name<'tcx>()-> DepKindStruct<'tcx> {
$crate::plumbing::query_callback::<query_impl::$name::QueryType<'tcx>>(
is_anon!([$($modifiers)*]),

View file

@ -5,7 +5,7 @@ use rustc_ast::{
self as ast, CRATE_NODE_ID, Crate, ItemKind, MetaItemInner, MetaItemKind, ModKind, NodeId, Path,
};
use rustc_ast_pretty::pprust;
use rustc_attr_data_structures::{self as attr, Stability};
use rustc_attr_data_structures::{self as attr, AttributeKind, Stability, find_attr};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::codes::*;
@ -1998,9 +1998,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Otherwise, point out if the struct has any private fields.
if let Some(def_id) = res.opt_def_id()
&& !def_id.is_local()
&& let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
&& let Some(attr_span) = find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::NonExhaustive(span) => *span)
{
non_exhaustive = Some(attr.span());
non_exhaustive = Some(attr_span);
} else if let Some(span) = ctor_fields_span {
let label = errors::ConstructorPrivateIfAnyFieldPrivate { span };
err.subdiagnostic(label);

View file

@ -46,7 +46,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::FreezeReadGuard;
use rustc_data_structures::unord::UnordMap;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed};
use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind};
use rustc_feature::BUILTIN_ATTRIBUTES;
@ -1031,7 +1031,7 @@ pub struct Resolver<'ra, 'tcx> {
tcx: TyCtxt<'tcx>,
/// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
expn_that_defined: UnordMap<LocalDefId, ExpnId>,
graph_root: Module<'ra>,
@ -1208,7 +1208,7 @@ pub struct Resolver<'ra, 'tcx> {
effective_visibilities: EffectiveVisibilities,
doc_link_resolutions: FxIndexMap<LocalDefId, DocLinkResMap>,
doc_link_traits_in_scope: FxIndexMap<LocalDefId, Vec<DefId>>,
all_macro_rules: FxHashSet<Symbol>,
all_macro_rules: UnordSet<Symbol>,
/// Invocation ids of all glob delegations.
glob_delegation_invoc_ids: FxHashSet<LocalExpnId>,
@ -1653,16 +1653,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let confused_type_with_std_module = self.confused_type_with_std_module;
let effective_visibilities = self.effective_visibilities;
let stripped_cfg_items = Steal::new(
self.stripped_cfg_items
.into_iter()
.filter_map(|item| {
let parent_module =
self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id();
Some(StrippedCfgItem { parent_module, ident: item.ident, cfg: item.cfg })
})
.collect(),
);
let stripped_cfg_items = self
.stripped_cfg_items
.into_iter()
.filter_map(|item| {
let parent_module =
self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id();
Some(StrippedCfgItem { parent_module, ident: item.ident, cfg: item.cfg })
})
.collect();
let global_ctxt = ResolverGlobalCtxt {
expn_that_defined,

View file

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

View file

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

View file

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

View file

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

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

View file

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

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

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

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

View file

@ -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:?}"))
}
}

View file

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

View file

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

View 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

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

View file

@ -1623,7 +1623,6 @@ symbols! {
pointee_sized,
pointee_trait,
pointer,
pointer_like,
poll,
poll_next,
position,

View file

@ -21,19 +21,9 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
if let ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) =
key.value.predicate.kind().skip_binder()
&& term.is_trivially_wf(tcx)
{
match term.as_type()?.kind() {
ty::Param(_)
| ty::Bool
| ty::Char
| ty::Int(_)
| ty::Float(_)
| ty::Str
| ty::Uint(_) => {
return Some(());
}
_ => {}
}
return Some(());
}
None

View file

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

View file

@ -368,16 +368,17 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
// Proving `Sized`/`MetaSized`, very often on "obviously sized" types like
// `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
// canonicalize and all that for such cases.
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) =
if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
predicate.kind().skip_binder()
&& trait_pred.polarity == ty::PredicatePolarity::Positive
{
let sizedness = match tcx.as_lang_item(trait_ref.def_id()) {
let sizedness = match tcx.as_lang_item(trait_pred.def_id()) {
Some(LangItem::Sized) => SizedTraitKind::Sized,
Some(LangItem::MetaSized) => SizedTraitKind::MetaSized,
_ => return false,
};
if trait_ref.self_ty().has_trivial_sizedness(tcx, sizedness) {
if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) {
debug!("fast path -- trivial sizedness");
return true;
}

View file

@ -6,11 +6,11 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::bug;
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt, Upcast};
use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeVisitableExt};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits::{
ImplSource, Obligation, ObligationCause, ObligationCtxt, ScrubbedTraitError, SelectionContext,
SelectionError, sizedness_fast_path,
SelectionError,
};
use tracing::debug;
@ -34,13 +34,6 @@ pub(crate) fn codegen_select_candidate<'tcx>(
let (infcx, param_env) = tcx.infer_ctxt().ignoring_regions().build_with_typing_env(typing_env);
let mut selcx = SelectionContext::new(&infcx);
if sizedness_fast_path(tcx, trait_ref.upcast(tcx)) {
return Ok(&*tcx.arena.alloc(ImplSource::Builtin(
ty::solve::BuiltinImplSource::Trivial,
Default::default(),
)));
}
let obligation_cause = ObligationCause::dummy();
let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);

View file

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

View file

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

View file

@ -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)]

View file

@ -61,4 +61,71 @@ impl bool {
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
if self { Some(f()) } else { None }
}
/// Returns `Ok(())` if the `bool` is [`true`](../std/keyword.true.html),
/// or `Err(err)` otherwise.
///
/// Arguments passed to `ok_or` are eagerly evaluated; if you are
/// passing the result of a function call, it is recommended to use
/// [`ok_or_else`], which is lazily evaluated.
///
/// [`ok_or_else`]: bool::ok_or_else
///
/// # Examples
///
/// ```
/// #![feature(bool_to_result)]
///
/// assert_eq!(false.ok_or(0), Err(0));
/// assert_eq!(true.ok_or(0), Ok(()));
/// ```
///
/// ```
/// #![feature(bool_to_result)]
///
/// let mut a = 0;
/// let mut function_with_side_effects = || { a += 1; };
///
/// assert!(true.ok_or(function_with_side_effects()).is_ok());
/// assert!(false.ok_or(function_with_side_effects()).is_err());
///
/// // `a` is incremented twice because the value passed to `ok_or` is
/// // evaluated eagerly.
/// assert_eq!(a, 2);
/// ```
#[unstable(feature = "bool_to_result", issue = "142748")]
#[inline]
pub fn ok_or<E>(self, err: E) -> Result<(), E> {
if self { Ok(()) } else { Err(err) }
}
/// Returns `Ok(())` if the `bool` is [`true`](../std/keyword.true.html),
/// or `Err(f())` otherwise.
///
/// # Examples
///
/// ```
/// #![feature(bool_to_result)]
///
/// assert_eq!(false.ok_or_else(|| 0), Err(0));
/// assert_eq!(true.ok_or_else(|| 0), Ok(()));
/// ```
///
/// ```
/// #![feature(bool_to_result)]
///
/// let mut a = 0;
///
/// assert!(true.ok_or_else(|| { a += 1; }).is_ok());
/// assert!(false.ok_or_else(|| { a += 1; }).is_err());
///
/// // `a` is incremented once because the closure is evaluated lazily by
/// // `ok_or_else`.
/// assert_eq!(a, 1);
/// ```
#[unstable(feature = "bool_to_result", issue = "142748")]
#[inline]
pub fn ok_or_else<E, F: FnOnce() -> E>(self, f: F) -> Result<(), E> {
if self { Ok(()) } else { Err(f()) }
}
}

View file

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

View file

@ -1449,7 +1449,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
/// check `==` and `<` separately to do rather than needing to calculate
/// (then optimize out) the three-way `Ordering` result.
#[inline]
#[must_use]
// Added to improve the behaviour of tuples; not necessarily stabilization-track.
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
#[doc(hidden)]
@ -1459,7 +1458,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
/// Same as `__chaining_lt`, but for `<=` instead of `<`.
#[inline]
#[must_use]
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
#[doc(hidden)]
fn __chaining_le(&self, other: &Rhs) -> ControlFlow<bool> {
@ -1468,7 +1466,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
/// Same as `__chaining_lt`, but for `>` instead of `<`.
#[inline]
#[must_use]
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
#[doc(hidden)]
fn __chaining_gt(&self, other: &Rhs) -> ControlFlow<bool> {
@ -1477,7 +1474,6 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
/// Same as `__chaining_lt`, but for `>=` instead of `<`.
#[inline]
#[must_use]
#[unstable(feature = "partial_ord_chaining_methods", issue = "none")]
#[doc(hidden)]
fn __chaining_ge(&self, other: &Rhs) -> ControlFlow<bool> {

View file

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

View file

@ -943,7 +943,7 @@ impl f64 {
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f64::max`] which only returns NaN when *both* arguments are NaN.
///
/// ```ignore-arm-unknown-linux-gnueabihf,ignore-i586 (see https://github.com/rust-lang/rust/issues/141087)
/// ```
/// #![feature(float_minimum_maximum)]
/// let x = 1.0_f64;
/// let y = 2.0_f64;
@ -970,7 +970,7 @@ impl f64 {
/// This returns NaN when *either* argument is NaN, as opposed to
/// [`f64::min`] which only returns NaN when *both* arguments are NaN.
///
/// ```ignore-arm-unknown-linux-gnueabihf,ignore-i586 (see https://github.com/rust-lang/rust/issues/141087)
/// ```
/// #![feature(float_minimum_maximum)]
/// let x = 1.0_f64;
/// let y = 2.0_f64;

View file

@ -2572,7 +2572,7 @@ macro_rules! uint_impl {
if size_of::<Self>() == 1 {
// Trick LLVM into generating the psadbw instruction when SSE2
// is available and this function is autovectorized for u8's.
(self as i32).wrapping_sub(other as i32).abs() as Self
(self as i32).wrapping_sub(other as i32).unsigned_abs() as Self
} else {
if self < other {
other - self

View file

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

View file

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

View file

@ -105,3 +105,11 @@ fn test_bool_to_option() {
assert_eq!(D, Some(0));
*/
}
#[test]
fn test_bool_to_result() {
assert_eq!(false.ok_or(0), Err(0));
assert_eq!(true.ok_or(0), Ok(()));
assert_eq!(false.ok_or_else(|| 0), Err(0));
assert_eq!(true.ok_or_else(|| 0), Ok(()));
}

View file

@ -11,6 +11,7 @@
#![feature(async_iter_from_iter)]
#![feature(async_iterator)]
#![feature(bigint_helper_methods)]
#![feature(bool_to_result)]
#![feature(bstr)]
#![feature(cfg_target_has_reliable_f16_f128)]
#![feature(char_max_len)]

View file

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

Some files were not shown because too many files have changed in this diff Show more