diff options
Diffstat (limited to 'compiler')
84 files changed, 4099 insertions, 2732 deletions
diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 18f0750aaa1..8d3c10fd770 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -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. diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 61ef31b8f9f..b5934f4e36e 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -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), diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index a1b1d670cfe..02e95ddcb6f 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -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 } } } diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 5437803d781..8ad98c8d1d4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -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; +} diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 0215504b52b..f5ac3890a46 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -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; diff --git a/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs new file mode 100644 index 00000000000..47cc925f7f6 --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/no_implicit_prelude.rs @@ -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; +} diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs new file mode 100644 index 00000000000..94f6a65c74e --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs @@ -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; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index bf8b1438df7..265e1bb6a8c 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -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 diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index ffb932a3c38..04f1129d87c 100644 --- a/compiler/rustc_codegen_cranelift/src/allocator.rs +++ b/compiler/rustc_codegen_cranelift/src/allocator.rs @@ -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 { diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs index cf8aa500c77..0d8dc93274f 100644 --- a/compiler/rustc_codegen_gcc/src/allocator.rs +++ b/compiler/rustc_codegen_gcc/src/allocator.rs @@ -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<'_>, diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index 9dca63cfc8d..2b5090ed6db 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -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<'_>, diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 776658b9cca..35922c100cd 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -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()]), diff --git a/compiler/rustc_data_structures/src/vec_cache.rs b/compiler/rustc_data_structures/src/vec_cache.rs index 0ffa6b3205f..599970663db 100644 --- a/compiler/rustc_data_structures/src/vec_cache.rs +++ b/compiler/rustc_data_structures/src/vec_cache.rs @@ -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, diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 82e7468211d..c4181a62a35 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -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 diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index fe9797026de..5746c28a2ab 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -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, diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 3f5872f34a6..2f398cea926 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -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(), diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 4348610be0a..719d4ca625a 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -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(); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index dad2fd99ef2..2ffd4e3cf28 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -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]), diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 10dd5ff9aa7..c11db63ba11 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -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); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 5cec3331bb1..b2cfab37c1f 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -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 }; } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index ed8d25e9915..4934136bc7a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -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 }; -} diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 464ffa8711a..0133b1e8fcd 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -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 diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 734c9c58c08..65bc441a473 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -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> { diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 16bac430491..ed8f78216ff 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -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::{ diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index b10d5b55789..271104c20c6 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -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(..)) + }), ) } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 95743f9a63e..0e775d374ab 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -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, diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index fef0dbf2ece..bf539dfab42 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -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>> { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 2ff7caef732..3a153ab089a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -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 }; } diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index 499f5572f47..d155f4f98ad 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -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 diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index dbba45dc7bb..0666b335e09 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -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 &[]; diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 1cc618e2aee..ea8c2c6ce23 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -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 + }; } diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 8380c3710e6..316468b0a5d 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -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. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index be0eb13cace..94c93e73627 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -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> { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 3fe7c5e4286..a438cde018c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -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; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 2bc30fa7cb0..370e886c525 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -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"); diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs index d85618f664d..d3b3b55dd4c 100644 --- a/compiler/rustc_lint/src/pass_by_value.rs +++ b/compiler/rustc_lint/src/pass_by_value.rs @@ -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)); } } diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index a163518fd19..0edc1d18ecc 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -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" } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 90bc427a19a..b0ec605a85f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -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(); - - // 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() - }); + // 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(), + ); - 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( diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index 0c998a2cbb3..0c757a390ca 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -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>; diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 0a8e6153817..781e3e442e6 100644 --- a/compiler/rustc_middle/src/dep_graph/mod.rs +++ b/compiler/rustc_middle/src/dep_graph/mod.rs @@ -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, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 8c20e71e26a..17a29c9ae4b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -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 diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 6d5a3abf665..44165b06f1c 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -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; } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index efa47b57cf3..e8b15b76fd8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -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 = diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 84b21fee92f..a92d6fe3916 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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 } } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index e44a440b5c1..a44afed5492 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -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) diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 4d64cdeb69a..27355a422d1 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -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; } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 87d46e3e506..c5ced406414 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -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 }); } } } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 46ced7500ea..e53cebc59ba 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -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(()) } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 9fbbcdc7556..55549cba737 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -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)*]), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 18078b760c3..c99bc747fd2 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -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); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 05bc3611dd8..7162f3a77d3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -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, diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 5b88a7017c5..0516982aeab 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -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 diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 74e766a1e95..4627c2978fc 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -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 { diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 2982a920b03..dcdc77b76c2 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -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>; -} diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index a6d31ac4e13..ecaf3571896 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -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) } diff --git a/compiler/rustc_smir/src/rustc_smir/bridge.rs b/compiler/rustc_smir/src/rustc_smir/bridge.rs new file mode 100644 index 00000000000..a31eb93d0e8 --- /dev/null +++ b/compiler/rustc_smir/src/rustc_smir/bridge.rs @@ -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); diff --git a/compiler/rustc_smir/src/rustc_smir/builder.rs b/compiler/rustc_smir/src/rustc_smir/builder.rs index 40e6d21c063..2141053d09a 100644 --- a/compiler/rustc_smir/src/rustc_smir/builder.rs +++ b/compiler/rustc_smir/src/rustc_smir/builder.rs @@ -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 } } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs deleted file mode 100644 index 3fa83cfc6a0..00000000000 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ /dev/null @@ -1,1000 +0,0 @@ -//! Implementation of StableMIR Context. - -#![allow(rustc::usage_of_qualified_ty)] - -use std::cell::RefCell; -use std::iter; - -use rustc_abi::HasDataLayout; -use rustc_hir::{Attribute, LangItem}; -use rustc_middle::ty::layout::{ - FnAbiOf, FnAbiOfHelpers, HasTyCtxt, HasTypingEnv, LayoutOf, LayoutOfHelpers, -}; -use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; -use rustc_middle::ty::{ - CoroutineArgsExt, GenericPredicates, Instance, List, ScalarInt, TyCtxt, TypeVisitableExt, - ValTree, -}; -use rustc_middle::{mir, ty}; -use rustc_span::def_id::LOCAL_CRATE; -use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions}; -use stable_mir::mir::alloc::GlobalAlloc; -use stable_mir::mir::mono::{InstanceDef, StaticDef}; -use stable_mir::mir::{BinOp, Body, Place, UnOp}; -use stable_mir::target::{MachineInfo, MachineSize}; -use stable_mir::ty::{ - AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, - ForeignDef, ForeignItemKind, GenericArgs, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, - Span, Ty, TyConst, TyKind, UintTy, VariantDef, VariantIdx, -}; -use stable_mir::{Crate, CrateDef, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, Symbol}; - -use crate::rustc_internal::RustcInternal; -use crate::rustc_smir::builder::BodyBuilder; -use crate::rustc_smir::{Stable, Tables, alloc, filter_def_ids, new_item_kind, smir_crate}; -use crate::stable_mir; - -/// 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>(pub RefCell<Tables<'tcx>>); - -impl<'tcx> SmirCtxt<'tcx> { - pub fn target_info(&self) -> MachineInfo { - let mut tables = self.0.borrow_mut(); - MachineInfo { - endian: tables.tcx.data_layout.endian.stable(&mut *tables), - pointer_width: MachineSize::from_bits( - tables.tcx.data_layout.pointer_size.bits().try_into().unwrap(), - ), - } - } - - pub fn entry_fn(&self) -> Option<stable_mir::CrateItem> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - Some(tables.crate_item(tcx.entry_fn(())?.0)) - } - - /// Retrieve all items of the local crate that have a MIR associated with them. - pub fn all_local_items(&self) -> stable_mir::CrateItems { - let mut tables = self.0.borrow_mut(); - tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect() - } - - /// Retrieve the body of a function. - /// This function will panic if the body is not available. - pub fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body { - let mut tables = self.0.borrow_mut(); - let def_id = tables[item]; - tables.tcx.instance_mir(rustc_middle::ty::InstanceKind::Item(def_id)).stable(&mut tables) - } - - /// Check whether the body of a function is available. - pub fn has_body(&self, def: DefId) -> bool { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.internal(&mut *tables, tcx); - tables.item_has_body(def_id) - } - - pub fn foreign_modules(&self, crate_num: CrateNum) -> Vec<stable_mir::ty::ForeignModuleDef> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - tcx.foreign_modules(crate_num.internal(&mut *tables, tcx)) - .keys() - .map(|mod_def_id| tables.foreign_module_def(*mod_def_id)) - .collect() - } - - /// Retrieve all functions defined in this crate. - pub fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let krate = crate_num.internal(&mut *tables, tcx); - filter_def_ids(tcx, krate, |def_id| tables.to_fn_def(def_id)) - } - - /// Retrieve all static items defined in this crate. - pub fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let krate = crate_num.internal(&mut *tables, tcx); - filter_def_ids(tcx, krate, |def_id| tables.to_static(def_id)) - } - - pub fn foreign_module( - &self, - mod_def: stable_mir::ty::ForeignModuleDef, - ) -> stable_mir::ty::ForeignModule { - let mut tables = self.0.borrow_mut(); - let def_id = tables[mod_def.def_id()]; - let mod_def = tables.tcx.foreign_modules(def_id.krate).get(&def_id).unwrap(); - mod_def.stable(&mut *tables) - } - - pub fn foreign_items(&self, mod_def: stable_mir::ty::ForeignModuleDef) -> Vec<ForeignDef> { - let mut tables = self.0.borrow_mut(); - let def_id = tables[mod_def.def_id()]; - tables - .tcx - .foreign_modules(def_id.krate) - .get(&def_id) - .unwrap() - .foreign_items - .iter() - .map(|item_def| tables.foreign_def(*item_def)) - .collect() - } - - pub fn all_trait_decls(&self) -> stable_mir::TraitDecls { - let mut tables = self.0.borrow_mut(); - tables - .tcx - .all_traits_including_private() - .map(|trait_def_id| tables.trait_def(trait_def_id)) - .collect() - } - - pub fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - tcx.traits(crate_num.internal(&mut *tables, tcx)) - .iter() - .map(|trait_def_id| tables.trait_def(*trait_def_id)) - .collect() - } - - pub fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl { - let mut tables = self.0.borrow_mut(); - let def_id = tables[trait_def.0]; - let trait_def = tables.tcx.trait_def(def_id); - trait_def.stable(&mut *tables) - } - - pub fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - iter::once(LOCAL_CRATE) - .chain(tables.tcx.crates(()).iter().copied()) - .flat_map(|cnum| tcx.trait_impls_in_crate(cnum).iter()) - .map(|impl_def_id| tables.impl_def(*impl_def_id)) - .collect() - } - - pub fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - tcx.trait_impls_in_crate(crate_num.internal(&mut *tables, tcx)) - .iter() - .map(|impl_def_id| tables.impl_def(*impl_def_id)) - .collect() - } - - pub fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait { - let mut tables = self.0.borrow_mut(); - let def_id = tables[impl_def.0]; - let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap(); - impl_trait.stable(&mut *tables) - } - - pub fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics { - let mut tables = self.0.borrow_mut(); - let def_id = tables[def_id]; - let generics = tables.tcx.generics_of(def_id); - generics.stable(&mut *tables) - } - - pub fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates { - let mut tables = self.0.borrow_mut(); - let def_id = tables[def_id]; - let GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id); - stable_mir::ty::GenericPredicates { - parent: parent.map(|did| tables.trait_def(did)), - predicates: predicates - .iter() - .map(|(clause, span)| { - ( - clause.as_predicate().kind().skip_binder().stable(&mut *tables), - span.stable(&mut *tables), - ) - }) - .collect(), - } - } - - pub fn explicit_predicates_of( - &self, - def_id: stable_mir::DefId, - ) -> stable_mir::ty::GenericPredicates { - let mut tables = self.0.borrow_mut(); - let def_id = tables[def_id]; - let GenericPredicates { parent, predicates } = tables.tcx.explicit_predicates_of(def_id); - stable_mir::ty::GenericPredicates { - parent: parent.map(|did| tables.trait_def(did)), - predicates: predicates - .iter() - .map(|(clause, span)| { - ( - clause.as_predicate().kind().skip_binder().stable(&mut *tables), - span.stable(&mut *tables), - ) - }) - .collect(), - } - } - - /// Get information about the local crate. - pub fn local_crate(&self) -> stable_mir::Crate { - let tables = self.0.borrow(); - smir_crate(tables.tcx, LOCAL_CRATE) - } - - /// Retrieve a list of all external crates. - pub fn external_crates(&self) -> Vec<stable_mir::Crate> { - let tables = self.0.borrow(); - tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect() - } - - /// Find a crate with the given name. - pub fn find_crates(&self, name: &str) -> Vec<stable_mir::Crate> { - let tables = self.0.borrow(); - let crates: Vec<stable_mir::Crate> = [LOCAL_CRATE] - .iter() - .chain(tables.tcx.crates(()).iter()) - .filter_map(|crate_num| { - let crate_name = tables.tcx.crate_name(*crate_num).to_string(); - (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num)) - }) - .collect(); - crates - } - - /// Returns the name of given `DefId`. - pub fn def_name(&self, def_id: stable_mir::DefId, trimmed: bool) -> Symbol { - let tables = self.0.borrow(); - if trimmed { - with_forced_trimmed_paths!(tables.tcx.def_path_str(tables[def_id])) - } else { - with_no_trimmed_paths!(tables.tcx.def_path_str(tables[def_id])) - } - } - - /// 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: stable_mir::DefId, - attr: &[stable_mir::Symbol], - ) -> Vec<stable_mir::crate_def::Attribute> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let did = tables[def_id]; - let attr_name: Vec<_> = attr.iter().map(|seg| rustc_span::Symbol::intern(&seg)).collect(); - tcx.get_attrs_by_path(did, &attr_name) - .filter_map(|attribute| { - if let Attribute::Unparsed(u) = attribute { - let attr_str = rustc_hir_pretty::attribute_to_string(&tcx, attribute); - Some(stable_mir::crate_def::Attribute::new( - attr_str, - u.span.stable(&mut *tables), - )) - } else { - None - } - }) - .collect() - } - - /// Get all tool attributes of a definition. - pub fn all_tool_attrs( - &self, - def_id: stable_mir::DefId, - ) -> Vec<stable_mir::crate_def::Attribute> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let did = tables[def_id]; - let attrs_iter = if let Some(did) = did.as_local() { - tcx.hir_attrs(tcx.local_def_id_to_hir_id(did)).iter() - } else { - 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(&tcx, attribute); - Some(stable_mir::crate_def::Attribute::new( - attr_str, - u.span.stable(&mut *tables), - )) - } else { - None - } - }) - .collect() - } - - /// Returns printable, human readable form of `Span`. - pub fn span_to_string(&self, span: stable_mir::ty::Span) -> String { - let tables = self.0.borrow(); - tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span]) - } - - /// Return filename from given `Span`, for diagnostic purposes. - pub fn get_filename(&self, span: &Span) -> Filename { - let tables = self.0.borrow(); - tables - .tcx - .sess - .source_map() - .span_to_filename(tables[*span]) - .display(rustc_span::FileNameDisplayPreference::Local) - .to_string() - } - - /// Return lines corresponding to this `Span`. - pub fn get_lines(&self, span: &Span) -> LineInfo { - let tables = self.0.borrow(); - let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]); - LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 } - } - - /// Returns the `kind` of given `DefId`. - pub fn item_kind(&self, item: CrateItem) -> ItemKind { - let tables = self.0.borrow(); - new_item_kind(tables.tcx.def_kind(tables[item.0])) - } - - /// Returns whether this is a foreign item. - pub fn is_foreign_item(&self, item: DefId) -> bool { - let tables = self.0.borrow(); - tables.tcx.is_foreign_item(tables[item]) - } - - /// Returns the kind of a given foreign item. - pub fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind { - let mut tables = self.0.borrow_mut(); - let def_id = tables[def.def_id()]; - let tcx = tables.tcx; - use rustc_hir::def::DefKind; - match tcx.def_kind(def_id) { - DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)), - DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)), - DefKind::ForeignTy => ForeignItemKind::Type( - tables.intern_ty(rustc_middle::ty::Ty::new_foreign(tcx, def_id)), - ), - def_kind => unreachable!("Unexpected kind for a foreign item: {:?}", def_kind), - } - } - - /// Returns the kind of a given algebraic data type. - pub fn adt_kind(&self, def: AdtDef) -> AdtKind { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - def.internal(&mut *tables, tcx).adt_kind().stable(&mut *tables) - } - - /// Returns if the ADT is a box. - pub fn adt_is_box(&self, def: AdtDef) -> bool { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - def.internal(&mut *tables, tcx).is_box() - } - - /// Returns whether this ADT is simd. - pub fn adt_is_simd(&self, def: AdtDef) -> bool { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - def.internal(&mut *tables, tcx).repr().simd() - } - - /// Returns whether this definition is a C string. - pub fn adt_is_cstr(&self, def: AdtDef) -> bool { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.0.internal(&mut *tables, tcx); - tables.tcx.is_lang_item(def_id, LangItem::CStr) - } - - /// Returns the representation options for this ADT - pub fn adt_repr(&self, def: AdtDef) -> ReprOptions { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - def.internal(&mut *tables, tcx).repr().stable(&mut *tables) - } - - /// Retrieve the function signature for the given generic arguments. - pub fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.0.internal(&mut *tables, tcx); - let sig = - tables.tcx.fn_sig(def_id).instantiate(tables.tcx, args.internal(&mut *tables, tcx)); - sig.stable(&mut *tables) - } - - /// Retrieve the intrinsic definition if the item corresponds one. - pub fn intrinsic(&self, def: DefId) -> Option<IntrinsicDef> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.internal(&mut *tables, tcx); - let intrinsic = tcx.intrinsic_raw(def_id); - intrinsic.map(|_| IntrinsicDef(def)) - } - - /// Retrieve the plain function name of an intrinsic. - pub fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.0.internal(&mut *tables, tcx); - tcx.intrinsic(def_id).unwrap().name.to_string() - } - - /// Retrieve the closure signature for the given generic arguments. - pub fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let args_ref = args.internal(&mut *tables, tcx); - let sig = args_ref.as_closure().sig(); - sig.stable(&mut *tables) - } - - /// The number of variants in this ADT. - pub fn adt_variants_len(&self, def: AdtDef) -> usize { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - def.internal(&mut *tables, tcx).variants().len() - } - - /// Discriminant for a given variant index of AdtDef - pub fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let adt = adt.internal(&mut *tables, tcx); - let variant = variant.internal(&mut *tables, tcx); - adt.discriminant_for_variant(tcx, variant).stable(&mut *tables) - } - - /// Discriminant for a given variand index and args of a coroutine - pub fn coroutine_discr_for_variant( - &self, - coroutine: CoroutineDef, - args: &GenericArgs, - variant: VariantIdx, - ) -> Discr { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let coroutine = coroutine.def_id().internal(&mut *tables, tcx); - let args = args.internal(&mut *tables, tcx); - let variant = variant.internal(&mut *tables, tcx); - args.as_coroutine().discriminant_for_variant(coroutine, tcx, variant).stable(&mut *tables) - } - - /// The name of a variant. - pub fn variant_name(&self, def: VariantDef) -> Symbol { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - def.internal(&mut *tables, tcx).name.to_string() - } - - pub fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect() - } - - /// Evaluate constant as a target usize. - pub fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let mir_const = cnst.internal(&mut *tables, tcx); - mir_const - .try_eval_target_usize(tables.tcx, ty::TypingEnv::fully_monomorphized()) - .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) - } - pub fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let mir_const = cnst.internal(&mut *tables, tcx); - mir_const - .try_to_target_usize(tables.tcx) - .ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64"))) - } - - /// Create a new zero-sized constant. - pub fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let ty_internal = ty.internal(&mut *tables, tcx); - let size = tables - .tcx - .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty_internal)) - .map_err(|err| { - Error::new(format!( - "Cannot create a zero-sized constant for type `{ty_internal}`: {err}" - )) - })? - .size; - if size.bytes() != 0 { - return Err(Error::new(format!( - "Cannot create a zero-sized constant for type `{ty_internal}`: \ - Type `{ty_internal}` has {} bytes", - size.bytes() - ))); - } - - Ok(mir::Const::Ty(ty_internal, ty::Const::zero_sized(tables.tcx, ty_internal)) - .stable(&mut *tables)) - } - - /// Create a new constant that represents the given string value. - pub fn new_const_str(&self, value: &str) -> MirConst { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let ty = ty::Ty::new_static_str(tcx); - let bytes = value.as_bytes(); - let valtree = ty::ValTree::from_raw_bytes(tcx, bytes); - let cv = ty::Value { ty, valtree }; - let val = tcx.valtree_to_const_val(cv); - mir::Const::from_value(val, ty).stable(&mut tables) - } - - /// Create a new constant that represents the given boolean value. - pub fn new_const_bool(&self, value: bool) -> MirConst { - let mut tables = self.0.borrow_mut(); - mir::Const::from_bool(tables.tcx, value).stable(&mut tables) - } - - /// Create a new constant that represents the given value. - pub fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); - let size = tables - .tcx - .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) - .unwrap() - .size; - let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { - Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`.")) - })?; - Ok(mir::Const::from_scalar(tcx, mir::interpret::Scalar::Int(scalar), ty) - .stable(&mut tables)) - } - pub fn try_new_ty_const_uint( - &self, - value: u128, - uint_ty: UintTy, - ) -> Result<stable_mir::ty::TyConst, Error> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let ty = ty::Ty::new_uint(tcx, uint_ty.internal(&mut *tables, tcx)); - let size = tables - .tcx - .layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) - .unwrap() - .size; - - // We don't use Const::from_bits since it doesn't have any error checking. - let scalar = ScalarInt::try_from_uint(value, size).ok_or_else(|| { - Error::new(format!("Value overflow: cannot convert `{value}` to `{ty}`.")) - })?; - Ok(ty::Const::new_value(tcx, ValTree::from_scalar_int(tcx, scalar), ty) - .stable(&mut *tables)) - } - - /// Create a new type from the given kind. - pub fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let internal_kind = kind.internal(&mut *tables, tcx); - tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables) - } - - /// Create a new box type, `Box<T>`, for the given inner type `T`. - pub fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let inner = ty.internal(&mut *tables, tcx); - ty::Ty::new_box(tables.tcx, inner).stable(&mut *tables) - } - - /// Returns the type of given crate item. - pub fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - tcx.type_of(item.internal(&mut *tables, tcx)).instantiate_identity().stable(&mut *tables) - } - - /// Returns the type of given definition instantiated with the given arguments. - pub fn def_ty_with_args( - &self, - item: stable_mir::DefId, - args: &GenericArgs, - ) -> stable_mir::ty::Ty { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let args = args.internal(&mut *tables, tcx); - let def_ty = tables.tcx.type_of(item.internal(&mut *tables, tcx)); - tables - .tcx - .instantiate_and_normalize_erasing_regions( - args, - ty::TypingEnv::fully_monomorphized(), - def_ty, - ) - .stable(&mut *tables) - } - - /// Returns literal value of a const as a string. - pub fn mir_const_pretty(&self, cnst: &stable_mir::ty::MirConst) -> String { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - cnst.internal(&mut *tables, tcx).to_string() - } - - /// `Span` of an item. - pub fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span { - let mut tables = self.0.borrow_mut(); - tables.tcx.def_span(tables[def_id]).stable(&mut *tables) - } - - /// Obtain the representation of a type. - pub fn ty_pretty(&self, ty: stable_mir::ty::Ty) -> String { - let tables = self.0.borrow_mut(); - tables.types[ty].to_string() - } - - /// Obtain the representation of a type. - pub fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind { - let mut tables = self.0.borrow_mut(); - tables.types[ty].kind().stable(&mut *tables) - } - - pub fn ty_const_pretty(&self, ct: stable_mir::ty::TyConstId) -> String { - let tables = self.0.borrow_mut(); - tables.ty_consts[ct].to_string() - } - - /// Get the discriminant Ty for this Ty if there's one. - pub fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let internal_kind = ty.internal(&mut *tables, tcx); - let internal_ty = tables.tcx.mk_ty_from_kind(internal_kind); - internal_ty.discriminant_ty(tables.tcx).stable(&mut *tables) - } - - /// Get the body of an Instance which is already monomorphized. - pub fn instance_body(&self, def: InstanceDef) -> Option<Body> { - let mut tables = self.0.borrow_mut(); - let instance = tables.instances[def]; - tables - .instance_has_body(instance) - .then(|| BodyBuilder::new(tables.tcx, instance).build(&mut *tables)) - } - - /// Get the instance type with generic instantiations applied and lifetimes erased. - pub fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty { - let mut tables = self.0.borrow_mut(); - let instance = tables.instances[def]; - assert!(!instance.has_non_region_param(), "{instance:?} needs further instantiation"); - instance.ty(tables.tcx, ty::TypingEnv::fully_monomorphized()).stable(&mut *tables) - } - - /// Get the instantiation types. - pub fn instance_args(&self, def: InstanceDef) -> GenericArgs { - let mut tables = self.0.borrow_mut(); - let instance = tables.instances[def]; - instance.args.stable(&mut *tables) - } - - /// Get an instance ABI. - pub fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> { - let mut tables = self.0.borrow_mut(); - let instance = tables.instances[def]; - Ok(tables.fn_abi_of_instance(instance, List::empty())?.stable(&mut *tables)) - } - - /// Get the ABI of a function pointer. - pub fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let sig = fn_ptr.internal(&mut *tables, tcx); - Ok(tables.fn_abi_of_fn_ptr(sig, List::empty())?.stable(&mut *tables)) - } - - /// Get the instance. - pub fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId { - let mut tables = self.0.borrow_mut(); - let def_id = tables.instances[def].def_id(); - tables.create_def_id(def_id) - } - - /// Get the instance mangled name. - pub fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol { - let tables = self.0.borrow_mut(); - let instance = tables.instances[instance]; - tables.tcx.symbol_name(instance).name.to_string() - } - - /// Check if this is an empty DropGlue shim. - pub fn is_empty_drop_shim(&self, def: InstanceDef) -> bool { - let tables = self.0.borrow_mut(); - let instance = tables.instances[def]; - 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: stable_mir::DefId) -> stable_mir::mir::mono::Instance { - let mut tables = self.0.borrow_mut(); - let def_id = tables[def_id]; - Instance::mono(tables.tcx, def_id).stable(&mut *tables) - } - - /// Item requires monomorphization. - pub fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool { - let tables = self.0.borrow(); - let def_id = tables[def_id]; - let generics = tables.tcx.generics_of(def_id); - let result = generics.requires_monomorphization(tables.tcx); - result - } - - /// Resolve an instance from the given function definition and generic arguments. - pub fn resolve_instance( - &self, - def: stable_mir::ty::FnDef, - args: &stable_mir::ty::GenericArgs, - ) -> Option<stable_mir::mir::mono::Instance> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.0.internal(&mut *tables, tcx); - let args_ref = args.internal(&mut *tables, tcx); - match Instance::try_resolve( - tables.tcx, - ty::TypingEnv::fully_monomorphized(), - def_id, - args_ref, - ) { - Ok(Some(instance)) => Some(instance.stable(&mut *tables)), - Ok(None) | Err(_) => None, - } - } - - /// Resolve an instance for drop_in_place for the given type. - pub fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let internal_ty = ty.internal(&mut *tables, tcx); - let instance = Instance::resolve_drop_in_place(tables.tcx, internal_ty); - instance.stable(&mut *tables) - } - - /// Resolve instance for a function pointer. - pub fn resolve_for_fn_ptr( - &self, - def: FnDef, - args: &GenericArgs, - ) -> Option<stable_mir::mir::mono::Instance> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.0.internal(&mut *tables, tcx); - let args_ref = args.internal(&mut *tables, tcx); - Instance::resolve_for_fn_ptr( - tables.tcx, - ty::TypingEnv::fully_monomorphized(), - def_id, - args_ref, - ) - .stable(&mut *tables) - } - - /// Resolve instance for a closure with the requested type. - pub fn resolve_closure( - &self, - def: ClosureDef, - args: &GenericArgs, - kind: ClosureKind, - ) -> Option<stable_mir::mir::mono::Instance> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.0.internal(&mut *tables, tcx); - let args_ref = args.internal(&mut *tables, tcx); - let closure_kind = kind.internal(&mut *tables, tcx); - Some( - Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind) - .stable(&mut *tables), - ) - } - - /// Try to evaluate an instance into a constant. - pub fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> { - let mut tables = self.0.borrow_mut(); - let instance = tables.instances[def]; - let tcx = tables.tcx; - let result = tcx.const_eval_instance( - ty::TypingEnv::fully_monomorphized(), - instance, - tcx.def_span(instance.def_id()), - ); - result - .map(|const_val| { - alloc::try_new_allocation( - const_ty.internal(&mut *tables, tcx), - const_val, - &mut *tables, - ) - }) - .map_err(|e| e.stable(&mut *tables))? - } - - /// Evaluate a static's initializer. - pub fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = def.0.internal(&mut *tables, tcx); - tables.tcx.eval_static_initializer(def_id).stable(&mut *tables) - } - - /// Retrieve global allocation for the given allocation ID. - pub fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let alloc_id = alloc.internal(&mut *tables, tcx); - tables.tcx.global_alloc(alloc_id).stable(&mut *tables) - } - - /// Retrieve the id for the virtual table. - pub fn vtable_allocation( - &self, - global_alloc: &GlobalAlloc, - ) -> Option<stable_mir::mir::alloc::AllocId> { - let mut tables = self.0.borrow_mut(); - let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { - return None; - }; - let tcx = tables.tcx; - let alloc_id = tables.tcx.vtable_allocation(( - ty.internal(&mut *tables, tcx), - trait_ref - .internal(&mut *tables, tcx) - .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)), - )); - Some(alloc_id.stable(&mut *tables)) - } - - pub fn krate(&self, def_id: stable_mir::DefId) -> Crate { - let tables = self.0.borrow(); - smir_crate(tables.tcx, tables[def_id].krate) - } - - /// Retrieve the instance name for diagnostic messages. - /// - /// This will return the specialized name, e.g., `Vec<char>::new`. - pub fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol { - let tables = self.0.borrow_mut(); - let instance = tables.instances[def]; - if trimmed { - with_forced_trimmed_paths!( - tables.tcx.def_path_str_with_args(instance.def_id(), instance.args) - ) - } else { - with_no_trimmed_paths!( - tables.tcx.def_path_str_with_args(instance.def_id(), instance.args) - ) - } - } - - /// Get the layout of a type. - pub fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let ty = ty.internal(&mut *tables, tcx); - let layout = tables.layout_of(ty)?.layout; - Ok(layout.stable(&mut *tables)) - } - - /// Get the layout shape. - pub fn layout_shape(&self, id: Layout) -> LayoutShape { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - id.internal(&mut *tables, tcx).0.stable(&mut *tables) - } - - /// Get a debug string representation of a place. - pub fn place_pretty(&self, place: &Place) -> String { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - format!("{:?}", place.internal(&mut *tables, tcx)) - } - - /// Get the resulting type of binary operation. - pub fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let rhs_internal = rhs.internal(&mut *tables, tcx); - let lhs_internal = lhs.internal(&mut *tables, tcx); - let ty = bin_op.internal(&mut *tables, tcx).ty(tcx, rhs_internal, lhs_internal); - ty.stable(&mut *tables) - } - - /// Get the resulting type of unary operation. - pub fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let arg_internal = arg.internal(&mut *tables, tcx); - let ty = un_op.internal(&mut *tables, tcx).ty(tcx, arg_internal); - ty.stable(&mut *tables) - } - - /// Get all associated items of a definition. - pub fn associated_items(&self, def_id: stable_mir::DefId) -> stable_mir::AssocItems { - let mut tables = self.0.borrow_mut(); - let tcx = tables.tcx; - let def_id = tables[def_id]; - let assoc_items = if tcx.is_trait_alias(def_id) { - Vec::new() - } else { - tcx.associated_item_def_ids(def_id) - .iter() - .map(|did| tcx.associated_item(*did).stable(&mut *tables)) - .collect() - }; - assoc_items - } -} - -/// Implement error handling for extracting function ABI information. -impl<'tcx> FnAbiOfHelpers<'tcx> for Tables<'tcx> { - type FnAbiOfResult = Result<&'tcx rustc_target::callconv::FnAbi<'tcx, ty::Ty<'tcx>>, Error>; - - #[inline] - fn handle_fn_abi_err( - &self, - err: ty::layout::FnAbiError<'tcx>, - _span: rustc_span::Span, - fn_abi_request: ty::layout::FnAbiRequest<'tcx>, - ) -> Error { - Error::new(format!("Failed to get ABI for `{fn_abi_request:?}`: {err:?}")) - } -} - -impl<'tcx> LayoutOfHelpers<'tcx> for Tables<'tcx> { - type LayoutOfResult = Result<ty::layout::TyAndLayout<'tcx>, Error>; - - #[inline] - fn handle_layout_err( - &self, - err: ty::layout::LayoutError<'tcx>, - _span: rustc_span::Span, - ty: ty::Ty<'tcx>, - ) -> Error { - Error::new(format!("Failed to get layout for `{ty}`: {err}")) - } -} - -impl<'tcx> HasTypingEnv<'tcx> for Tables<'tcx> { - fn typing_env(&self) -> ty::TypingEnv<'tcx> { - ty::TypingEnv::fully_monomorphized() - } -} - -impl<'tcx> HasTyCtxt<'tcx> for Tables<'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } -} - -impl<'tcx> HasDataLayout for Tables<'tcx> { - fn data_layout(&self) -> &rustc_abi::TargetDataLayout { - self.tcx.data_layout() - } -} diff --git a/compiler/rustc_smir/src/rustc_smir/context/impls.rs b/compiler/rustc_smir/src/rustc_smir/context/impls.rs new file mode 100644 index 00000000000..89ae47143ef --- /dev/null +++ b/compiler/rustc_smir/src/rustc_smir/context/impls.rs @@ -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 + } +} diff --git a/compiler/rustc_smir/src/rustc_smir/context/mod.rs b/compiler/rustc_smir/src/rustc_smir/context/mod.rs new file mode 100644 index 00000000000..38743e5f7d3 --- /dev/null +++ b/compiler/rustc_smir/src/rustc_smir/context/mod.rs @@ -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() + } +} diff --git a/compiler/rustc_smir/src/rustc_smir/context/traits.rs b/compiler/rustc_smir/src/rustc_smir/context/traits.rs new file mode 100644 index 00000000000..19e09016cdd --- /dev/null +++ b/compiler/rustc_smir/src/rustc_smir/context/traits.rs @@ -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; +} diff --git a/compiler/rustc_smir/src/rustc_smir/convert/error.rs b/compiler/rustc_smir/src/rustc_smir/convert/error.rs deleted file mode 100644 index 2cde5542483..00000000000 --- a/compiler/rustc_smir/src/rustc_smir/convert/error.rs +++ /dev/null @@ -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:?}")) - } -} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 26de9b0a496..e8b7a3fec09 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,229 +7,280 @@ //! //! 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>>, +} + +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> Tables<'tcx> { - pub(crate) fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty { +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(..) - ) - } - - /// 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 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_def_id(&mut self, did: DefId) -> B::DefId { + self.def_ids.create_or_fetch(did) } - 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 create_alloc_id(&mut self, aid: AllocId) -> B::AllocId { + self.alloc_ids.create_or_fetch(aid) } -} -/// Iterate over the definitions of the given crate. -pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T> -where - F: FnMut(DefId) -> Option<T>, -{ - if krate == LOCAL_CRATE { - tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect() - } else { - let num_definitions = tcx.num_extern_def_ids(krate); - (0..num_definitions) - .filter_map(move |i| { - let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) }; - func(def_id) - }) - .collect() + pub fn create_span(&mut self, span: Span) -> B::Span { + self.spans.create_or_fetch(span) } -} -/// 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 fn instance_def(&mut self, instance: ty::Instance<'tcx>) -> B::InstanceDef { + self.instances.create_or_fetch(instance) + } -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), + pub fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> B::Layout { + self.layouts.create_or_fetch(layout) } -} -/// 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; -} + pub fn crate_item(&mut self, did: rustc_span::def_id::DefId) -> B::CrateItem { + B::CrateItem::new(self.create_def_id(did)) + } -impl<'tcx, T> Stable<'tcx> for &T -where - T: Stable<'tcx>, -{ - type T = T::T; + pub fn adt_def(&mut self, did: rustc_span::def_id::DefId) -> B::AdtDef { + B::AdtDef::new(self.create_def_id(did)) + } - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - (*self).stable(tables) + pub fn foreign_module_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignModuleDef { + B::ForeignModuleDef::new(self.create_def_id(did)) } -} -impl<'tcx, T> Stable<'tcx> for Option<T> -where - T: Stable<'tcx>, -{ - type T = Option<T::T>; + 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)) + } - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - self.as_ref().map(|value| value.stable(tables)) + 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)) } } -impl<'tcx, T, E> Stable<'tcx> for Result<T, E> -where - T: Stable<'tcx>, - E: Stable<'tcx>, -{ - type T = Result<T::T, E::T>; +/// 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; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - match self { - Ok(val) => Ok(val.stable(tables)), - Err(error) => Err(error.stable(tables)), - } + 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<'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<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<'tcx, T, U> Stable<'tcx> for (T, U) -where - T: Stable<'tcx>, - U: Stable<'tcx>, +impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V> + for IndexMap<K, V> { - type T = (T::T, U::T); - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - (self.0.stable(tables), self.1.stable(tables)) + 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 } } -impl<'tcx, T> Stable<'tcx> for RangeInclusive<T> +/// Iterate over the definitions of the given crate. +pub(crate) fn filter_def_ids<F, T>(tcx: TyCtxt<'_>, krate: CrateNum, mut func: F) -> Vec<T> where - T: Stable<'tcx>, + F: FnMut(DefId) -> Option<T>, { - type T = RangeInclusive<T::T>; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - RangeInclusive::new(self.start().stable(tables), self.end().stable(tables)) + if krate == LOCAL_CRATE { + tcx.iter_local_def_id().filter_map(|did| func(did.to_def_id())).collect() + } else { + let num_definitions = tcx.num_extern_def_ids(krate); + (0..num_definitions) + .filter_map(move |i| { + let def_id = DefId { krate, index: rustc_span::def_id::DefIndex::from_usize(i) }; + func(def_id) + }) + .collect() } } diff --git a/compiler/rustc_smir/src/stable_mir/abi.rs b/compiler/rustc_smir/src/stable_mir/abi.rs index d8a2b97662c..369d08e444e 100644 --- a/compiler/rustc_smir/src/stable_mir/abi.rs +++ b/compiler/rustc_smir/src/stable_mir/abi.rs @@ -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) } diff --git a/compiler/rustc_smir/src/stable_mir/alloc.rs b/compiler/rustc_smir/src/stable_mir/alloc.rs new file mode 100644 index 00000000000..120cb4404b9 --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/alloc.rs @@ -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) +} diff --git a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs index 2668fba9f4f..a19968d2ab7 100644 --- a/compiler/rustc_smir/src/stable_mir/compiler_interface.rs +++ b/compiler/rustc_smir/src/stable_mir/compiler_interface.rs @@ -5,133 +5,488 @@ use std::cell::Cell; +use rustc_hir::def::DefKind; use rustc_smir::context::SmirCtxt; +use rustc_smir::{Bridge, SmirContainer}; use stable_mir::abi::{FnAbi, Layout, LayoutShape, ReprOptions}; use stable_mir::crate_def::Attribute; use stable_mir::mir::alloc::{AllocId, GlobalAlloc}; use stable_mir::mir::mono::{Instance, InstanceDef, StaticDef}; use stable_mir::mir::{BinOp, Body, Place, UnOp}; -use stable_mir::target::MachineInfo; +use stable_mir::target::{MachineInfo, MachineSize}; use stable_mir::ty::{ AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, CoroutineDef, Discr, FieldDef, FnDef, ForeignDef, ForeignItemKind, ForeignModule, ForeignModuleDef, GenericArgs, GenericPredicates, Generics, ImplDef, ImplTrait, IntrinsicDef, LineInfo, MirConst, PolyFnSig, RigidTy, Span, TraitDecl, TraitDef, Ty, TyConst, TyConstId, TyKind, UintTy, VariantDef, VariantIdx, }; +use stable_mir::unstable::{RustcInternal, Stable, new_item_kind}; use stable_mir::{ - AssocItems, Crate, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, ImplTraitDecls, - ItemKind, Symbol, TraitDecls, mir, + AssocItems, Crate, CrateDef, CrateItem, CrateItems, CrateNum, DefId, Error, Filename, + ImplTraitDecls, ItemKind, Symbol, TraitDecls, alloc, mir, }; +use tracing::debug; use crate::{rustc_smir, stable_mir}; +pub struct BridgeTys; + +impl Bridge for BridgeTys { + type DefId = stable_mir::DefId; + type AllocId = stable_mir::mir::alloc::AllocId; + type Span = stable_mir::ty::Span; + type Ty = stable_mir::ty::Ty; + type InstanceDef = stable_mir::mir::mono::InstanceDef; + type TyConstId = stable_mir::ty::TyConstId; + type MirConstId = stable_mir::ty::MirConstId; + type Layout = stable_mir::abi::Layout; + + type Error = stable_mir::Error; + type CrateItem = stable_mir::CrateItem; + type AdtDef = stable_mir::ty::AdtDef; + type ForeignModuleDef = stable_mir::ty::ForeignModuleDef; + type ForeignDef = stable_mir::ty::ForeignDef; + type FnDef = stable_mir::ty::FnDef; + type ClosureDef = stable_mir::ty::ClosureDef; + type CoroutineDef = stable_mir::ty::CoroutineDef; + type CoroutineClosureDef = stable_mir::ty::CoroutineClosureDef; + type AliasDef = stable_mir::ty::AliasDef; + type ParamDef = stable_mir::ty::ParamDef; + type BrNamedDef = stable_mir::ty::BrNamedDef; + type TraitDef = stable_mir::ty::TraitDef; + type GenericDef = stable_mir::ty::GenericDef; + type ConstDef = stable_mir::ty::ConstDef; + type ImplDef = stable_mir::ty::ImplDef; + type RegionDef = stable_mir::ty::RegionDef; + type CoroutineWitnessDef = stable_mir::ty::CoroutineWitnessDef; + type AssocDef = stable_mir::ty::AssocDef; + type OpaqueDef = stable_mir::ty::OpaqueDef; + type Prov = stable_mir::ty::Prov; + type StaticDef = stable_mir::mir::mono::StaticDef; + + type Allocation = stable_mir::ty::Allocation; +} + /// Stable public API for querying compiler information. /// -/// All queries are delegated to an internal [`SmirCtxt`] that provides +/// All queries are delegated to [`crate::rustc_smir::context::SmirCtxt`] that provides /// similar APIs but based on internal rustc constructs. /// /// Do not use this directly. This is currently used in the macro expansion. -pub(crate) struct SmirInterface<'tcx> { - pub(crate) cx: SmirCtxt<'tcx>, +pub(crate) trait SmirInterface { + fn entry_fn(&self) -> Option<CrateItem>; + /// Retrieve all items of the local crate that have a MIR associated with them. + fn all_local_items(&self) -> CrateItems; + /// Retrieve the body of a function. + /// This function will panic if the body is not available. + fn mir_body(&self, item: DefId) -> mir::Body; + /// Check whether the body of a function is available. + fn has_body(&self, item: DefId) -> bool; + fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef>; + + /// Retrieve all functions defined in this crate. + fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef>; + + /// Retrieve all static items defined in this crate. + fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef>; + fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule; + fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef>; + fn all_trait_decls(&self) -> TraitDecls; + fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls; + fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; + fn all_trait_impls(&self) -> ImplTraitDecls; + fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls; + fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait; + fn generics_of(&self, def_id: DefId) -> Generics; + fn predicates_of(&self, def_id: DefId) -> GenericPredicates; + fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates; + + /// Get information about the local crate. + fn local_crate(&self) -> Crate; + /// Retrieve a list of all external crates. + fn external_crates(&self) -> Vec<Crate>; + + /// Find a crate with the given name. + fn find_crates(&self, name: &str) -> Vec<Crate>; + + /// Returns the name of given `DefId` + fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol; + + /// 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()]`. + fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute>; + + /// Get all tool attributes of a definition. + fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute>; + + /// Returns printable, human readable form of `Span` + fn span_to_string(&self, span: Span) -> String; + + /// Return filename from given `Span`, for diagnostic purposes + fn get_filename(&self, span: &Span) -> Filename; + + /// Return lines corresponding to this `Span` + fn get_lines(&self, span: &Span) -> LineInfo; + + /// Returns the `kind` of given `DefId` + fn item_kind(&self, item: CrateItem) -> ItemKind; + + /// Returns whether this is a foreign item. + fn is_foreign_item(&self, item: DefId) -> bool; + + /// Returns the kind of a given foreign item. + fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind; + + /// Returns the kind of a given algebraic data type + fn adt_kind(&self, def: AdtDef) -> AdtKind; + + /// Returns if the ADT is a box. + fn adt_is_box(&self, def: AdtDef) -> bool; + + /// Returns whether this ADT is simd. + fn adt_is_simd(&self, def: AdtDef) -> bool; + + /// Returns whether this definition is a C string. + fn adt_is_cstr(&self, def: AdtDef) -> bool; + + /// Returns the representation options for this ADT. + fn adt_repr(&self, def: AdtDef) -> ReprOptions; + + /// Retrieve the function signature for the given generic arguments. + fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig; + + /// Retrieve the intrinsic definition if the item corresponds one. + fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef>; + + /// Retrieve the plain function name of an intrinsic. + fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol; + + /// Retrieve the closure signature for the given generic arguments. + fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig; + + /// The number of variants in this ADT. + fn adt_variants_len(&self, def: AdtDef) -> usize; + + /// Discriminant for a given variant index of AdtDef. + fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr; + + /// Discriminant for a given variand index and args of a coroutine. + fn coroutine_discr_for_variant( + &self, + coroutine: CoroutineDef, + args: &GenericArgs, + variant: VariantIdx, + ) -> Discr; + + /// The name of a variant. + fn variant_name(&self, def: VariantDef) -> Symbol; + fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef>; + + /// Evaluate constant as a target usize. + fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error>; + fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error>; + + /// Create a new zero-sized constant. + fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error>; + + /// Create a new constant that represents the given string value. + fn new_const_str(&self, value: &str) -> MirConst; + + /// Create a new constant that represents the given boolean value. + fn new_const_bool(&self, value: bool) -> MirConst; + + /// Create a new constant that represents the given value. + fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error>; + fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<TyConst, Error>; + + /// Create a new type from the given kind. + fn new_rigid_ty(&self, kind: RigidTy) -> Ty; + + /// Create a new box type, `Box<T>`, for the given inner type `T`. + fn new_box_ty(&self, ty: Ty) -> Ty; + + /// Returns the type of given crate item. + fn def_ty(&self, item: DefId) -> Ty; + + /// Returns the type of given definition instantiated with the given arguments. + fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty; + + /// Returns literal value of a const as a string. + fn mir_const_pretty(&self, cnst: &MirConst) -> String; + + /// `Span` of an item + fn span_of_an_item(&self, def_id: DefId) -> Span; + + fn ty_const_pretty(&self, ct: TyConstId) -> String; + + /// Obtain the representation of a type. + fn ty_pretty(&self, ty: Ty) -> String; + + /// Obtain the kind of a type. + fn ty_kind(&self, ty: Ty) -> TyKind; + + // Get the discriminant Ty for this Ty if there's one. + fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty; + + /// Get the body of an Instance which is already monomorphized. + fn instance_body(&self, instance: InstanceDef) -> Option<Body>; + + /// Get the instance type with generic instantiations applied and lifetimes erased. + fn instance_ty(&self, instance: InstanceDef) -> Ty; + + /// Get the instantiation types. + fn instance_args(&self, def: InstanceDef) -> GenericArgs; + + /// Get the instance. + fn instance_def_id(&self, instance: InstanceDef) -> DefId; + + /// Get the instance mangled name. + fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol; + + /// Check if this is an empty DropGlue shim. + fn is_empty_drop_shim(&self, def: InstanceDef) -> bool; + + /// Convert a non-generic crate item into an instance. + /// This function will panic if the item is generic. + fn mono_instance(&self, def_id: DefId) -> Instance; + + /// Item requires monomorphization. + fn requires_monomorphization(&self, def_id: DefId) -> bool; + + /// Resolve an instance from the given function definition and generic arguments. + fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>; + + /// Resolve an instance for drop_in_place for the given type. + fn resolve_drop_in_place(&self, ty: Ty) -> Instance; + + /// Resolve instance for a function pointer. + fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance>; + + /// Resolve instance for a closure with the requested type. + fn resolve_closure( + &self, + def: ClosureDef, + args: &GenericArgs, + kind: ClosureKind, + ) -> Option<Instance>; + + /// Evaluate a static's initializer. + fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error>; + + /// Try to evaluate an instance into a constant. + fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error>; + + /// Retrieve global allocation for the given allocation ID. + fn global_alloc(&self, id: AllocId) -> GlobalAlloc; + + /// Retrieve the id for the virtual table. + fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId>; + fn krate(&self, def_id: DefId) -> Crate; + fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol; + + /// Return information about the target machine. + fn target_info(&self) -> MachineInfo; + + /// Get an instance ABI. + fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error>; + + /// Get the ABI of a function pointer. + fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error>; + + /// Get the layout of a type. + fn ty_layout(&self, ty: Ty) -> Result<Layout, Error>; + + /// Get the layout shape. + fn layout_shape(&self, id: Layout) -> LayoutShape; + + /// Get a debug string representation of a place. + fn place_pretty(&self, place: &Place) -> String; + + /// Get the resulting type of binary operation. + fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty; + + /// Get the resulting type of unary operation. + fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty; + + /// Get all associated items of a definition. + fn associated_items(&self, def_id: DefId) -> AssocItems; } -impl<'tcx> SmirInterface<'tcx> { - pub(crate) fn entry_fn(&self) -> Option<CrateItem> { - self.cx.entry_fn() +impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> { + fn entry_fn(&self) -> Option<CrateItem> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = cx.entry_fn(); + Some(tables.crate_item(did?)) } /// Retrieve all items of the local crate that have a MIR associated with them. - pub(crate) fn all_local_items(&self) -> CrateItems { - self.cx.all_local_items() + fn all_local_items(&self) -> CrateItems { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.all_local_items().iter().map(|did| tables.crate_item(*did)).collect() } /// Retrieve the body of a function. /// This function will panic if the body is not available. - pub(crate) fn mir_body(&self, item: DefId) -> mir::Body { - self.cx.mir_body(item) + fn mir_body(&self, item: DefId) -> mir::Body { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[item]; + cx.mir_body(did).stable(&mut *tables, cx) } /// Check whether the body of a function is available. - pub(crate) fn has_body(&self, item: DefId) -> bool { - self.cx.has_body(item) + fn has_body(&self, item: DefId) -> bool { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def = item.internal(&mut *tables, cx.tcx); + cx.has_body(def) } - pub(crate) fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef> { - self.cx.foreign_modules(crate_num) + fn foreign_modules(&self, crate_num: CrateNum) -> Vec<ForeignModuleDef> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.foreign_modules(crate_num.internal(&mut *tables, cx.tcx)) + .iter() + .map(|did| tables.foreign_module_def(*did)) + .collect() } /// Retrieve all functions defined in this crate. - pub(crate) fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> { - self.cx.crate_functions(crate_num) + fn crate_functions(&self, crate_num: CrateNum) -> Vec<FnDef> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let krate = crate_num.internal(&mut *tables, cx.tcx); + cx.crate_functions(krate).iter().map(|did| tables.fn_def(*did)).collect() } /// Retrieve all static items defined in this crate. - pub(crate) fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> { - self.cx.crate_statics(crate_num) + fn crate_statics(&self, crate_num: CrateNum) -> Vec<StaticDef> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let krate = crate_num.internal(&mut *tables, cx.tcx); + cx.crate_statics(krate).iter().map(|did| tables.static_def(*did)).collect() } - pub(crate) fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule { - self.cx.foreign_module(mod_def) + fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[mod_def.def_id()]; + cx.foreign_module(did).stable(&mut *tables, cx) } - pub(crate) fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef> { - self.cx.foreign_items(mod_def) + fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec<ForeignDef> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[mod_def.def_id()]; + cx.foreign_items(did).iter().map(|did| tables.foreign_def(*did)).collect() } - pub(crate) fn all_trait_decls(&self) -> TraitDecls { - self.cx.all_trait_decls() + fn all_trait_decls(&self) -> TraitDecls { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.all_trait_decls().map(|did| tables.trait_def(did)).collect() } - pub(crate) fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls { - self.cx.trait_decls(crate_num) + fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let krate = crate_num.internal(&mut *tables, cx.tcx); + cx.trait_decls(krate).iter().map(|did| tables.trait_def(*did)).collect() } - pub(crate) fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl { - self.cx.trait_decl(trait_def) + fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[trait_def.0]; + cx.trait_decl(did).stable(&mut *tables, cx) } - pub(crate) fn all_trait_impls(&self) -> ImplTraitDecls { - self.cx.all_trait_impls() + fn all_trait_impls(&self) -> ImplTraitDecls { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.all_trait_impls().iter().map(|did| tables.impl_def(*did)).collect() } - pub(crate) fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls { - self.cx.trait_impls(crate_num) + fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let krate = crate_num.internal(&mut *tables, cx.tcx); + cx.trait_impls(krate).iter().map(|did| tables.impl_def(*did)).collect() } - pub(crate) fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait { - self.cx.trait_impl(trait_impl) + fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[trait_impl.0]; + cx.trait_impl(did).stable(&mut *tables, cx) } - pub(crate) fn generics_of(&self, def_id: DefId) -> Generics { - self.cx.generics_of(def_id) + fn generics_of(&self, def_id: DefId) -> Generics { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.generics_of(did).stable(&mut *tables, cx) } - pub(crate) fn predicates_of(&self, def_id: DefId) -> GenericPredicates { - self.cx.predicates_of(def_id) + fn predicates_of(&self, def_id: DefId) -> GenericPredicates { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + let (parent, kinds) = cx.predicates_of(did); + stable_mir::ty::GenericPredicates { + parent: parent.map(|did| tables.trait_def(did)), + predicates: kinds + .iter() + .map(|(kind, span)| (kind.stable(&mut *tables, cx), span.stable(&mut *tables, cx))) + .collect(), + } } - pub(crate) fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates { - self.cx.explicit_predicates_of(def_id) + fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + let (parent, kinds) = cx.explicit_predicates_of(did); + stable_mir::ty::GenericPredicates { + parent: parent.map(|did| tables.trait_def(did)), + predicates: kinds + .iter() + .map(|(kind, span)| (kind.stable(&mut *tables, cx), span.stable(&mut *tables, cx))) + .collect(), + } } /// Get information about the local crate. - pub(crate) fn local_crate(&self) -> Crate { - self.cx.local_crate() + fn local_crate(&self) -> Crate { + let cx = &*self.cx.borrow(); + smir_crate(cx, cx.local_crate_num()) } /// Retrieve a list of all external crates. - pub(crate) fn external_crates(&self) -> Vec<Crate> { - self.cx.external_crates() + fn external_crates(&self) -> Vec<Crate> { + let cx = &*self.cx.borrow(); + cx.external_crates().iter().map(|crate_num| smir_crate(cx, *crate_num)).collect() } /// Find a crate with the given name. - pub(crate) fn find_crates(&self, name: &str) -> Vec<Crate> { - self.cx.find_crates(name) + fn find_crates(&self, name: &str) -> Vec<Crate> { + let cx = &*self.cx.borrow(); + cx.find_crates(name).iter().map(|crate_num| smir_crate(cx, *crate_num)).collect() } /// Returns the name of given `DefId`. - pub(crate) fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol { - self.cx.def_name(def_id, trimmed) + fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol { + let tables = self.tables.borrow(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.def_name(did, trimmed) } /// Return registered tool attributes with the given attribute name. @@ -141,364 +496,581 @@ impl<'tcx> SmirInterface<'tcx> { /// /// 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(crate) fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute> { - self.cx.tool_attrs(def_id, attr) + fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec<Attribute> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.tool_attrs(did, attr) + .into_iter() + .map(|(attr_str, span)| Attribute::new(attr_str, span.stable(&mut *tables, cx))) + .collect() } /// Get all tool attributes of a definition. - pub(crate) fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute> { - self.cx.all_tool_attrs(def_id) + fn all_tool_attrs(&self, def_id: DefId) -> Vec<Attribute> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.all_tool_attrs(did) + .into_iter() + .map(|(attr_str, span)| Attribute::new(attr_str, span.stable(&mut *tables, cx))) + .collect() } /// Returns printable, human readable form of `Span`. - pub(crate) fn span_to_string(&self, span: Span) -> String { - self.cx.span_to_string(span) + fn span_to_string(&self, span: Span) -> String { + let tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let sp = tables.spans[span]; + cx.span_to_string(sp) } /// Return filename from given `Span`, for diagnostic purposes. - pub(crate) fn get_filename(&self, span: &Span) -> Filename { - self.cx.get_filename(span) + fn get_filename(&self, span: &Span) -> Filename { + let tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let sp = tables.spans[*span]; + cx.get_filename(sp) } /// Return lines corresponding to this `Span`. - pub(crate) fn get_lines(&self, span: &Span) -> LineInfo { - self.cx.get_lines(span) + fn get_lines(&self, span: &Span) -> LineInfo { + let tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let sp = tables.spans[*span]; + let lines = cx.get_lines(sp); + LineInfo::from(lines) } /// Returns the `kind` of given `DefId`. - pub(crate) fn item_kind(&self, item: CrateItem) -> ItemKind { - self.cx.item_kind(item) + fn item_kind(&self, item: CrateItem) -> ItemKind { + let tables = self.tables.borrow(); + let cx = &*self.cx.borrow(); + let did = tables[item.0]; + new_item_kind(cx.def_kind(did)) } /// Returns whether this is a foreign item. - pub(crate) fn is_foreign_item(&self, item: DefId) -> bool { - self.cx.is_foreign_item(item) + fn is_foreign_item(&self, item: DefId) -> bool { + let tables = self.tables.borrow(); + let cx = &*self.cx.borrow(); + let did = tables[item]; + cx.is_foreign_item(did) } /// Returns the kind of a given foreign item. - pub(crate) fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind { - self.cx.foreign_item_kind(def) + fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = tables[def.def_id()]; + let def_kind = cx.foreign_item_kind(def_id); + match def_kind { + DefKind::Fn => ForeignItemKind::Fn(tables.fn_def(def_id)), + DefKind::Static { .. } => ForeignItemKind::Static(tables.static_def(def_id)), + DefKind::ForeignTy => { + use rustc_smir::context::SmirTy; + ForeignItemKind::Type(tables.intern_ty(cx.new_foreign(def_id))) + } + def_kind => unreachable!("Unexpected kind for a foreign item: {:?}", def_kind), + } } /// Returns the kind of a given algebraic data type. - pub(crate) fn adt_kind(&self, def: AdtDef) -> AdtKind { - self.cx.adt_kind(def) + fn adt_kind(&self, def: AdtDef) -> AdtKind { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.adt_kind(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx) } /// Returns if the ADT is a box. - pub(crate) fn adt_is_box(&self, def: AdtDef) -> bool { - self.cx.adt_is_box(def) + fn adt_is_box(&self, def: AdtDef) -> bool { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.adt_is_box(def.internal(&mut *tables, cx.tcx)) } /// Returns whether this ADT is simd. - pub(crate) fn adt_is_simd(&self, def: AdtDef) -> bool { - self.cx.adt_is_simd(def) + fn adt_is_simd(&self, def: AdtDef) -> bool { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.adt_is_simd(def.internal(&mut *tables, cx.tcx)) } /// Returns whether this definition is a C string. - pub(crate) fn adt_is_cstr(&self, def: AdtDef) -> bool { - self.cx.adt_is_cstr(def) + fn adt_is_cstr(&self, def: AdtDef) -> bool { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.adt_is_cstr(def.0.internal(&mut *tables, cx.tcx)) } /// Returns the representation options for this ADT - pub(crate) fn adt_repr(&self, def: AdtDef) -> ReprOptions { - self.cx.adt_repr(def) + fn adt_repr(&self, def: AdtDef) -> ReprOptions { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.adt_repr(def.internal(&mut *tables, cx.tcx)).stable(&mut *tables, cx) } /// Retrieve the function signature for the given generic arguments. - pub(crate) fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { - self.cx.fn_sig(def, args) + fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = def.0.internal(&mut *tables, cx.tcx); + let args_ref = args.internal(&mut *tables, cx.tcx); + cx.fn_sig(def_id, args_ref).stable(&mut *tables, cx) } /// Retrieve the intrinsic definition if the item corresponds one. - pub(crate) fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef> { - self.cx.intrinsic(item) + fn intrinsic(&self, item: DefId) -> Option<IntrinsicDef> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = item.internal(&mut *tables, cx.tcx); + cx.intrinsic(def_id).map(|_| IntrinsicDef(item)) } /// Retrieve the plain function name of an intrinsic. - pub(crate) fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol { - self.cx.intrinsic_name(def) + fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = def.0.internal(&mut *tables, cx.tcx); + cx.intrinsic_name(def_id) } /// Retrieve the closure signature for the given generic arguments. - pub(crate) fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { - self.cx.closure_sig(args) + fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let args_ref = args.internal(&mut *tables, cx.tcx); + cx.closure_sig(args_ref).stable(&mut *tables, cx) } /// The number of variants in this ADT. - pub(crate) fn adt_variants_len(&self, def: AdtDef) -> usize { - self.cx.adt_variants_len(def) + fn adt_variants_len(&self, def: AdtDef) -> usize { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.adt_variants_len(def.internal(&mut *tables, cx.tcx)) } - /// Discriminant for a given variant index of AdtDef - pub(crate) fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { - self.cx.adt_discr_for_variant(adt, variant) + /// Discriminant for a given variant index of AdtDef. + fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.adt_discr_for_variant( + adt.internal(&mut *tables, cx.tcx), + variant.internal(&mut *tables, cx.tcx), + ) + .stable(&mut *tables, cx) } - /// Discriminant for a given variand index and args of a coroutine - pub(crate) fn coroutine_discr_for_variant( + /// Discriminant for a given variand index and args of a coroutine. + fn coroutine_discr_for_variant( &self, coroutine: CoroutineDef, args: &GenericArgs, variant: VariantIdx, ) -> Discr { - self.cx.coroutine_discr_for_variant(coroutine, args, variant) + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let tcx = cx.tcx; + let def = coroutine.def_id().internal(&mut *tables, tcx); + let args_ref = args.internal(&mut *tables, tcx); + cx.coroutine_discr_for_variant(def, args_ref, variant.internal(&mut *tables, tcx)) + .stable(&mut *tables, cx) } /// The name of a variant. - pub(crate) fn variant_name(&self, def: VariantDef) -> Symbol { - self.cx.variant_name(def) + fn variant_name(&self, def: VariantDef) -> Symbol { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.variant_name(def.internal(&mut *tables, cx.tcx)) } - pub(crate) fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> { - self.cx.variant_fields(def) + fn variant_fields(&self, def: VariantDef) -> Vec<FieldDef> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + def.internal(&mut *tables, cx.tcx) + .fields + .iter() + .map(|f| f.stable(&mut *tables, cx)) + .collect() } /// Evaluate constant as a target usize. - pub(crate) fn eval_target_usize(&self, cnst: &MirConst) -> Result<u64, Error> { - self.cx.eval_target_usize(cnst) + fn eval_target_usize(&self, mir_const: &MirConst) -> Result<u64, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let cnst = mir_const.internal(&mut *tables, cx.tcx); + cx.eval_target_usize(cnst) } - pub(crate) fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result<u64, Error> { - self.cx.eval_target_usize_ty(cnst) + fn eval_target_usize_ty(&self, ty_const: &TyConst) -> Result<u64, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let cnst = ty_const.internal(&mut *tables, cx.tcx); + cx.eval_target_usize_ty(cnst) } /// Create a new zero-sized constant. - pub(crate) fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> { - self.cx.try_new_const_zst(ty) + fn try_new_const_zst(&self, ty: Ty) -> Result<MirConst, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let ty_internal = ty.internal(&mut *tables, cx.tcx); + cx.try_new_const_zst(ty_internal).map(|cnst| cnst.stable(&mut *tables, cx)) } /// Create a new constant that represents the given string value. - pub(crate) fn new_const_str(&self, value: &str) -> MirConst { - self.cx.new_const_str(value) + fn new_const_str(&self, value: &str) -> MirConst { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.new_const_str(value).stable(&mut *tables, cx) } /// Create a new constant that represents the given boolean value. - pub(crate) fn new_const_bool(&self, value: bool) -> MirConst { - self.cx.new_const_bool(value) + fn new_const_bool(&self, value: bool) -> MirConst { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.new_const_bool(value).stable(&mut *tables, cx) } /// Create a new constant that represents the given value. - pub(crate) fn try_new_const_uint( - &self, - value: u128, - uint_ty: UintTy, - ) -> Result<MirConst, Error> { - self.cx.try_new_const_uint(value, uint_ty) + fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<MirConst, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx)); + cx.try_new_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx)) } - pub(crate) fn try_new_ty_const_uint( - &self, - value: u128, - uint_ty: UintTy, - ) -> Result<TyConst, Error> { - self.cx.try_new_ty_const_uint(value, uint_ty) + fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result<TyConst, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let ty = cx.ty_new_uint(uint_ty.internal(&mut *tables, cx.tcx)); + cx.try_new_ty_const_uint(value, ty).map(|cnst| cnst.stable(&mut *tables, cx)) } /// Create a new type from the given kind. - pub(crate) fn new_rigid_ty(&self, kind: RigidTy) -> Ty { - self.cx.new_rigid_ty(kind) + fn new_rigid_ty(&self, kind: RigidTy) -> Ty { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let internal_kind = kind.internal(&mut *tables, cx.tcx); + cx.new_rigid_ty(internal_kind).stable(&mut *tables, cx) } /// Create a new box type, `Box<T>`, for the given inner type `T`. - pub(crate) fn new_box_ty(&self, ty: Ty) -> Ty { - self.cx.new_box_ty(ty) + fn new_box_ty(&self, ty: Ty) -> Ty { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let inner = ty.internal(&mut *tables, cx.tcx); + cx.new_box_ty(inner).stable(&mut *tables, cx) } /// Returns the type of given crate item. - pub(crate) fn def_ty(&self, item: DefId) -> Ty { - self.cx.def_ty(item) + fn def_ty(&self, item: DefId) -> Ty { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let inner = item.internal(&mut *tables, cx.tcx); + cx.def_ty(inner).stable(&mut *tables, cx) } /// Returns the type of given definition instantiated with the given arguments. - pub(crate) fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty { - self.cx.def_ty_with_args(item, args) + fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let inner = item.internal(&mut *tables, cx.tcx); + let args_ref = args.internal(&mut *tables, cx.tcx); + cx.def_ty_with_args(inner, args_ref).stable(&mut *tables, cx) } /// Returns literal value of a const as a string. - pub(crate) fn mir_const_pretty(&self, cnst: &MirConst) -> String { - self.cx.mir_const_pretty(cnst) + fn mir_const_pretty(&self, cnst: &MirConst) -> String { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cnst.internal(&mut *tables, cx.tcx).to_string() } /// `Span` of an item. - pub(crate) fn span_of_an_item(&self, def_id: DefId) -> Span { - self.cx.span_of_an_item(def_id) + fn span_of_an_item(&self, def_id: DefId) -> Span { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.span_of_an_item(did).stable(&mut *tables, cx) } - pub(crate) fn ty_const_pretty(&self, ct: TyConstId) -> String { - self.cx.ty_const_pretty(ct) + fn ty_const_pretty(&self, ct: TyConstId) -> String { + let tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.ty_const_pretty(tables.ty_consts[ct]) } /// Obtain the representation of a type. - pub(crate) fn ty_pretty(&self, ty: Ty) -> String { - self.cx.ty_pretty(ty) + fn ty_pretty(&self, ty: Ty) -> String { + let tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.ty_pretty(tables.types[ty]) } - /// Obtain the representation of a type. - pub(crate) fn ty_kind(&self, ty: Ty) -> TyKind { - self.cx.ty_kind(ty) + /// Obtain the kind of a type. + fn ty_kind(&self, ty: Ty) -> TyKind { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + cx.ty_kind(tables.types[ty]).stable(&mut *tables, cx) } /// Get the discriminant Ty for this Ty if there's one. - pub(crate) fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty { - self.cx.rigid_ty_discriminant_ty(ty) + fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let internal_kind = ty.internal(&mut *tables, cx.tcx); + cx.rigid_ty_discriminant_ty(internal_kind).stable(&mut *tables, cx) } /// Get the body of an Instance which is already monomorphized. - pub(crate) fn instance_body(&self, instance: InstanceDef) -> Option<Body> { - self.cx.instance_body(instance) + fn instance_body(&self, instance: InstanceDef) -> Option<Body> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let instance = tables.instances[instance]; + cx.instance_body(instance).map(|body| body.stable(&mut *tables, cx)) } /// Get the instance type with generic instantiations applied and lifetimes erased. - pub(crate) fn instance_ty(&self, instance: InstanceDef) -> Ty { - self.cx.instance_ty(instance) + fn instance_ty(&self, instance: InstanceDef) -> Ty { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let instance = tables.instances[instance]; + cx.instance_ty(instance).stable(&mut *tables, cx) } /// Get the instantiation types. - pub(crate) fn instance_args(&self, def: InstanceDef) -> GenericArgs { - self.cx.instance_args(def) + fn instance_args(&self, def: InstanceDef) -> GenericArgs { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let instance = tables.instances[def]; + cx.instance_args(instance).stable(&mut *tables, cx) } /// Get the instance. - pub(crate) fn instance_def_id(&self, instance: InstanceDef) -> DefId { - self.cx.instance_def_id(instance) + fn instance_def_id(&self, instance: InstanceDef) -> DefId { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let instance = tables.instances[instance]; + cx.instance_def_id(instance, &mut *tables) } /// Get the instance mangled name. - pub(crate) fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol { - self.cx.instance_mangled_name(instance) + fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol { + let tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let instance = tables.instances[instance]; + cx.instance_mangled_name(instance) } /// Check if this is an empty DropGlue shim. - pub(crate) fn is_empty_drop_shim(&self, def: InstanceDef) -> bool { - self.cx.is_empty_drop_shim(def) + fn is_empty_drop_shim(&self, def: InstanceDef) -> bool { + let tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let instance = tables.instances[def]; + cx.is_empty_drop_shim(instance) } /// Convert a non-generic crate item into an instance. /// This function will panic if the item is generic. - pub(crate) fn mono_instance(&self, def_id: DefId) -> Instance { - self.cx.mono_instance(def_id) + fn mono_instance(&self, def_id: DefId) -> Instance { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.mono_instance(did).stable(&mut *tables, cx) } /// Item requires monomorphization. - pub(crate) fn requires_monomorphization(&self, def_id: DefId) -> bool { - self.cx.requires_monomorphization(def_id) + fn requires_monomorphization(&self, def_id: DefId) -> bool { + let tables = self.tables.borrow(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.requires_monomorphization(did) } /// Resolve an instance from the given function definition and generic arguments. - pub(crate) fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> { - self.cx.resolve_instance(def, args) + fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = def.0.internal(&mut *tables, cx.tcx); + let args_ref = args.internal(&mut *tables, cx.tcx); + cx.resolve_instance(def_id, args_ref).map(|inst| inst.stable(&mut *tables, cx)) } /// Resolve an instance for drop_in_place for the given type. - pub(crate) fn resolve_drop_in_place(&self, ty: Ty) -> Instance { - self.cx.resolve_drop_in_place(ty) + fn resolve_drop_in_place(&self, ty: Ty) -> Instance { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let internal_ty = ty.internal(&mut *tables, cx.tcx); + + cx.resolve_drop_in_place(internal_ty).stable(&mut *tables, cx) } /// Resolve instance for a function pointer. - pub(crate) fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> { - self.cx.resolve_for_fn_ptr(def, args) + fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option<Instance> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = def.0.internal(&mut *tables, cx.tcx); + let args_ref = args.internal(&mut *tables, cx.tcx); + cx.resolve_for_fn_ptr(def_id, args_ref).stable(&mut *tables, cx) } /// Resolve instance for a closure with the requested type. - pub(crate) fn resolve_closure( + fn resolve_closure( &self, def: ClosureDef, args: &GenericArgs, kind: ClosureKind, ) -> Option<Instance> { - self.cx.resolve_closure(def, args, kind) + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = def.0.internal(&mut *tables, cx.tcx); + let args_ref = args.internal(&mut *tables, cx.tcx); + let closure_kind = kind.internal(&mut *tables, cx.tcx); + cx.resolve_closure(def_id, args_ref, closure_kind).map(|inst| inst.stable(&mut *tables, cx)) } /// Evaluate a static's initializer. - pub(crate) fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> { - self.cx.eval_static_initializer(def) + fn eval_static_initializer(&self, def: StaticDef) -> Result<Allocation, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let def_id = def.0.internal(&mut *tables, cx.tcx); + + cx.eval_static_initializer(def_id).stable(&mut *tables, cx) } /// Try to evaluate an instance into a constant. - pub(crate) fn eval_instance( - &self, - def: InstanceDef, - const_ty: Ty, - ) -> Result<Allocation, Error> { - self.cx.eval_instance(def, const_ty) + fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result<Allocation, Error> { + let mut tables = self.tables.borrow_mut(); + let instance = tables.instances[def]; + let cx = &*self.cx.borrow(); + let const_ty = const_ty.internal(&mut *tables, cx.tcx); + cx.eval_instance(instance) + .map(|const_val| alloc::try_new_allocation(const_ty, const_val, &mut *tables, cx)) + .map_err(|e| e.stable(&mut *tables, cx))? } /// Retrieve global allocation for the given allocation ID. - pub(crate) fn global_alloc(&self, id: AllocId) -> GlobalAlloc { - self.cx.global_alloc(id) + fn global_alloc(&self, id: AllocId) -> GlobalAlloc { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let alloc_id = id.internal(&mut *tables, cx.tcx); + cx.global_alloc(alloc_id).stable(&mut *tables, cx) } /// Retrieve the id for the virtual table. - pub(crate) fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId> { - self.cx.vtable_allocation(global_alloc) + fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option<AllocId> { + let mut tables = self.tables.borrow_mut(); + let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { + return None; + }; + let cx = &*self.cx.borrow(); + let ty = ty.internal(&mut *tables, cx.tcx); + let trait_ref = trait_ref.internal(&mut *tables, cx.tcx); + let alloc_id = cx.vtable_allocation(ty, trait_ref); + Some(alloc_id.stable(&mut *tables, cx)) } - pub(crate) fn krate(&self, def_id: DefId) -> Crate { - self.cx.krate(def_id) + fn krate(&self, def_id: DefId) -> Crate { + let tables = self.tables.borrow(); + let cx = &*self.cx.borrow(); + smir_crate(cx, tables[def_id].krate) } - pub(crate) fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol { - self.cx.instance_name(def, trimmed) + fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol { + let tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let instance = tables.instances[def]; + cx.instance_name(instance, trimmed) } /// Return information about the target machine. - pub(crate) fn target_info(&self) -> MachineInfo { - self.cx.target_info() + fn target_info(&self) -> MachineInfo { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + MachineInfo { + endian: cx.target_endian().stable(&mut *tables, cx), + pointer_width: MachineSize::from_bits(cx.target_pointer_size()), + } } /// Get an instance ABI. - pub(crate) fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> { - self.cx.instance_abi(def) + fn instance_abi(&self, def: InstanceDef) -> Result<FnAbi, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let instance = tables.instances[def]; + cx.instance_abi(instance).map(|fn_abi| fn_abi.stable(&mut *tables, cx)) } /// Get the ABI of a function pointer. - pub(crate) fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> { - self.cx.fn_ptr_abi(fn_ptr) + fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result<FnAbi, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let sig = fn_ptr.internal(&mut *tables, cx.tcx); + cx.fn_ptr_abi(sig).map(|fn_abi| fn_abi.stable(&mut *tables, cx)) } /// Get the layout of a type. - pub(crate) fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> { - self.cx.ty_layout(ty) + fn ty_layout(&self, ty: Ty) -> Result<Layout, Error> { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let internal_ty = ty.internal(&mut *tables, cx.tcx); + cx.ty_layout(internal_ty).map(|layout| layout.stable(&mut *tables, cx)) } /// Get the layout shape. - pub(crate) fn layout_shape(&self, id: Layout) -> LayoutShape { - self.cx.layout_shape(id) + fn layout_shape(&self, id: Layout) -> LayoutShape { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + id.internal(&mut *tables, cx.tcx).0.stable(&mut *tables, cx) } /// Get a debug string representation of a place. - pub(crate) fn place_pretty(&self, place: &Place) -> String { - self.cx.place_pretty(place) + fn place_pretty(&self, place: &Place) -> String { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + + format!("{:?}", place.internal(&mut *tables, cx.tcx)) } /// Get the resulting type of binary operation. - pub(crate) fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty { - self.cx.binop_ty(bin_op, rhs, lhs) + fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let rhs_internal = rhs.internal(&mut *tables, cx.tcx); + let lhs_internal = lhs.internal(&mut *tables, cx.tcx); + let bin_op_internal = bin_op.internal(&mut *tables, cx.tcx); + cx.binop_ty(bin_op_internal, rhs_internal, lhs_internal).stable(&mut *tables, cx) } /// Get the resulting type of unary operation. - pub(crate) fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty { - self.cx.unop_ty(un_op, arg) + fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let un_op = un_op.internal(&mut *tables, cx.tcx); + let arg = arg.internal(&mut *tables, cx.tcx); + cx.unop_ty(un_op, arg).stable(&mut *tables, cx) } /// Get all associated items of a definition. - pub(crate) fn associated_items(&self, def_id: DefId) -> AssocItems { - self.cx.associated_items(def_id) + fn associated_items(&self, def_id: DefId) -> AssocItems { + let mut tables = self.tables.borrow_mut(); + let cx = &*self.cx.borrow(); + let did = tables[def_id]; + cx.associated_items(did).iter().map(|assoc| assoc.stable(&mut *tables, cx)).collect() } } // A thread local variable that stores a pointer to [`SmirInterface`]. scoped_tls::scoped_thread_local!(static TLV: Cell<*const ()>); -pub(crate) fn run<'tcx, T, F>(interface: &SmirInterface<'tcx>, f: F) -> Result<T, Error> +pub(crate) fn run<F, T>(interface: &dyn SmirInterface, f: F) -> Result<T, Error> where F: FnOnce() -> T, { if TLV.is_set() { Err(Error::from("StableMIR already running")) } else { - let ptr: *const () = (interface as *const SmirInterface<'tcx>) as *const (); + let ptr: *const () = (&raw const interface) as _; TLV.set(&Cell::new(ptr), || Ok(f())) } } @@ -507,11 +1079,22 @@ where /// /// I.e., This function will load the current interface and calls a function with it. /// Do not nest these, as that will ICE. -pub(crate) fn with<R>(f: impl FnOnce(&SmirInterface<'_>) -> R) -> R { +pub(crate) fn with<R>(f: impl FnOnce(&dyn SmirInterface) -> R) -> R { assert!(TLV.is_set()); TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - f(unsafe { &*(ptr as *const SmirInterface<'_>) }) + f(unsafe { *(ptr as *const &dyn SmirInterface) }) }) } + +fn smir_crate<'tcx>( + cx: &SmirCtxt<'tcx, BridgeTys>, + crate_num: rustc_span::def_id::CrateNum, +) -> Crate { + let name = cx.crate_name(crate_num); + let is_local = cx.crate_is_local(crate_num); + let id = cx.crate_num_id(crate_num); + debug!(?name, ?crate_num, "smir_crate"); + Crate { id, name, is_local } +} diff --git a/compiler/rustc_smir/src/stable_mir/error.rs b/compiler/rustc_smir/src/stable_mir/error.rs index 050752e41eb..3f9d67954b9 100644 --- a/compiler/rustc_smir/src/stable_mir/error.rs +++ b/compiler/rustc_smir/src/stable_mir/error.rs @@ -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 { diff --git a/compiler/rustc_smir/src/stable_mir/mir/alloc.rs b/compiler/rustc_smir/src/stable_mir/mir/alloc.rs index 782f52888b7..26f30898a9c 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/alloc.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/alloc.rs @@ -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; diff --git a/compiler/rustc_smir/src/stable_mir/mir/mono.rs b/compiler/rustc_smir/src/stable_mir/mir/mono.rs index f5239cccae1..5f177416714 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/mono.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/mono.rs @@ -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 { diff --git a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs index b068a9a1081..a7347e9b021 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/pretty.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/pretty.rs @@ -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; diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index c59758d4ad3..70c09c12854 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -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), + } + } +} diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 398738d1c38..004a7c02234 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -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) } diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs index f878b6e6b71..4cbe02bfa0d 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs @@ -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() } } diff --git a/compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs new file mode 100644 index 00000000000..6e1b85671f8 --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/unstable/convert/mod.rs @@ -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)) + } +} diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/abi.rs index 35d5b7fb89a..d8823a0d10c 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/abi.rs @@ -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), } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mir.rs index daea4acc36c..99f9f456567 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mir.rs @@ -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)), } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mod.rs index 3494de62d83..799917c6e17 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mod.rs @@ -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) } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/ty.rs index ff0b8e833dc..c0a430079d8 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/unstable/convert/stable/ty.rs @@ -2,16 +2,20 @@ use rustc_middle::ty::Ty; use rustc_middle::{mir, ty}; +use rustc_smir::Tables; +use rustc_smir::context::SmirCtxt; +use stable_mir::alloc; +use stable_mir::compiler_interface::BridgeTys; use stable_mir::ty::{ AdtKind, FloatTy, GenericArgs, GenericParamDef, IntTy, Region, RigidTy, TyKind, UintTy, }; +use stable_mir::unstable::Stable; -use crate::rustc_smir::{Stable, Tables, alloc}; -use crate::stable_mir; +use crate::{rustc_smir, stable_mir}; impl<'tcx> Stable<'tcx> for ty::AliasTyKind { type T = stable_mir::ty::AliasKind; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { ty::Projection => stable_mir::ty::AliasKind::Projection, ty::Inherent => stable_mir::ty::AliasKind::Inherent, @@ -23,24 +27,35 @@ impl<'tcx> Stable<'tcx> for ty::AliasTyKind { impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> { type T = stable_mir::ty::AliasTy; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::AliasTy { args, def_id, .. } = self; - stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables) } + stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::AliasTerm<'tcx> { type T = stable_mir::ty::AliasTerm; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::AliasTerm { args, def_id, .. } = self; - stable_mir::ty::AliasTerm { def_id: tables.alias_def(*def_id), args: args.stable(tables) } + stable_mir::ty::AliasTerm { + def_id: tables.alias_def(*def_id), + args: args.stable(tables, cx), + } } } impl<'tcx> Stable<'tcx> for ty::DynKind { type T = stable_mir::ty::DynKind; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { ty::Dyn => stable_mir::ty::DynKind::Dyn, } @@ -50,14 +65,18 @@ impl<'tcx> Stable<'tcx> for ty::DynKind { impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> { type T = stable_mir::ty::ExistentialPredicate; - 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::ty::ExistentialPredicate::*; match self { ty::ExistentialPredicate::Trait(existential_trait_ref) => { - Trait(existential_trait_ref.stable(tables)) + Trait(existential_trait_ref.stable(tables, cx)) } ty::ExistentialPredicate::Projection(existential_projection) => { - Projection(existential_projection.stable(tables)) + Projection(existential_projection.stable(tables, cx)) } ty::ExistentialPredicate::AutoTrait(def_id) => AutoTrait(tables.trait_def(*def_id)), } @@ -67,11 +86,15 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> { impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> { type T = stable_mir::ty::ExistentialTraitRef; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::ExistentialTraitRef { def_id, args, .. } = self; stable_mir::ty::ExistentialTraitRef { def_id: tables.trait_def(*def_id), - generic_args: args.stable(tables), + generic_args: args.stable(tables, cx), } } } @@ -79,12 +102,16 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> { impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> { type T = stable_mir::ty::TermKind; - 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::ty::TermKind; match self { - ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables)), + ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables, cx)), ty::TermKind::Const(cnst) => { - let cnst = cnst.stable(tables); + let cnst = cnst.stable(tables, cx); TermKind::Const(cnst) } } @@ -94,25 +121,33 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> { impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> { type T = stable_mir::ty::ExistentialProjection; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::ExistentialProjection { def_id, args, term, .. } = self; stable_mir::ty::ExistentialProjection { def_id: tables.trait_def(*def_id), - generic_args: args.stable(tables), - term: term.kind().stable(tables), + generic_args: args.stable(tables, cx), + term: term.kind().stable(tables, cx), } } } impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion { type T = stable_mir::mir::PointerCoercion; - 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::ty::adjustment::PointerCoercion; match self { PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer, PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer, PointerCoercion::ClosureFnPointer(safety) => { - stable_mir::mir::PointerCoercion::ClosureFnPointer(safety.stable(tables)) + stable_mir::mir::PointerCoercion::ClosureFnPointer(safety.stable(tables, cx)) } PointerCoercion::MutToConstPointer => { stable_mir::mir::PointerCoercion::MutToConstPointer @@ -125,7 +160,7 @@ impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion { impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex { type T = usize; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { self.as_usize() } } @@ -133,7 +168,7 @@ impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex { impl<'tcx> Stable<'tcx> for ty::AdtKind { type T = AdtKind; - fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { ty::AdtKind::Struct => AdtKind::Struct, ty::AdtKind::Union => AdtKind::Union, @@ -145,30 +180,44 @@ impl<'tcx> Stable<'tcx> for ty::AdtKind { impl<'tcx> Stable<'tcx> for ty::FieldDef { type T = stable_mir::ty::FieldDef; - 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::ty::FieldDef { def: tables.create_def_id(self.did), - name: self.name.stable(tables), + name: self.name.stable(tables, cx), } } } impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> { type T = stable_mir::ty::GenericArgs; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - GenericArgs(self.iter().map(|arg| arg.kind().stable(tables)).collect()) + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { + GenericArgs(self.iter().map(|arg| arg.kind().stable(tables, cx)).collect()) } } impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> { type T = stable_mir::ty::GenericArgKind; - 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::ty::GenericArgKind; match self { - ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(region.stable(tables)), - ty::GenericArgKind::Type(ty) => GenericArgKind::Type(ty.stable(tables)), - ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables)), + ty::GenericArgKind::Lifetime(region) => { + GenericArgKind::Lifetime(region.stable(tables, cx)) + } + ty::GenericArgKind::Type(ty) => GenericArgKind::Type(ty.stable(tables, cx)), + ty::GenericArgKind::Const(cnst) => GenericArgKind::Const(cnst.stable(tables, cx)), } } } @@ -179,15 +228,19 @@ where { type T = stable_mir::ty::Binder<V>; - 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::ty::Binder; Binder { - value: self.as_ref().skip_binder().stable(tables), + value: self.as_ref().skip_binder().stable(tables, cx), bound_vars: self .bound_vars() .iter() - .map(|bound_var| bound_var.stable(tables)) + .map(|bound_var| bound_var.stable(tables, cx)) .collect(), } } @@ -199,23 +252,35 @@ where { type T = stable_mir::ty::EarlyBinder<V>; - 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::ty::EarlyBinder; - EarlyBinder { value: self.as_ref().skip_binder().stable(tables) } + EarlyBinder { value: self.as_ref().skip_binder().stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { type T = stable_mir::ty::FnSig; - 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::ty::FnSig; FnSig { - inputs_and_output: self.inputs_and_output.iter().map(|ty| ty.stable(tables)).collect(), + inputs_and_output: self + .inputs_and_output + .iter() + .map(|ty| ty.stable(tables, cx)) + .collect(), c_variadic: self.c_variadic, - safety: self.safety.stable(tables), - abi: self.abi.stable(tables), + safety: self.safety.stable(tables, cx), + abi: self.abi.stable(tables, cx), } } } @@ -223,7 +288,11 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { impl<'tcx> Stable<'tcx> for ty::BoundTyKind { type T = stable_mir::ty::BoundTyKind; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + _: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { use stable_mir::ty::BoundTyKind; match self { @@ -238,7 +307,11 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind { impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { type T = stable_mir::ty::BoundRegionKind; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + _: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { use stable_mir::ty::BoundRegionKind; match self { @@ -254,15 +327,19 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { impl<'tcx> Stable<'tcx> for ty::BoundVariableKind { type T = stable_mir::ty::BoundVariableKind; - 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::ty::BoundVariableKind; match self { ty::BoundVariableKind::Ty(bound_ty_kind) => { - BoundVariableKind::Ty(bound_ty_kind.stable(tables)) + BoundVariableKind::Ty(bound_ty_kind.stable(tables, cx)) } ty::BoundVariableKind::Region(bound_region_kind) => { - BoundVariableKind::Region(bound_region_kind.stable(tables)) + BoundVariableKind::Region(bound_region_kind.stable(tables, cx)) } ty::BoundVariableKind::Const => BoundVariableKind::Const, } @@ -272,7 +349,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundVariableKind { impl<'tcx> Stable<'tcx> for ty::IntTy { type T = IntTy; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { ty::IntTy::Isize => IntTy::Isize, ty::IntTy::I8 => IntTy::I8, @@ -287,7 +364,7 @@ impl<'tcx> Stable<'tcx> for ty::IntTy { impl<'tcx> Stable<'tcx> for ty::UintTy { type T = UintTy; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { ty::UintTy::Usize => UintTy::Usize, ty::UintTy::U8 => UintTy::U8, @@ -302,7 +379,7 @@ impl<'tcx> Stable<'tcx> for ty::UintTy { impl<'tcx> Stable<'tcx> for ty::FloatTy { type T = FloatTy; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { ty::FloatTy::F16 => FloatTy::F16, ty::FloatTy::F32 => FloatTy::F32, @@ -314,46 +391,55 @@ impl<'tcx> Stable<'tcx> for ty::FloatTy { impl<'tcx> Stable<'tcx> for Ty<'tcx> { type T = stable_mir::ty::Ty; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - tables.intern_ty(tables.tcx.lift(*self).unwrap()) + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { + tables.intern_ty(cx.lift(*self).unwrap()) } } impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { type T = stable_mir::ty::TyKind; - 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 { ty::Bool => TyKind::RigidTy(RigidTy::Bool), ty::Char => TyKind::RigidTy(RigidTy::Char), - ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables))), - ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))), - ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))), + ty::Int(int_ty) => TyKind::RigidTy(RigidTy::Int(int_ty.stable(tables, cx))), + ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables, cx))), + ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables, cx))), ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt( tables.adt_def(adt_def.did()), - generic_args.stable(tables), + generic_args.stable(tables, cx), )), ty::Foreign(def_id) => TyKind::RigidTy(RigidTy::Foreign(tables.foreign_def(*def_id))), ty::Str => TyKind::RigidTy(RigidTy::Str), ty::Array(ty, constant) => { - TyKind::RigidTy(RigidTy::Array(ty.stable(tables), constant.stable(tables))) + TyKind::RigidTy(RigidTy::Array(ty.stable(tables, cx), constant.stable(tables, cx))) } ty::Pat(ty, pat) => { - TyKind::RigidTy(RigidTy::Pat(ty.stable(tables), pat.stable(tables))) + TyKind::RigidTy(RigidTy::Pat(ty.stable(tables, cx), pat.stable(tables, cx))) } - ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables))), + ty::Slice(ty) => TyKind::RigidTy(RigidTy::Slice(ty.stable(tables, cx))), ty::RawPtr(ty, mutbl) => { - TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables), mutbl.stable(tables))) + TyKind::RigidTy(RigidTy::RawPtr(ty.stable(tables, cx), mutbl.stable(tables, cx))) } ty::Ref(region, ty, mutbl) => TyKind::RigidTy(RigidTy::Ref( - region.stable(tables), - ty.stable(tables), - mutbl.stable(tables), + region.stable(tables, cx), + ty.stable(tables, cx), + mutbl.stable(tables, cx), + )), + ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( + tables.fn_def(*def_id), + generic_args.stable(tables, cx), )), - ty::FnDef(def_id, generic_args) => { - TyKind::RigidTy(RigidTy::FnDef(tables.fn_def(*def_id), generic_args.stable(tables))) - } ty::FnPtr(sig_tys, hdr) => { - TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables))) + TyKind::RigidTy(RigidTy::FnPtr(sig_tys.with(*hdr).stable(tables, cx))) } // FIXME(unsafe_binders): ty::UnsafeBinder(_) => todo!(), @@ -361,36 +447,36 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { TyKind::RigidTy(RigidTy::Dynamic( existential_predicates .iter() - .map(|existential_predicate| existential_predicate.stable(tables)) + .map(|existential_predicate| existential_predicate.stable(tables, cx)) .collect(), - region.stable(tables), - dyn_kind.stable(tables), + region.stable(tables, cx), + dyn_kind.stable(tables, cx), )) } ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( tables.closure_def(*def_id), - generic_args.stable(tables), + generic_args.stable(tables, cx), )), ty::CoroutineClosure(..) => todo!("FIXME(async_closures): Lower these to SMIR"), ty::Coroutine(def_id, generic_args) => TyKind::RigidTy(RigidTy::Coroutine( tables.coroutine_def(*def_id), - generic_args.stable(tables), - tables.tcx.coroutine_movability(*def_id).stable(tables), + generic_args.stable(tables, cx), + cx.coroutine_movability(*def_id).stable(tables, cx), )), ty::Never => TyKind::RigidTy(RigidTy::Never), - ty::Tuple(fields) => { - TyKind::RigidTy(RigidTy::Tuple(fields.iter().map(|ty| ty.stable(tables)).collect())) - } + ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( + fields.iter().map(|ty| ty.stable(tables, cx)).collect(), + )), ty::Alias(alias_kind, alias_ty) => { - TyKind::Alias(alias_kind.stable(tables), alias_ty.stable(tables)) + TyKind::Alias(alias_kind.stable(tables, cx), alias_ty.stable(tables, cx)) } - ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables)), + ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables, cx)), ty::Bound(debruijn_idx, bound_ty) => { - TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables)) + TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables, cx)) } ty::CoroutineWitness(def_id, args) => TyKind::RigidTy(RigidTy::CoroutineWitness( tables.coroutine_witness_def(*def_id), - args.stable(tables), + args.stable(tables, cx), )), ty::Placeholder(..) | ty::Infer(_) | ty::Error(_) => { unreachable!(); @@ -402,12 +488,16 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { type T = stable_mir::ty::Pattern; - 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 { ty::PatternKind::Range { start, end } => stable_mir::ty::Pattern::Range { // FIXME(SMIR): update data structures to not have an Option here anymore - start: Some(start.stable(tables)), - end: Some(end.stable(tables)), + start: Some(start.stable(tables, cx)), + end: Some(end.stable(tables, cx)), include_end: true, }, ty::PatternKind::Or(_) => todo!(), @@ -418,24 +508,30 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { type T = stable_mir::ty::TyConst; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - let ct = tables.tcx.lift(*self).unwrap(); + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { + let ct = cx.lift(*self).unwrap(); let kind = match ct.kind() { ty::ConstKind::Value(cv) => { - let const_val = tables.tcx.valtree_to_const_val(cv); + let const_val = cx.valtree_to_const_val(cv); if matches!(const_val, mir::ConstValue::ZeroSized) { - stable_mir::ty::TyConstKind::ZSTValue(cv.ty.stable(tables)) + stable_mir::ty::TyConstKind::ZSTValue(cv.ty.stable(tables, cx)) } else { stable_mir::ty::TyConstKind::Value( - cv.ty.stable(tables), - alloc::new_allocation(cv.ty, const_val, tables), + cv.ty.stable(tables, cx), + alloc::new_allocation(cv.ty, const_val, tables, cx), ) } } - ty::ConstKind::Param(param) => stable_mir::ty::TyConstKind::Param(param.stable(tables)), + ty::ConstKind::Param(param) => { + stable_mir::ty::TyConstKind::Param(param.stable(tables, cx)) + } ty::ConstKind::Unevaluated(uv) => stable_mir::ty::TyConstKind::Unevaluated( tables.const_def(uv.def), - uv.args.stable(tables), + uv.args.stable(tables, cx), ), ty::ConstKind::Error(_) => unreachable!(), ty::ConstKind::Infer(_) => unreachable!(), @@ -450,7 +546,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { impl<'tcx> Stable<'tcx> for ty::ParamConst { type T = stable_mir::ty::ParamConst; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use stable_mir::ty::ParamConst; ParamConst { index: self.index, name: self.name.to_string() } } @@ -458,7 +554,7 @@ impl<'tcx> Stable<'tcx> for ty::ParamConst { impl<'tcx> Stable<'tcx> for ty::ParamTy { type T = stable_mir::ty::ParamTy; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use stable_mir::ty::ParamTy; ParamTy { index: self.index, name: self.name.to_string() } } @@ -466,15 +562,19 @@ impl<'tcx> Stable<'tcx> for ty::ParamTy { impl<'tcx> Stable<'tcx> for ty::BoundTy { type T = stable_mir::ty::BoundTy; - 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::ty::BoundTy; - BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables) } + BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind { type T = stable_mir::ty::TraitSpecializationKind; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use stable_mir::ty::TraitSpecializationKind; match self { @@ -489,20 +589,24 @@ impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind { impl<'tcx> Stable<'tcx> for ty::TraitDef { type T = stable_mir::ty::TraitDecl; - 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::opaque; use stable_mir::ty::TraitDecl; TraitDecl { def_id: tables.trait_def(self.def_id), - safety: self.safety.stable(tables), + safety: self.safety.stable(tables, cx), paren_sugar: self.paren_sugar, has_auto_impl: self.has_auto_impl, is_marker: self.is_marker, is_coinductive: self.is_coinductive, skip_array_during_method_dispatch: self.skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch: self.skip_boxed_slice_during_method_dispatch, - specialization_kind: self.specialization_kind.stable(tables), + specialization_kind: self.specialization_kind.stable(tables, cx), must_implement_one_of: self .must_implement_one_of .as_ref() @@ -515,20 +619,28 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef { impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> { type T = stable_mir::ty::TraitRef; - 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::ty::TraitRef; - TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables)).unwrap() + TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables, cx)).unwrap() } } impl<'tcx> Stable<'tcx> for ty::Generics { type T = stable_mir::ty::Generics; - 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::ty::Generics; - let params: Vec<_> = self.own_params.iter().map(|param| param.stable(tables)).collect(); + let params: Vec<_> = self.own_params.iter().map(|param| param.stable(tables, cx)).collect(); let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect(); @@ -541,7 +653,7 @@ impl<'tcx> Stable<'tcx> for ty::Generics { has_late_bound_regions: self .has_late_bound_regions .as_ref() - .map(|late_bound_regions| late_bound_regions.stable(tables)), + .map(|late_bound_regions| late_bound_regions.stable(tables, cx)), } } } @@ -549,7 +661,7 @@ impl<'tcx> Stable<'tcx> for ty::Generics { impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { type T = stable_mir::ty::GenericParamDefKind; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use stable_mir::ty::GenericParamDefKind; match self { ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime, @@ -566,13 +678,17 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind { impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef { type T = stable_mir::ty::GenericParamDef; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { GenericParamDef { name: self.name.to_string(), def_id: tables.generic_def(self.def_id), index: self.index, pure_wrt_drop: self.pure_wrt_drop, - kind: self.kind.stable(tables), + kind: self.kind.stable(tables, cx), } } } @@ -580,31 +696,36 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef { impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { type T = stable_mir::ty::PredicateKind; - 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::ty::PredicateKind; match self { PredicateKind::Clause(clause_kind) => { - stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables)) + stable_mir::ty::PredicateKind::Clause(clause_kind.stable(tables, cx)) } PredicateKind::DynCompatible(did) => { stable_mir::ty::PredicateKind::DynCompatible(tables.trait_def(*did)) } PredicateKind::Subtype(subtype_predicate) => { - stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables)) + stable_mir::ty::PredicateKind::SubType(subtype_predicate.stable(tables, cx)) } PredicateKind::Coerce(coerce_predicate) => { - stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables)) - } - PredicateKind::ConstEquate(a, b) => { - stable_mir::ty::PredicateKind::ConstEquate(a.stable(tables), b.stable(tables)) + stable_mir::ty::PredicateKind::Coerce(coerce_predicate.stable(tables, cx)) } + PredicateKind::ConstEquate(a, b) => stable_mir::ty::PredicateKind::ConstEquate( + a.stable(tables, cx), + b.stable(tables, cx), + ), PredicateKind::Ambiguous => stable_mir::ty::PredicateKind::Ambiguous, PredicateKind::NormalizesTo(_pred) => unimplemented!(), PredicateKind::AliasRelate(a, b, alias_relation_direction) => { stable_mir::ty::PredicateKind::AliasRelate( - a.kind().stable(tables), - b.kind().stable(tables), - alias_relation_direction.stable(tables), + a.kind().stable(tables, cx), + b.kind().stable(tables, cx), + alias_relation_direction.stable(tables, cx), ) } } @@ -614,34 +735,38 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> { impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { type T = stable_mir::ty::ClauseKind; - 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::ty::ClauseKind; match *self { ClauseKind::Trait(trait_object) => { - stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables)) + stable_mir::ty::ClauseKind::Trait(trait_object.stable(tables, cx)) } ClauseKind::RegionOutlives(region_outlives) => { - stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables)) + stable_mir::ty::ClauseKind::RegionOutlives(region_outlives.stable(tables, cx)) } ClauseKind::TypeOutlives(type_outlives) => { let ty::OutlivesPredicate::<_, _>(a, b) = type_outlives; stable_mir::ty::ClauseKind::TypeOutlives(stable_mir::ty::OutlivesPredicate( - a.stable(tables), - b.stable(tables), + a.stable(tables, cx), + b.stable(tables, cx), )) } ClauseKind::Projection(projection_predicate) => { - stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables)) + stable_mir::ty::ClauseKind::Projection(projection_predicate.stable(tables, cx)) } ClauseKind::ConstArgHasType(const_, ty) => stable_mir::ty::ClauseKind::ConstArgHasType( - const_.stable(tables), - ty.stable(tables), + const_.stable(tables, cx), + ty.stable(tables, cx), ), ClauseKind::WellFormed(term) => { - stable_mir::ty::ClauseKind::WellFormed(term.kind().stable(tables)) + stable_mir::ty::ClauseKind::WellFormed(term.kind().stable(tables, cx)) } ClauseKind::ConstEvaluatable(const_) => { - stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables)) + stable_mir::ty::ClauseKind::ConstEvaluatable(const_.stable(tables, cx)) } ClauseKind::HostEffect(..) => { todo!() @@ -653,7 +778,7 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> { impl<'tcx> Stable<'tcx> for ty::ClosureKind { type T = stable_mir::ty::ClosureKind; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::ty::ClosureKind::*; match self { Fn => stable_mir::ty::ClosureKind::Fn, @@ -666,25 +791,33 @@ impl<'tcx> Stable<'tcx> for ty::ClosureKind { impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> { type T = stable_mir::ty::SubtypePredicate; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::SubtypePredicate { a, b, a_is_expected: _ } = self; - stable_mir::ty::SubtypePredicate { a: a.stable(tables), b: b.stable(tables) } + stable_mir::ty::SubtypePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> { type T = stable_mir::ty::CoercePredicate; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::CoercePredicate { a, b } = self; - stable_mir::ty::CoercePredicate { a: a.stable(tables), b: b.stable(tables) } + stable_mir::ty::CoercePredicate { a: a.stable(tables, cx), b: b.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection { type T = stable_mir::ty::AliasRelationDirection; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::ty::AliasRelationDirection::*; match self { Equate => stable_mir::ty::AliasRelationDirection::Equate, @@ -696,11 +829,15 @@ impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection { impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> { type T = stable_mir::ty::TraitPredicate; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::TraitPredicate { trait_ref, polarity } = self; stable_mir::ty::TraitPredicate { - trait_ref: trait_ref.stable(tables), - polarity: polarity.stable(tables), + trait_ref: trait_ref.stable(tables, cx), + polarity: polarity.stable(tables, cx), } } } @@ -711,20 +848,28 @@ where { type T = stable_mir::ty::OutlivesPredicate<T::T, Region>; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::OutlivesPredicate(a, b) = self; - stable_mir::ty::OutlivesPredicate(a.stable(tables), b.stable(tables)) + stable_mir::ty::OutlivesPredicate(a.stable(tables, cx), b.stable(tables, cx)) } } impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { type T = stable_mir::ty::ProjectionPredicate; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { let ty::ProjectionPredicate { projection_term, term } = self; stable_mir::ty::ProjectionPredicate { - projection_term: projection_term.stable(tables), - term: term.kind().stable(tables), + projection_term: projection_term.stable(tables, cx), + term: term.kind().stable(tables, cx), } } } @@ -732,7 +877,7 @@ impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> { impl<'tcx> Stable<'tcx> for ty::ImplPolarity { type T = stable_mir::ty::ImplPolarity; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::ty::ImplPolarity::*; match self { Positive => stable_mir::ty::ImplPolarity::Positive, @@ -745,7 +890,7 @@ impl<'tcx> Stable<'tcx> for ty::ImplPolarity { impl<'tcx> Stable<'tcx> for ty::PredicatePolarity { type T = stable_mir::ty::PredicatePolarity; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_middle::ty::PredicatePolarity::*; match self { Positive => stable_mir::ty::PredicatePolarity::Positive, @@ -757,15 +902,23 @@ impl<'tcx> Stable<'tcx> for ty::PredicatePolarity { impl<'tcx> Stable<'tcx> for ty::Region<'tcx> { type T = stable_mir::ty::Region; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - Region { kind: self.kind().stable(tables) } + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { + Region { kind: self.kind().stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { type T = stable_mir::ty::RegionKind; - 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::ty::{BoundRegion, EarlyParamRegion, RegionKind}; match self { ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion { @@ -774,7 +927,10 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { }), ty::ReBound(db_index, bound_reg) => RegionKind::ReBound( db_index.as_u32(), - BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) }, + BoundRegion { + var: bound_reg.var.as_u32(), + kind: bound_reg.kind.stable(tables, cx), + }, ), ty::ReStatic => RegionKind::ReStatic, ty::RePlaceholder(place_holder) => { @@ -782,7 +938,7 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { universe: place_holder.universe.as_u32(), bound: BoundRegion { var: place_holder.bound.var.as_u32(), - kind: place_holder.bound.kind.stable(tables), + kind: place_holder.bound.kind.stable(tables, cx), }, }) } @@ -795,8 +951,12 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> { impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { type T = stable_mir::mir::mono::Instance; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - let def = tables.instance_def(tables.tcx.lift(*self).unwrap()); + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { + let def = tables.instance_def(cx.lift(*self).unwrap()); let kind = match self.def { ty::InstanceKind::Item(..) => stable_mir::mir::mono::InstanceKind::Item, ty::InstanceKind::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic, @@ -824,7 +984,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { impl<'tcx> Stable<'tcx> for ty::Variance { type T = stable_mir::mir::Variance; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { ty::Bivariant => stable_mir::mir::Variance::Bivariant, ty::Contravariant => stable_mir::mir::Variance::Contravariant, @@ -837,7 +997,7 @@ impl<'tcx> Stable<'tcx> for ty::Variance { impl<'tcx> Stable<'tcx> for ty::Movability { type T = stable_mir::ty::Movability; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { match self { ty::Movability::Static => stable_mir::ty::Movability::Static, ty::Movability::Movable => stable_mir::ty::Movability::Movable, @@ -848,7 +1008,7 @@ impl<'tcx> Stable<'tcx> for ty::Movability { impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { type T = stable_mir::ty::Abi; - fn stable(&self, _: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use rustc_abi::ExternAbi; use stable_mir::ty::Abi; match *self { @@ -886,10 +1046,14 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { type T = stable_mir::ty::ForeignModule; - 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::ty::ForeignModule { def_id: tables.foreign_module_def(self.def_id), - abi: self.abi.stable(tables), + abi: self.abi.stable(tables, cx), } } } @@ -897,7 +1061,11 @@ impl<'tcx> Stable<'tcx> for rustc_session::cstore::ForeignModule { impl<'tcx> Stable<'tcx> for ty::AssocKind { type T = stable_mir::ty::AssocKind; - 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::ty::{AssocKind, AssocTypeData}; match *self { ty::AssocKind::Const { name } => AssocKind::Const { name: name.to_string() }, @@ -908,7 +1076,7 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind { data: match data { ty::AssocTypeData::Normal(name) => AssocTypeData::Normal(name.to_string()), ty::AssocTypeData::Rpitit(rpitit) => { - AssocTypeData::Rpitit(rpitit.stable(tables)) + AssocTypeData::Rpitit(rpitit.stable(tables, cx)) } }, }, @@ -919,7 +1087,7 @@ impl<'tcx> Stable<'tcx> for ty::AssocKind { impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { type T = stable_mir::ty::AssocItemContainer; - fn stable(&self, _tables: &mut Tables<'_>) -> Self::T { + fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T { use stable_mir::ty::AssocItemContainer; match self { ty::AssocItemContainer::Trait => AssocItemContainer::Trait, @@ -931,11 +1099,15 @@ impl<'tcx> Stable<'tcx> for ty::AssocItemContainer { impl<'tcx> Stable<'tcx> for ty::AssocItem { type T = stable_mir::ty::AssocItem; - 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::ty::AssocItem { def_id: tables.assoc_def(self.def_id), - kind: self.kind.stable(tables), - container: self.container.stable(tables), + kind: self.kind.stable(tables, cx), + container: self.container.stable(tables, cx), trait_item_def_id: self.trait_item_def_id.map(|did| tables.assoc_def(did)), } } @@ -944,7 +1116,11 @@ impl<'tcx> Stable<'tcx> for ty::AssocItem { impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { type T = stable_mir::ty::ImplTraitInTraitData; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + _: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { use stable_mir::ty::ImplTraitInTraitData; match self { ty::ImplTraitInTraitData::Trait { fn_def_id, opaque_def_id } => { @@ -963,7 +1139,11 @@ impl<'tcx> Stable<'tcx> for ty::ImplTraitInTraitData { impl<'tcx> Stable<'tcx> for rustc_middle::ty::util::Discr<'tcx> { type T = stable_mir::ty::Discr; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - stable_mir::ty::Discr { val: self.val, ty: self.ty.stable(tables) } + fn stable<'cx>( + &self, + tables: &mut Tables<'cx, BridgeTys>, + cx: &SmirCtxt<'cx, BridgeTys>, + ) -> Self::T { + stable_mir::ty::Discr { val: self.val, ty: self.ty.stable(tables, cx) } } } diff --git a/compiler/rustc_smir/src/stable_mir/unstable/mod.rs b/compiler/rustc_smir/src/stable_mir/unstable/mod.rs new file mode 100644 index 00000000000..77a772019eb --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/unstable/mod.rs @@ -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), + } +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d6537d49be7..09f01d8704e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1623,7 +1623,6 @@ symbols! { pointee_sized, pointee_trait, pointer, - pointer_like, poll, poll_next, position, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs index 18971c47831..22eeb285b37 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs @@ -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 diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3a369f13e79..a6b77583fdc 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -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), - ) -} diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index a05bae53566..141454bfe37 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -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; } diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index 9d144010561..7dd3c59edd0 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -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); |
