diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 98d8c14f7d18..9d4b6192d6ea 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -19,6 +19,7 @@ env: PR_TITLE: Weekly `cargo update` PR_MESSAGE: | Automation to keep dependencies in `Cargo.lock` current. + r? dep-bumps The following is the output from `cargo update`: COMMIT_MESSAGE: "cargo update \n\n" diff --git a/Cargo.lock b/Cargo.lock index 7cf10628b005..34fc0860a4b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -581,7 +581,7 @@ dependencies = [ "serde_json", "syn 2.0.104", "tempfile", - "termize", + "termize 0.1.1", "tokio", "toml 0.7.8", "ui_test", @@ -3761,7 +3761,7 @@ dependencies = [ "serde", "serde_json", "termcolor", - "termize", + "termize 0.2.0", "tracing", "windows 0.61.3", ] @@ -4133,6 +4133,7 @@ dependencies = [ "rustc_fs_util", "rustc_hir", "rustc_hir_pretty", + "rustc_incremental", "rustc_index", "rustc_macros", "rustc_middle", @@ -4522,7 +4523,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", - "termize", + "termize 0.2.0", "tracing", "windows 0.61.3", ] @@ -5294,6 +5295,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "termize" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8da106d1a19c5b9c53c03311936568a0439926a7607815bd3461139cbab1cc" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "test-float-parse" version = "0.1.0" diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 18f0750aaa1f..8d3c10fd770a 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 61ef31b8f9f4..b5934f4e36e8 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 a1b1d670cfe0..02e95ddcb6fd 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 5437803d781d..8ad98c8d1d4a 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 NoArgsAttributeParser for PubTransparentParser { const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; const CREATE: fn(Span) -> AttributeKind = AttributeKind::PubTransparent; } + +pub(crate) struct PassByValueParser; +impl NoArgsAttributeParser for PassByValueParser { + const PATH: &[Symbol] = &[sym::rustc_pass_by_value]; + const ON_DUPLICATE: OnDuplicate = 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 0215504b52b7..f5ac3890a46a 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 000000000000..47cc925f7f6b --- /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 NoArgsAttributeParser for NoImplicitPreludeParser { + const PATH: &[rustc_span::Symbol] = &[sym::no_implicit_prelude]; + const ON_DUPLICATE: OnDuplicate = 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 000000000000..94f6a65c74ec --- /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 NoArgsAttributeParser for NonExhaustiveParser { + const PATH: &[Symbol] = &[sym::non_exhaustive]; + const ON_DUPLICATE: OnDuplicate = 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 bf8b1438df78..265e1bb6a8cb 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>, Single>, Single>, + Single>, Single>, + Single>, + Single>, Single>, Single>, // tidy-alphabetical-end diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs index ffb932a3c38e..04f1129d87c1 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 cf8aa500c778..0d8dc93274f9 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 9dca63cfc8d4..2b5090ed6dba 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 776658b9cca7..35922c100cd1 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 0ffa6b3205f3..599970663db8 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 82e7468211db..c4181a62a35d 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 fe9797026def..5746c28a2ab2 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 3f5872f34a6f..2f398cea926c 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 4348610be0af..719d4ca625ae 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 = 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 dad2fd99ef20..2ffd4e3cf285 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 10dd5ff9aa76..c11db63ba11f 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 5cec3331bb19..b2cfab37c1f6 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 ed8d25e9915c..4934136bc7af 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 464ffa8711a5..0133b1e8fcd3 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::::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 734c9c58c08a..65bc441a473e 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 16bac4304910..ed8f78216ff2 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 b10d5b55789b..271104c20c62 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 95743f9a63eb..0e775d374ab4 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 fef0dbf2ece9..bf539dfab42a 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> { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 2ff7caef732a..3a153ab089a4 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 499f5572f470..d155f4f98ad7 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 dbba45dc7bb5..0666b335e093 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 1cc618e2aeec..ea8c2c6ce23a 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 8380c3710e6f..316468b0a5d1 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 be0eb13cace6..94c93e736274 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 3fe7c5e42864..a438cde018c6 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 = 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 2bc30fa7cb04..370e886c525f 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 d85618f664d6..d3b3b55dd4c4 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 { 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 a163518fd195..0edc1d18ecc7 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 90bc427a19ae..b0ec605a85fe 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>, + // The path containing the metadata, to record as work product. + path: Option>, // We need to carry MaybeTempDir to avoid deleting the temporary // directory while accessing the Mmap. _temp_dir: Option, @@ -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 Encodable for EncodedMetadata { @@ -2365,17 +2383,53 @@ impl Decodable 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 = ecx.lazy(CrateHeader { + name: tcx.crate_name(LOCAL_CRATE), + triple: tcx.sess.opts.target_triple.clone(), + hash: tcx.crate_hash(LOCAL_CRATE), + is_proc_macro_crate: false, + is_stub: true, + }); + header.position.get() + }) + } + + let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata"); + + let dep_node = tcx.metadata_dep_node(); + + // If the metadata dep-node is green, try to reuse the saved work product. + if tcx.dep_graph.is_fully_enabled() + && let work_product_id = WorkProductId::from_cgu_name("metadata") + && let Some(work_product) = tcx.dep_graph.previous_work_product(&work_product_id) + && tcx.try_mark_green(&dep_node) + { + let saved_path = &work_product.saved_files["rmeta"]; + let incr_comp_session_dir = tcx.sess.incr_comp_session_dir_opt().unwrap(); + let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, saved_path); + debug!("copying preexisting metadata from {source_file:?} to {path:?}"); + match rustc_fs_util::link_or_copy(&source_file, path) { + Ok(_) => {} + Err(err) => tcx.dcx().emit_fatal(FailCreateFileEncoder { err }), + }; + return; + }; + if tcx.sess.threads() != 1 { // Prefetch some queries used by metadata encoding. // This is not necessary for correctness, but is only done for performance reasons. @@ -2389,35 +2443,32 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { ); } - with_encode_metadata_header(tcx, path, |ecx| { - // Encode all the entries and extra information in the crate, - // culminating in the `CrateRoot` which points to all of it. - let root = ecx.encode_crate_root(); + // Perform metadata encoding inside a task, so the dep-graph can check if any encoded + // information changes, and maybe reuse the work product. + tcx.dep_graph.with_task( + dep_node, + tcx, + path, + |tcx, path| { + with_encode_metadata_header(tcx, path, |ecx| { + // Encode all the entries and extra information in the crate, + // culminating in the `CrateRoot` which points to all of it. + let root = ecx.encode_crate_root(); - // Flush buffer to ensure backing file has the correct size. - ecx.opaque.flush(); - // Record metadata size for self-profiling - tcx.prof.artifact_size( - "crate_metadata", - "crate_metadata", - ecx.opaque.file().metadata().unwrap().len(), - ); + // Flush buffer to ensure backing file has the correct size. + ecx.opaque.flush(); + // Record metadata size for self-profiling + tcx.prof.artifact_size( + "crate_metadata", + "crate_metadata", + ecx.opaque.file().metadata().unwrap().len(), + ); - root.position.get() - }); - - if let Some(ref_path) = ref_path { - with_encode_metadata_header(tcx, ref_path, |ecx| { - let header: LazyValue = 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 0c998a2cbb38..0c757a390ca0 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; diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs index 0a8e6153817e..781e3e442e64 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 8c20e71e26a5..17a29c9ae4b2 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 { desc { "fetching potentially unused trait imports" } } - query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxIndexSet { - 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 6d5a3abf665b..44165b06f1c3 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 efa47b57cf38..e8b15b76fd89 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 { - // 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 84b21fee92fe..a92d6fe3916d 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, + pub expn_that_defined: UnordMap, pub effective_visibilities: EffectiveVisibilities, pub extern_crate_map: UnordMap, pub maybe_unused_trait_imports: FxIndexSet, @@ -196,8 +196,8 @@ pub struct ResolverGlobalCtxt { pub confused_type_with_std_module: FxIndexMap, pub doc_link_resolutions: FxIndexMap, pub doc_link_traits_in_scope: FxIndexMap>, - pub all_macro_rules: FxHashSet, - pub stripped_cfg_items: Steal>, + pub all_macro_rules: UnordSet, + pub stripped_cfg_items: Vec, } /// 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, 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 e44a440b5c13..a44afed5492d 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 4d64cdeb69ab..27355a422d1f 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 87d46e3e5069..c5ced4064140 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>, @@ -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 46ced7500ea2..e53cebc59baf 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 9fbbcdc75569..55549cba737e 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::>( is_anon!([$($modifiers)*]), diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 18078b760c3e..c99bc747fd21 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 05bc3611dd87..7162f3a77d35 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, + expn_that_defined: UnordMap, graph_root: Module<'ra>, @@ -1208,7 +1208,7 @@ pub struct Resolver<'ra, 'tcx> { effective_visibilities: EffectiveVisibilities, doc_link_resolutions: FxIndexMap, doc_link_traits_in_scope: FxIndexMap>, - all_macro_rules: FxHashSet, + all_macro_rules: UnordSet, /// Invocation ids of all glob delegations. glob_delegation_invoc_ids: FxHashSet, @@ -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 5b88a7017c51..0516982aeabb 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 74e766a1e951..4627c2978fc0 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 2982a920b03d..dcdc77b76c21 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 for Tables<'tcx> { - type Output = DefId; - - #[inline(always)] - fn index(&self, index: stable_mir::DefId) -> &Self::Output { - &self.def_ids[index] - } -} - -impl<'tcx> Index 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(f: impl for<'tcx> FnOnce(&mut Tables<'tcx>) -> R) -> R { +pub(crate) fn with_container( + 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(tcx: TyCtxt<'_>, f: F) -> Result 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 { - index_map: fx::FxIndexMap, -} - -impl Default for IndexMap { - fn default() -> Self { - Self { index_map: FxIndexMap::default() } - } -} - -impl IndexMap { - 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 Index - for IndexMap -{ - 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 a6d31ac4e13d..ecaf3571896e 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>, &'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 { + 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 { - 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 { + 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> = 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 000000000000..a31eb93d0e80 --- /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(err: T) -> Self; +} + +pub trait Prov { + fn new(aid: B::AllocId) -> Self; +} + +pub trait Allocation { + fn new<'tcx>( + bytes: Vec>, + 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 { + 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 40e6d21c0637..2141053d09af 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 3fa83cfc6a08..000000000000 --- 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>); - -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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - let tables = self.0.borrow(); - let crates: Vec = [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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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`, 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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::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 { - 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, 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 000000000000..89ae47143ef6 --- /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>>(&self, value: T) -> Option { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + self.tcx.all_traits_including_private() + } + + pub fn trait_decls(&self, crate_num: CrateNum) -> Vec { + 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 { + 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 { + 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, 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, 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 { + 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 { + let crates: Vec = [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 { + 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 { + 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 { + 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, 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, 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, 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`, 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> { + 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> { + 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::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> { + 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, 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, 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>>, + ) -> 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::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, 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 { + 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 000000000000..38743e5f7d37 --- /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, +} + +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, 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 000000000000..19e09016cdde --- /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 2cde5542483d..000000000000 --- 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 26de9b0a4960..e8b7a3fec092 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,91 +7,263 @@ //! //! For now, we are developing everything inside `rustc`, thus, we keep this module private. -use std::marker::PointeeSized; -use std::ops::RangeInclusive; +use std::cell::RefCell; +use std::fmt::Debug; +use std::hash::Hash; +use std::ops::Index; -use rustc_hir::def::DefKind; +use bridge::*; +use context::SmirCtxt; +use rustc_data_structures::fx::{self, FxIndexMap}; use rustc_middle::mir; use rustc_middle::mir::interpret::AllocId; -use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::Span; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use stable_mir::abi::Layout; -use stable_mir::mir::mono::{InstanceDef, StaticDef}; -use stable_mir::ty::{FnDef, MirConstId, Span, TyConstId}; -use stable_mir::{CtorKind, ItemKind}; -use tracing::debug; -use crate::rustc_internal::IndexMap; -use crate::stable_mir; - -mod alloc; +pub mod alloc; +pub mod bridge; mod builder; pub mod context; -mod convert; -pub struct Tables<'tcx> { - pub(crate) tcx: TyCtxt<'tcx>, - pub(crate) def_ids: IndexMap, - pub(crate) alloc_ids: IndexMap, - pub(crate) spans: IndexMap, - pub(crate) types: IndexMap, stable_mir::ty::Ty>, - pub(crate) instances: IndexMap, InstanceDef>, - pub(crate) ty_consts: IndexMap, TyConstId>, - pub(crate) mir_consts: IndexMap, MirConstId>, - pub(crate) layouts: IndexMap, Layout>, +/// A container which is used for TLS. +pub struct SmirContainer<'tcx, B: Bridge> { + pub tables: RefCell>, + pub cx: RefCell>, } -impl<'tcx> Tables<'tcx> { - pub(crate) fn intern_ty(&mut self, ty: Ty<'tcx>) -> stable_mir::ty::Ty { +pub struct Tables<'tcx, B: Bridge> { + pub def_ids: IndexMap, + pub alloc_ids: IndexMap, + pub spans: IndexMap, + pub types: IndexMap, B::Ty>, + pub instances: IndexMap, B::InstanceDef>, + pub ty_consts: IndexMap, B::TyConstId>, + pub mir_consts: IndexMap, B::MirConstId>, + pub layouts: IndexMap, B::Layout>, +} + +impl<'tcx, B: Bridge> Default for Tables<'tcx, B> { + fn default() -> Self { + Self { + def_ids: IndexMap::default(), + alloc_ids: IndexMap::default(), + spans: IndexMap::default(), + types: IndexMap::default(), + instances: IndexMap::default(), + ty_consts: IndexMap::default(), + mir_consts: IndexMap::default(), + layouts: IndexMap::default(), + } + } +} + +impl<'tcx, B: Bridge> Index for Tables<'tcx, B> { + type Output = DefId; + + #[inline(always)] + fn index(&self, index: B::DefId) -> &Self::Output { + &self.def_ids[index] + } +} + +impl<'tcx, B: Bridge> Tables<'tcx, B> { + pub fn intern_ty(&mut self, ty: Ty<'tcx>) -> B::Ty { self.types.create_or_fetch(ty) } - pub(crate) fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> TyConstId { + pub fn intern_ty_const(&mut self, ct: ty::Const<'tcx>) -> B::TyConstId { self.ty_consts.create_or_fetch(ct) } - pub(crate) fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> MirConstId { + pub fn intern_mir_const(&mut self, constant: mir::Const<'tcx>) -> B::MirConstId { self.mir_consts.create_or_fetch(constant) } - /// Return whether the instance as a body available. - /// - /// Items and intrinsics may have a body available from its definition. - /// Shims body may be generated depending on their type. - pub(crate) fn instance_has_body(&self, instance: Instance<'tcx>) -> bool { - let def_id = instance.def_id(); - self.item_has_body(def_id) - || !matches!( - instance.def, - ty::InstanceKind::Virtual(..) - | ty::InstanceKind::Intrinsic(..) - | ty::InstanceKind::Item(..) - ) + pub fn create_def_id(&mut self, did: DefId) -> B::DefId { + self.def_ids.create_or_fetch(did) } - /// Return whether the item has a body defined by the user. - /// - /// Note that intrinsics may have a placeholder body that shouldn't be used in practice. - /// In StableMIR, we handle this case as if the body is not available. - pub(crate) fn item_has_body(&self, def_id: DefId) -> bool { - let must_override = if let Some(intrinsic) = self.tcx.intrinsic(def_id) { - intrinsic.must_be_overridden - } else { - false - }; - !must_override && self.tcx.is_mir_available(def_id) + pub fn create_alloc_id(&mut self, aid: AllocId) -> B::AllocId { + self.alloc_ids.create_or_fetch(aid) } - fn to_fn_def(&mut self, def_id: DefId) -> Option { - if matches!(self.tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) { - Some(self.fn_def(def_id)) - } else { - None - } + pub fn create_span(&mut self, span: Span) -> B::Span { + self.spans.create_or_fetch(span) } - fn to_static(&mut self, def_id: DefId) -> Option { - matches!(self.tcx.def_kind(def_id), DefKind::Static { .. }).then(|| self.static_def(def_id)) + pub fn instance_def(&mut self, instance: ty::Instance<'tcx>) -> B::InstanceDef { + self.instances.create_or_fetch(instance) + } + + pub fn layout_id(&mut self, layout: rustc_abi::Layout<'tcx>) -> B::Layout { + self.layouts.create_or_fetch(layout) + } + + pub fn crate_item(&mut self, did: rustc_span::def_id::DefId) -> B::CrateItem { + B::CrateItem::new(self.create_def_id(did)) + } + + pub fn adt_def(&mut self, did: rustc_span::def_id::DefId) -> B::AdtDef { + B::AdtDef::new(self.create_def_id(did)) + } + + pub fn foreign_module_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignModuleDef { + B::ForeignModuleDef::new(self.create_def_id(did)) + } + + pub fn foreign_def(&mut self, did: rustc_span::def_id::DefId) -> B::ForeignDef { + B::ForeignDef::new(self.create_def_id(did)) + } + + pub fn fn_def(&mut self, did: rustc_span::def_id::DefId) -> B::FnDef { + B::FnDef::new(self.create_def_id(did)) + } + + pub fn closure_def(&mut self, did: rustc_span::def_id::DefId) -> B::ClosureDef { + B::ClosureDef::new(self.create_def_id(did)) + } + + pub fn coroutine_def(&mut self, did: rustc_span::def_id::DefId) -> B::CoroutineDef { + B::CoroutineDef::new(self.create_def_id(did)) + } + + pub fn coroutine_closure_def( + &mut self, + did: rustc_span::def_id::DefId, + ) -> B::CoroutineClosureDef { + B::CoroutineClosureDef::new(self.create_def_id(did)) + } + + pub fn alias_def(&mut self, did: rustc_span::def_id::DefId) -> B::AliasDef { + B::AliasDef::new(self.create_def_id(did)) + } + + pub fn param_def(&mut self, did: rustc_span::def_id::DefId) -> B::ParamDef { + B::ParamDef::new(self.create_def_id(did)) + } + + pub fn br_named_def(&mut self, did: rustc_span::def_id::DefId) -> B::BrNamedDef { + B::BrNamedDef::new(self.create_def_id(did)) + } + + pub fn trait_def(&mut self, did: rustc_span::def_id::DefId) -> B::TraitDef { + B::TraitDef::new(self.create_def_id(did)) + } + + pub fn generic_def(&mut self, did: rustc_span::def_id::DefId) -> B::GenericDef { + B::GenericDef::new(self.create_def_id(did)) + } + + pub fn const_def(&mut self, did: rustc_span::def_id::DefId) -> B::ConstDef { + B::ConstDef::new(self.create_def_id(did)) + } + + pub fn impl_def(&mut self, did: rustc_span::def_id::DefId) -> B::ImplDef { + B::ImplDef::new(self.create_def_id(did)) + } + + pub fn region_def(&mut self, did: rustc_span::def_id::DefId) -> B::RegionDef { + B::RegionDef::new(self.create_def_id(did)) + } + + pub fn coroutine_witness_def( + &mut self, + did: rustc_span::def_id::DefId, + ) -> B::CoroutineWitnessDef { + B::CoroutineWitnessDef::new(self.create_def_id(did)) + } + + pub fn assoc_def(&mut self, did: rustc_span::def_id::DefId) -> B::AssocDef { + B::AssocDef::new(self.create_def_id(did)) + } + + pub fn opaque_def(&mut self, did: rustc_span::def_id::DefId) -> B::OpaqueDef { + B::OpaqueDef::new(self.create_def_id(did)) + } + + pub fn prov(&mut self, aid: rustc_middle::mir::interpret::AllocId) -> B::Prov { + B::Prov::new(self.create_alloc_id(aid)) + } + + pub fn static_def(&mut self, did: rustc_span::def_id::DefId) -> B::StaticDef { + B::StaticDef::new(self.create_def_id(did)) + } +} + +/// A trait defining types that are used to emulate StableMIR components, which is really +/// useful when programming in stable_mir-agnostic settings. +pub trait Bridge: Sized { + type DefId: Copy + Debug + PartialEq + IndexedVal; + type AllocId: Copy + Debug + PartialEq + IndexedVal; + type Span: Copy + Debug + PartialEq + IndexedVal; + type Ty: Copy + Debug + PartialEq + IndexedVal; + type InstanceDef: Copy + Debug + PartialEq + IndexedVal; + type TyConstId: Copy + Debug + PartialEq + IndexedVal; + type MirConstId: Copy + Debug + PartialEq + IndexedVal; + type Layout: Copy + Debug + PartialEq + IndexedVal; + + type Error: SmirError; + type CrateItem: CrateItem; + type AdtDef: AdtDef; + type ForeignModuleDef: ForeignModuleDef; + type ForeignDef: ForeignDef; + type FnDef: FnDef; + type ClosureDef: ClosureDef; + type CoroutineDef: CoroutineDef; + type CoroutineClosureDef: CoroutineClosureDef; + type AliasDef: AliasDef; + type ParamDef: ParamDef; + type BrNamedDef: BrNamedDef; + type TraitDef: TraitDef; + type GenericDef: GenericDef; + type ConstDef: ConstDef; + type ImplDef: ImplDef; + type RegionDef: RegionDef; + type CoroutineWitnessDef: CoroutineWitnessDef; + type AssocDef: AssocDef; + type OpaqueDef: OpaqueDef; + type Prov: Prov; + type StaticDef: StaticDef; + + type Allocation: Allocation; +} + +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 { + index_map: fx::FxIndexMap, +} + +impl Default for IndexMap { + fn default() -> Self { + Self { index_map: FxIndexMap::default() } + } +} + +impl IndexMap { + 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 Index + for IndexMap +{ + type Output = K; + + fn index(&self, index: V) -> &Self::Output { + let (k, v) = self.index_map.get_index(index.to_index()).unwrap(); + assert_eq!(*v, index, "Provided value doesn't match with indexed value"); + k } } @@ -112,124 +284,3 @@ where .collect() } } - -/// Build a stable mir crate from a given crate number. -pub(crate) fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { - let crate_name = tcx.crate_name(crate_num).to_string(); - let is_local = crate_num == LOCAL_CRATE; - debug!(?crate_name, ?crate_num, "smir_crate"); - stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local } -} - -pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind { - match kind { - DefKind::Mod - | DefKind::Struct - | DefKind::Union - | DefKind::Enum - | DefKind::Variant - | DefKind::Trait - | DefKind::TyAlias - | DefKind::ForeignTy - | DefKind::TraitAlias - | DefKind::AssocTy - | DefKind::TyParam - | DefKind::ConstParam - | DefKind::Macro(_) - | DefKind::ExternCrate - | DefKind::Use - | DefKind::ForeignMod - | DefKind::OpaqueTy - | DefKind::Field - | DefKind::LifetimeParam - | DefKind::Impl { .. } - | DefKind::GlobalAsm => { - unreachable!("Not a valid item kind: {kind:?}"); - } - DefKind::Closure | DefKind::AssocFn | DefKind::Fn | DefKind::SyntheticCoroutineBody => { - ItemKind::Fn - } - DefKind::Const | DefKind::InlineConst | DefKind::AssocConst | DefKind::AnonConst => { - ItemKind::Const - } - DefKind::Static { .. } => ItemKind::Static, - DefKind::Ctor(_, rustc_hir::def::CtorKind::Const) => ItemKind::Ctor(CtorKind::Const), - DefKind::Ctor(_, rustc_hir::def::CtorKind::Fn) => ItemKind::Ctor(CtorKind::Fn), - } -} - -/// Trait used to convert between an internal MIR type to a Stable MIR type. -pub trait Stable<'cx>: PointeeSized { - /// The stable representation of the type implementing Stable. - type T; - /// Converts an object to the equivalent Stable MIR representation. - fn stable(&self, tables: &mut Tables<'_>) -> Self::T; -} - -impl<'tcx, T> Stable<'tcx> for &T -where - T: Stable<'tcx>, -{ - type T = T::T; - - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - (*self).stable(tables) - } -} - -impl<'tcx, T> Stable<'tcx> for Option -where - T: Stable<'tcx>, -{ - type T = Option; - - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - self.as_ref().map(|value| value.stable(tables)) - } -} - -impl<'tcx, T, E> Stable<'tcx> for Result -where - T: Stable<'tcx>, - E: Stable<'tcx>, -{ - type T = Result; - - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - match self { - Ok(val) => Ok(val.stable(tables)), - Err(error) => Err(error.stable(tables)), - } - } -} - -impl<'tcx, T> Stable<'tcx> for &[T] -where - T: Stable<'tcx>, -{ - type T = Vec; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - self.iter().map(|e| e.stable(tables)).collect() - } -} - -impl<'tcx, T, U> Stable<'tcx> for (T, U) -where - T: Stable<'tcx>, - U: Stable<'tcx>, -{ - type T = (T::T, U::T); - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - (self.0.stable(tables), self.1.stable(tables)) - } -} - -impl<'tcx, T> Stable<'tcx> for RangeInclusive -where - T: Stable<'tcx>, -{ - type T = RangeInclusive; - fn stable(&self, tables: &mut Tables<'_>) -> Self::T { - RangeInclusive::new(self.start().stable(tables), self.end().stable(tables)) - } -} diff --git a/compiler/rustc_smir/src/stable_mir/abi.rs b/compiler/rustc_smir/src/stable_mir/abi.rs index d8a2b97662c4..369d08e444ec 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 000000000000..120cb4404b96 --- /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 { + 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 2668fba9f4f6..a19968d2ab77 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; + /// 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; + + /// Retrieve all functions defined in this crate. + fn crate_functions(&self, crate_num: CrateNum) -> Vec; + + /// Retrieve all static items defined in this crate. + fn crate_statics(&self, crate_num: CrateNum) -> Vec; + fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule; + fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec; + 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; + + /// Find a crate with the given name. + fn find_crates(&self, name: &str) -> Vec; + + /// 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; + + /// Get all tool attributes of a definition. + fn all_tool_attrs(&self, def_id: DefId) -> Vec; + + /// 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; + + /// 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; + + /// Evaluate constant as a target usize. + fn eval_target_usize(&self, cnst: &MirConst) -> Result; + fn eval_target_usize_ty(&self, cnst: &TyConst) -> Result; + + /// Create a new zero-sized constant. + fn try_new_const_zst(&self, ty: Ty) -> Result; + + /// 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; + fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result; + + /// Create a new type from the given kind. + fn new_rigid_ty(&self, kind: RigidTy) -> Ty; + + /// Create a new box type, `Box`, 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; + + /// 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; + + /// 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; + + /// Resolve instance for a closure with the requested type. + fn resolve_closure( + &self, + def: ClosureDef, + args: &GenericArgs, + kind: ClosureKind, + ) -> Option; + + /// Evaluate a static's initializer. + fn eval_static_initializer(&self, def: StaticDef) -> Result; + + /// Try to evaluate an instance into a constant. + fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result; + + /// 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; + 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; + + /// Get the ABI of a function pointer. + fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result; + + /// Get the layout of a type. + fn ty_layout(&self, ty: Ty) -> Result; + + /// 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 { - self.cx.entry_fn() +impl<'tcx> SmirInterface for SmirContainer<'tcx, BridgeTys> { + fn entry_fn(&self) -> Option { + 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 { - self.cx.foreign_modules(crate_num) + fn foreign_modules(&self, crate_num: CrateNum) -> Vec { + 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 { - self.cx.crate_functions(crate_num) + fn crate_functions(&self, crate_num: CrateNum) -> Vec { + 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 { - self.cx.crate_statics(crate_num) + fn crate_statics(&self, crate_num: CrateNum) -> Vec { + 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 { - self.cx.foreign_items(mod_def) + fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec { + 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 { - self.cx.external_crates() + fn external_crates(&self) -> Vec { + 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 { - self.cx.find_crates(name) + fn find_crates(&self, name: &str) -> Vec { + 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 { - self.cx.tool_attrs(def_id, attr) + fn tool_attrs(&self, def_id: DefId, attr: &[Symbol]) -> Vec { + 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 { - self.cx.all_tool_attrs(def_id) + fn all_tool_attrs(&self, def_id: DefId) -> Vec { + 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 { - self.cx.intrinsic(item) + fn intrinsic(&self, item: DefId) -> Option { + 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 { - self.cx.variant_fields(def) + fn variant_fields(&self, def: VariantDef) -> Vec { + 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 { - self.cx.eval_target_usize(cnst) + fn eval_target_usize(&self, mir_const: &MirConst) -> Result { + 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 { - self.cx.eval_target_usize_ty(cnst) + fn eval_target_usize_ty(&self, ty_const: &TyConst) -> Result { + 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 { - self.cx.try_new_const_zst(ty) + fn try_new_const_zst(&self, ty: Ty) -> Result { + 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 { - self.cx.try_new_const_uint(value, uint_ty) + fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + 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 { - self.cx.try_new_ty_const_uint(value, uint_ty) + fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + 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`, 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 { - self.cx.instance_body(instance) + fn instance_body(&self, instance: InstanceDef) -> Option { + 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 { - self.cx.resolve_instance(def, args) + fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option { + 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 { - self.cx.resolve_for_fn_ptr(def, args) + fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option { + 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 { - 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 { - self.cx.eval_static_initializer(def) + fn eval_static_initializer(&self, def: StaticDef) -> Result { + 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 { - self.cx.eval_instance(def, const_ty) + fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result { + 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 { - self.cx.vtable_allocation(global_alloc) + fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option { + 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 { - self.cx.instance_abi(def) + fn instance_abi(&self, def: InstanceDef) -> Result { + 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 { - self.cx.fn_ptr_abi(fn_ptr) + fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result { + 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 { - self.cx.ty_layout(ty) + fn ty_layout(&self, ty: Ty) -> Result { + 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 +pub(crate) fn run(interface: &dyn SmirInterface, f: F) -> Result 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(f: impl FnOnce(&SmirInterface<'_>) -> R) -> R { +pub(crate) fn with(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 050752e41eb9..3f9d67954b9d 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 { #[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(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 782f52888b73..26f30898a9cc 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 f5239cccae1e..5f177416714e 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 b068a9a1081f..a7347e9b0216 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 c59758d4ad3f..70c09c128541 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(value: &T) -> Opaque { Opaque(format!("{value:?}")) } + +macro_rules! bridge_impl { + ($name: ident, $ty: ty) => { + impl rustc_smir::bridge::$name 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 for stable_mir::ty::Prov { + fn new(aid: stable_mir::mir::alloc::AllocId) -> Self { + Self(aid) + } +} + +impl rustc_smir::bridge::Allocation for stable_mir::ty::Allocation { + fn new<'tcx>( + bytes: Vec>, + 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 398738d1c389..004a7c022346 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 similarity index 72% rename from compiler/rustc_smir/src/rustc_internal/internal.rs rename to compiler/rustc_smir/src/stable_mir/unstable/convert/internal.rs index f878b6e6b717..4cbe02bfa0db 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>; - 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>; - 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 000000000000..6e1b85671f84 --- /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 +where + T: Stable<'tcx>, +{ + type T = Option; + + 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 +where + T: Stable<'tcx>, + E: Stable<'tcx>, +{ + type T = Result; + + 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; + 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 +where + T: Stable<'tcx>, +{ + type T = RangeInclusive; + 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 similarity index 65% rename from compiler/rustc_smir/src/rustc_smir/convert/abi.rs rename to compiler/rustc_smir/src/stable_mir/unstable/convert/stable/abi.rs index 35d5b7fb89af..d8823a0d10c0 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 { 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 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 { 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 { impl<'tcx> Stable<'tcx> for rustc_abi::Variants { 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 Stable<'tcx> for rustc_abi::TagEncoding { 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 { 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 similarity index 68% rename from compiler/rustc_smir/src/rustc_smir/convert/mir.rs rename to compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mir.rs index daea4acc36c0..99f9f456567c 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` 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 similarity index 68% rename from compiler/rustc_smir/src/rustc_smir/convert/mod.rs rename to compiler/rustc_smir/src/stable_mir/unstable/convert/stable/mod.rs index 3494de62d835..799917c6e171 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 similarity index 69% rename from compiler/rustc_smir/src/rustc_smir/convert/ty.rs rename to compiler/rustc_smir/src/stable_mir/unstable/convert/stable/ty.rs index ff0b8e833dcc..c0a430079d8b 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; - 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; - 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; - 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 000000000000..77a772019ebe --- /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>>(self, value: T) -> Option { + TyCtxt::lift(self, value) + } + + fn mk_args_from_iter(self, iter: I) -> T::Output + where + I: Iterator, + T: ty::CollectAndApply, 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> { + TyCtxt::mk_poly_existential_predicates(self, eps) + } + + fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List> { + 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(self, iter: I) -> T::Output + where + I: Iterator, + T: ty::CollectAndApply>, + { + TyCtxt::mk_bound_variable_kinds_from_iter(self, iter) + } + + fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List> { + 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>>(self, value: T) -> Option; + + fn mk_args_from_iter(self, iter: I) -> T::Output + where + I: Iterator, + T: ty::CollectAndApply, 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>; + + fn mk_type_list(self, v: &[Ty<'tcx>]) -> &'tcx List>; + + fn lifetimes_re_erased(self) -> ty::Region<'tcx>; + + fn mk_bound_variable_kinds_from_iter(self, iter: I) -> T::Output + where + I: Iterator, + T: ty::CollectAndApply>; + + fn mk_place_elems(self, v: &[mir::PlaceElem<'tcx>]) -> &'tcx List>; + + 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 d6537d49be77..09f01d8704e2 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 18971c47831a..22eeb285b376 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 3a369f13e790..a6b77583fdcd 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 a05bae535663..141454bfe375 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 9d1440105618..7dd3c59edd05 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); diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index b4176e9c1f4d..c9b98fa4e5a9 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -429,10 +429,10 @@ pub mod __alloc_error_handler { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. #[rustc_std_internal_symbol] - static __rust_alloc_error_handler_should_panic: u8; + fn __rust_alloc_error_handler_should_panic_v2() -> u8; } - if unsafe { __rust_alloc_error_handler_should_panic != 0 } { + if unsafe { __rust_alloc_error_handler_should_panic_v2() != 0 } { panic!("memory allocation of {size} bytes failed") } else { core::panicking::panic_nounwind_fmt( diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 4e3f76de49e9..3db37f1d16f3 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -191,7 +191,7 @@ use core::error::{self, Error}; use core::fmt; use core::future::Future; use core::hash::{Hash, Hasher}; -use core::marker::{PointerLike, Tuple, Unsize}; +use core::marker::{Tuple, Unsize}; use core::mem::{self, SizedTypeProperties}; use core::ops::{ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, @@ -2132,6 +2132,3 @@ impl Error for Box { Error::provide(&**self, request); } } - -#[unstable(feature = "pointer_like_trait", issue = "none")] -impl PointerLike for Box {} diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index f416732a8d63..4290bb7a8a93 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -134,7 +134,6 @@ #![feature(panic_internals)] #![feature(pattern)] #![feature(pin_coerce_unsized_trait)] -#![feature(pointer_like_trait)] #![feature(ptr_alignment_type)] #![feature(ptr_internals)] #![feature(ptr_metadata)] diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index 2016ece007eb..99268d6182f6 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -61,4 +61,71 @@ impl bool { pub fn then T>(self, f: F) -> Option { if self { Some(f()) } else { None } } + + /// Returns `Ok(())` if the `bool` is [`true`](../std/keyword.true.html), + /// or `Err(err)` otherwise. + /// + /// Arguments passed to `ok_or` are eagerly evaluated; if you are + /// passing the result of a function call, it is recommended to use + /// [`ok_or_else`], which is lazily evaluated. + /// + /// [`ok_or_else`]: bool::ok_or_else + /// + /// # Examples + /// + /// ``` + /// #![feature(bool_to_result)] + /// + /// assert_eq!(false.ok_or(0), Err(0)); + /// assert_eq!(true.ok_or(0), Ok(())); + /// ``` + /// + /// ``` + /// #![feature(bool_to_result)] + /// + /// let mut a = 0; + /// let mut function_with_side_effects = || { a += 1; }; + /// + /// assert!(true.ok_or(function_with_side_effects()).is_ok()); + /// assert!(false.ok_or(function_with_side_effects()).is_err()); + /// + /// // `a` is incremented twice because the value passed to `ok_or` is + /// // evaluated eagerly. + /// assert_eq!(a, 2); + /// ``` + #[unstable(feature = "bool_to_result", issue = "142748")] + #[inline] + pub fn ok_or(self, err: E) -> Result<(), E> { + if self { Ok(()) } else { Err(err) } + } + + /// Returns `Ok(())` if the `bool` is [`true`](../std/keyword.true.html), + /// or `Err(f())` otherwise. + /// + /// # Examples + /// + /// ``` + /// #![feature(bool_to_result)] + /// + /// assert_eq!(false.ok_or_else(|| 0), Err(0)); + /// assert_eq!(true.ok_or_else(|| 0), Ok(())); + /// ``` + /// + /// ``` + /// #![feature(bool_to_result)] + /// + /// let mut a = 0; + /// + /// assert!(true.ok_or_else(|| { a += 1; }).is_ok()); + /// assert!(false.ok_or_else(|| { a += 1; }).is_err()); + /// + /// // `a` is incremented once because the closure is evaluated lazily by + /// // `ok_or_else`. + /// assert_eq!(a, 1); + /// ``` + #[unstable(feature = "bool_to_result", issue = "142748")] + #[inline] + pub fn ok_or_else E>(self, f: F) -> Result<(), E> { + if self { Ok(()) } else { Err(f()) } + } } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 7ce03e3d8319..dfed8a00b7d7 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -252,7 +252,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; -use crate::marker::{PhantomData, PointerLike, Unsize}; +use crate::marker::{PhantomData, Unsize}; use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; use crate::panic::const_panic; @@ -669,9 +669,6 @@ impl, U> CoerceUnsized> for Cell {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U> DispatchFromDyn> for Cell {} -#[unstable(feature = "pointer_like_trait", issue = "none")] -impl PointerLike for Cell {} - impl Cell<[T]> { /// Returns a `&[Cell]` from a `&Cell<[T]>` /// @@ -2361,9 +2358,6 @@ impl, U> CoerceUnsized> for UnsafeCell {} #[unstable(feature = "dispatch_from_dyn", issue = "none")] impl, U> DispatchFromDyn> for UnsafeCell {} -#[unstable(feature = "pointer_like_trait", issue = "none")] -impl PointerLike for UnsafeCell {} - /// [`UnsafeCell`], but [`Sync`]. /// /// This is just an `UnsafeCell`, except it implements `Sync` @@ -2470,9 +2464,6 @@ impl, U> CoerceUnsized> for SyncUnsafeCell //#[unstable(feature = "sync_unsafe_cell", issue = "95439")] impl, U> DispatchFromDyn> for SyncUnsafeCell {} -#[unstable(feature = "pointer_like_trait", issue = "none")] -impl PointerLike for SyncUnsafeCell {} - #[allow(unused)] fn assert_coerce_unsized( a: UnsafeCell<&i32>, diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 0aa8f47462db..b1ca3701fa5a 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1449,7 +1449,6 @@ pub trait PartialOrd: PartialEq + PointeeSized { /// check `==` and `<` separately to do rather than needing to calculate /// (then optimize out) the three-way `Ordering` result. #[inline] - #[must_use] // Added to improve the behaviour of tuples; not necessarily stabilization-track. #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] #[doc(hidden)] @@ -1459,7 +1458,6 @@ pub trait PartialOrd: PartialEq + PointeeSized { /// Same as `__chaining_lt`, but for `<=` instead of `<`. #[inline] - #[must_use] #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] #[doc(hidden)] fn __chaining_le(&self, other: &Rhs) -> ControlFlow { @@ -1468,7 +1466,6 @@ pub trait PartialOrd: PartialEq + PointeeSized { /// Same as `__chaining_lt`, but for `>` instead of `<`. #[inline] - #[must_use] #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] #[doc(hidden)] fn __chaining_gt(&self, other: &Rhs) -> ControlFlow { @@ -1477,7 +1474,6 @@ pub trait PartialOrd: PartialEq + PointeeSized { /// Same as `__chaining_lt`, but for `>=` instead of `<`. #[inline] - #[must_use] #[unstable(feature = "partial_ord_chaining_methods", issue = "none")] #[doc(hidden)] fn __chaining_ge(&self, other: &Rhs) -> ControlFlow { diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 67f95a02af3c..ccbd2b00cfd1 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1066,37 +1066,6 @@ pub trait Destruct {} #[rustc_do_not_implement_via_object] pub trait Tuple {} -/// A marker for pointer-like types. -/// -/// This trait can only be implemented for types that are certain to have -/// the same size and alignment as a [`usize`] or [`*const ()`](pointer). -/// To ensure this, there are special requirements on implementations -/// of `PointerLike` (other than the already-provided implementations -/// for built-in types): -/// -/// * The type must have `#[repr(transparent)]`. -/// * The type’s sole non-zero-sized field must itself implement `PointerLike`. -#[unstable(feature = "pointer_like_trait", issue = "none")] -#[lang = "pointer_like"] -#[diagnostic::on_unimplemented( - message = "`{Self}` needs to have the same ABI as a pointer", - label = "`{Self}` needs to be a pointer-like type" -)] -#[rustc_do_not_implement_via_object] -pub trait PointerLike {} - -marker_impls! { - #[unstable(feature = "pointer_like_trait", issue = "none")] - PointerLike for - isize, - usize, - {T} &T, - {T} &mut T, - {T} *const T, - {T} *mut T, - {T: PointerLike} crate::pin::Pin, -} - /// A marker for types which can be used as types of `const` generic parameters. /// /// These types must have a proper equivalence relation (`Eq`) and it must be automatically diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 93bfdbdd60b9..3cd079b84eb4 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -943,7 +943,7 @@ impl f64 { /// This returns NaN when *either* argument is NaN, as opposed to /// [`f64::max`] which only returns NaN when *both* arguments are NaN. /// - /// ```ignore-arm-unknown-linux-gnueabihf,ignore-i586 (see https://github.com/rust-lang/rust/issues/141087) + /// ``` /// #![feature(float_minimum_maximum)] /// let x = 1.0_f64; /// let y = 2.0_f64; @@ -970,7 +970,7 @@ impl f64 { /// This returns NaN when *either* argument is NaN, as opposed to /// [`f64::min`] which only returns NaN when *both* arguments are NaN. /// - /// ```ignore-arm-unknown-linux-gnueabihf,ignore-i586 (see https://github.com/rust-lang/rust/issues/141087) + /// ``` /// #![feature(float_minimum_maximum)] /// let x = 1.0_f64; /// let y = 2.0_f64; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 079032f2f96d..9cadbd47ab6a 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2572,7 +2572,7 @@ macro_rules! uint_impl { if size_of::() == 1 { // Trick LLVM into generating the psadbw instruction when SSE2 // is available and this function is autovectorized for u8's. - (self as i32).wrapping_sub(other as i32).abs() as Self + (self as i32).wrapping_sub(other as i32).unsigned_abs() as Self } else { if self < other { other - self diff --git a/library/core/src/pin/unsafe_pinned.rs b/library/core/src/pin/unsafe_pinned.rs index 17f7bcd306b0..b18b5d7c9ec0 100644 --- a/library/core/src/pin/unsafe_pinned.rs +++ b/library/core/src/pin/unsafe_pinned.rs @@ -1,5 +1,5 @@ use crate::cell::UnsafeCell; -use crate::marker::{PointerLike, Unpin}; +use crate::marker::Unpin; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::pin::Pin; use crate::{fmt, ptr}; @@ -178,8 +178,4 @@ impl, U> CoerceUnsized> for UnsafePinned // #[unstable(feature = "unsafe_pinned", issue = "125735")] impl, U> DispatchFromDyn> for UnsafePinned {} -#[unstable(feature = "pointer_like_trait", issue = "none")] -// #[unstable(feature = "unsafe_pinned", issue = "125735")] -impl PointerLike for UnsafePinned {} - // FIXME(unsafe_pinned): impl PinCoerceUnsized for UnsafePinned? diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index c26c3a32ef3a..c4ca29a36797 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1628,9 +1628,6 @@ impl DispatchFromDyn> for NonNull PinCoerceUnsized for NonNull {} -#[unstable(feature = "pointer_like_trait", issue = "none")] -impl core::marker::PointerLike for NonNull {} - #[stable(feature = "nonnull", since = "1.25.0")] impl fmt::Debug for NonNull { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/coretests/tests/bool.rs b/library/coretests/tests/bool.rs index bcd6dc2abac6..eb5f0f50663e 100644 --- a/library/coretests/tests/bool.rs +++ b/library/coretests/tests/bool.rs @@ -105,3 +105,11 @@ fn test_bool_to_option() { assert_eq!(D, Some(0)); */ } + +#[test] +fn test_bool_to_result() { + assert_eq!(false.ok_or(0), Err(0)); + assert_eq!(true.ok_or(0), Ok(())); + assert_eq!(false.ok_or_else(|| 0), Err(0)); + assert_eq!(true.ok_or_else(|| 0), Ok(())); +} diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 0c54609260ff..fdef736c0c0f 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -11,6 +11,7 @@ #![feature(async_iter_from_iter)] #![feature(async_iterator)] #![feature(bigint_helper_methods)] +#![feature(bool_to_result)] #![feature(bstr)] #![feature(cfg_target_has_reliable_f16_f128)] #![feature(char_max_len)] diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index b574e9f3a25e..1d61630269ac 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -349,10 +349,10 @@ fn default_alloc_error_hook(layout: Layout) { // This symbol is emitted by rustc next to __rust_alloc_error_handler. // Its value depends on the -Zoom={panic,abort} compiler option. #[rustc_std_internal_symbol] - static __rust_alloc_error_handler_should_panic: u8; + fn __rust_alloc_error_handler_should_panic_v2() -> u8; } - if unsafe { __rust_alloc_error_handler_should_panic != 0 } { + if unsafe { __rust_alloc_error_handler_should_panic_v2() != 0 } { panic!("memory allocation of {} bytes failed", layout.size()); } else { // This is the default path taken on OOM, and the only path taken on stable with std. diff --git a/library/std/src/sys/net/connection/uefi/mod.rs b/library/std/src/sys/net/connection/uefi/mod.rs index 46d67c8e5101..2d465bd0efaa 100644 --- a/library/std/src/sys/net/connection/uefi/mod.rs +++ b/library/std/src/sys/net/connection/uefi/mod.rs @@ -7,7 +7,7 @@ use crate::time::Duration; mod tcp; pub(crate) mod tcp4; -pub struct TcpStream(#[expect(dead_code)] tcp::Tcp); +pub struct TcpStream(tcp::Tcp); impl TcpStream { pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result { @@ -54,12 +54,13 @@ impl TcpStream { false } - pub fn write(&self, _: &[u8]) -> io::Result { - unsupported() + pub fn write(&self, buf: &[u8]) -> io::Result { + self.0.write(buf) } - pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result { - unsupported() + pub fn write_vectored(&self, buf: &[IoSlice<'_>]) -> io::Result { + // FIXME: UEFI does support vectored write, so implement that. + crate::io::default_write_vectored(|b| self.write(b), buf) } pub fn is_write_vectored(&self) -> bool { diff --git a/library/std/src/sys/net/connection/uefi/tcp.rs b/library/std/src/sys/net/connection/uefi/tcp.rs index f87accdc41de..9c3462e3468c 100644 --- a/library/std/src/sys/net/connection/uefi/tcp.rs +++ b/library/std/src/sys/net/connection/uefi/tcp.rs @@ -3,7 +3,7 @@ use crate::io; use crate::net::SocketAddr; pub(crate) enum Tcp { - V4(#[expect(dead_code)] tcp4::Tcp4), + V4(tcp4::Tcp4), } impl Tcp { @@ -18,4 +18,10 @@ impl Tcp { SocketAddr::V6(_) => todo!(), } } + + pub(crate) fn write(&self, buf: &[u8]) -> io::Result { + match self { + Self::V4(client) => client.write(buf), + } + } } diff --git a/library/std/src/sys/net/connection/uefi/tcp4.rs b/library/std/src/sys/net/connection/uefi/tcp4.rs index f7ca373b52b5..d0f0d27d975f 100644 --- a/library/std/src/sys/net/connection/uefi/tcp4.rs +++ b/library/std/src/sys/net/connection/uefi/tcp4.rs @@ -88,6 +88,46 @@ impl Tcp4 { } } + pub(crate) fn write(&self, buf: &[u8]) -> io::Result { + let evt = unsafe { self.create_evt() }?; + let completion_token = + tcp4::CompletionToken { event: evt.as_ptr(), status: Status::SUCCESS }; + let data_len = u32::try_from(buf.len()).unwrap_or(u32::MAX); + + let fragment = tcp4::FragmentData { + fragment_length: data_len, + fragment_buffer: buf.as_ptr().cast::().cast_mut(), + }; + let mut tx_data = tcp4::TransmitData { + push: r_efi::efi::Boolean::FALSE, + urgent: r_efi::efi::Boolean::FALSE, + data_length: data_len, + fragment_count: 1, + fragment_table: [fragment], + }; + + let protocol = self.protocol.as_ptr(); + let mut token = tcp4::IoToken { + completion_token, + packet: tcp4::IoTokenPacket { + tx_data: (&raw mut tx_data).cast::>(), + }, + }; + + let r = unsafe { ((*protocol).transmit)(protocol, &mut token) }; + if r.is_error() { + return Err(io::Error::from_raw_os_error(r.as_usize())); + } + + self.wait_for_flag(); + + if completion_token.status.is_error() { + Err(io::Error::from_raw_os_error(completion_token.status.as_usize())) + } else { + Ok(data_len as usize) + } + } + unsafe fn create_evt(&self) -> io::Result { self.flag.store(false, Ordering::Relaxed); helpers::OwnedEvent::new( diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs index 882fcd087800..f67569d14860 100644 --- a/src/bootstrap/src/core/build_steps/clean.rs +++ b/src/bootstrap/src/core/build_steps/clean.rs @@ -181,7 +181,7 @@ fn rm_rf(path: &Path) { panic!("failed to get metadata for file {}: {}", path.display(), e); } Ok(metadata) => { - if metadata.file_type().is_file() || metadata.file_type().is_symlink() { + if !metadata.file_type().is_dir() { do_op(path, "remove file", |p| match fs::remove_file(p) { #[cfg(windows)] Err(e) diff --git a/src/doc/rustc-dev-guide/josh-sync.toml b/src/doc/rustc-dev-guide/josh-sync.toml new file mode 100644 index 000000000000..7882051e2339 --- /dev/null +++ b/src/doc/rustc-dev-guide/josh-sync.toml @@ -0,0 +1,3 @@ +org = "rust-lang" +repo = "rustc-dev-guide" +path = "src/doc/rustc-dev-guide" diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 30ba3070e1f4..e444613e6311 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -d1d8e386c5e84c4ba857f56c3291f73c27e2d62a +c96a69059ecc618b519da385a6ccd03155aa0237 diff --git a/src/doc/rustc-dev-guide/src/autodiff/internals.md b/src/doc/rustc-dev-guide/src/autodiff/internals.md index 0093ef044c80..c1b31a0e4bd2 100644 --- a/src/doc/rustc-dev-guide/src/autodiff/internals.md +++ b/src/doc/rustc-dev-guide/src/autodiff/internals.md @@ -2,11 +2,11 @@ The `std::autodiff` module in Rust allows differentiable programming: ```rust #![feature(autodiff)] -use std::autodiff::autodiff; +use std::autodiff::*; // f(x) = x * x, f'(x) = 2.0 * x // bar therefore returns (x * x, 2.0 * x) -#[autodiff(bar, Reverse, Active, Active)] +#[autodiff_reverse(bar, Active, Active)] fn foo(x: f32) -> f32 { x * x } fn main() { diff --git a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md index c4783002b85a..d29cd1448102 100644 --- a/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md +++ b/src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md @@ -2,6 +2,24 @@ +
+ +For `profile = "library"` users, or users who use `download-rustc = true | "if-unchanged"`, please be advised that +the `./x test library/std` flow where `download-rustc` is active (i.e. no compiler changes) is currently broken. +This is tracked in . Only the `./x test` flow is affected in this +case, `./x {check,build} library/std` should still work. + +In the short-term, you may need to disable `download-rustc` for `./x test library/std`. This can be done either by: + +1. `./x test library/std --set rust.download-rustc=false` +2. Or set `rust.download-rustc=false` in `bootstrap.toml`. + +Unfortunately that will require building the stage 1 compiler. The bootstrap team is working on this, but +implementing a maintainable fix is taking some time. + +
+ + The compiler is built using a tool called `x.py`. You will need to have Python installed to run it. diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md index 46d74b967342..b3fcd79ec818 100644 --- a/src/doc/rustc-dev-guide/src/contributing.md +++ b/src/doc/rustc-dev-guide/src/contributing.md @@ -434,6 +434,10 @@ Just a few things to keep in mind: it might benefit from having a Table of Contents at the beginning, which you can auto-generate by including the `` marker at the top. +#### ⚠️ Note: Where to contribute `rustc-dev-guide` changes + +For detailed information about where to contribute rustc-dev-guide changes and the benefits of doing so, see [the rustc-dev-guide working group documentation](https://forge.rust-lang.org/wg-rustc-dev-guide/index.html#where-to-contribute-rustc-dev-guide-changes). + ## Issue triage Please see . diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index e01b8f2f1356..4e5c3413cb8a 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -1,14 +1,18 @@ # Diagnostic and subdiagnostic structs rustc has three diagnostic traits that can be used to create diagnostics: -`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`. For simple diagnostics, -instead of using the `Diag` API to create and emit diagnostics, -derived impls can be used. They are only suitable for simple diagnostics that +`Diagnostic`, `LintDiagnostic`, and `Subdiagnostic`. + +For simple diagnostics, +derived impls can be used, e.g. `#[derive(Diagnostic)]`. They are only suitable for simple diagnostics that don't require much logic in deciding whether or not to add additional subdiagnostics. -Such diagnostic can be translated into -different languages and each has a slug that uniquely identifies the -diagnostic. +In cases where diagnostics require more complex or dynamic behavior, such as conditionally adding subdiagnostics, +customizing the rendering logic, or selecting messages at runtime, you will need to manually implement +the corresponding trait (`Diagnostic`, `LintDiagnostic`, or `Subdiagnostic`). +This approach provides greater flexibility and is recommended for diagnostics that go beyond simple, static structures. + +Diagnostic can be translated into different languages and each has a slug that uniquely identifies the diagnostic. ## `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` @@ -142,7 +146,7 @@ tcx.dcx().emit_err(FieldAlreadyDeclared { }); ``` -### Reference +### Reference for `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` `#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the following attributes: @@ -330,7 +334,34 @@ function ([example][subdiag_use_1] and [example][subdiag_use_2]) on a diagnostic or by assigning it to a `#[subdiagnostic]`-annotated field of a diagnostic struct. -### Reference +### Argument sharing and isolation + +Subdiagnostics add their own arguments (i.e., certain fields in their structure) to the `Diag` structure before rendering the information. +`Diag` structure also stores the arguments from the main diagnostic, so the subdiagnostic can also use the arguments from the main diagnostic. + +However, when a subdiagnostic is added to a main diagnostic by implementing `#[derive(Subdiagnostic)]`, +the following rules, introduced in [rust-lang/rust#142724](https://github.com/rust-lang/rust/pull/142724) +apply to the handling of arguments (i.e., variables used in Fluent messages): + +**Argument isolation between sub diagnostics**: +Arguments set by a subdiagnostic are only available during the rendering of that subdiagnostic. +After the subdiagnostic is rendered, all arguments it introduced are restored from the main diagnostic. +This ensures that multiple subdiagnostics do not pollute each other's argument scope. +For example, when using a `Vec`, it iteratively adds the same argument over and over again. + +**Same argument override between sub and main diagnostics**: +If a subdiagnostic sets a argument with the same name as a arguments already in the main diagnostic, +it will report an error at runtime unless both have exactly the same value. +It has two benefits: +- preserves the flexibility that arguments in the main diagnostic are allowed to appear in the attributes of the subdiagnostic. +For example, There is an attribute `#[suggestion(code = "{new_vis}")]` in the subdiagnostic, but `new_vis` is the field in the main diagnostic struct. +- prevents accidental overwriting or deletion of arguments required by the main diagnostic or other subdiagnostics. + +These rules guarantee that arguments injected by subdiagnostics are strictly scoped to their own rendering. +The main diagnostic's arguments remain unaffected by subdiagnostic logic, even in the presence of name collisions. +Additionally, subdiagnostics can access arguments from the main diagnostic with the same name when needed. + +### Reference for `#[derive(Subdiagnostic)]` `#[derive(Subdiagnostic)]` supports the following attributes: - `#[label(slug)]`, `#[help(slug)]`, `#[warning(slug)]` or `#[note(slug)]` diff --git a/src/doc/rustc-dev-guide/src/hir/lowering.md b/src/doc/rustc-dev-guide/src/hir/lowering.md index 02c69b8609f1..c0057a69c10d 100644 --- a/src/doc/rustc-dev-guide/src/hir/lowering.md +++ b/src/doc/rustc-dev-guide/src/hir/lowering.md @@ -7,10 +7,8 @@ of such structures include but are not limited to * Parenthesis * Removed without replacement, the tree structure makes order explicit -* `for` loops and `while (let)` loops - * Converted to `loop` + `match` and some `let` bindings -* `if let` - * Converted to `match` +* `for` loops + * Converted to `match` + `loop` + `match` * Universal `impl Trait` * Converted to generic arguments (but with some flags, to know that the user didn't write them) diff --git a/src/doc/rustc-dev-guide/src/solve/opaque-types.md b/src/doc/rustc-dev-guide/src/solve/opaque-types.md index 6898ef3aa780..8880962d621f 100644 --- a/src/doc/rustc-dev-guide/src/solve/opaque-types.md +++ b/src/doc/rustc-dev-guide/src/solve/opaque-types.md @@ -56,7 +56,7 @@ Finally, we check whether the item bounds of the opaque hold for the expected ty [source][item-bounds-ck]. [norm]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L13 -[coherence-example]: https://github.com/rust-lang/rust/blob/master/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs +[coherence-example]: https://github.com/rust-lang/rust/blob/master/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.rs [placeholder-ck]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L33 [check-storage]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L51-L52 [eq-prev]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L51-L59 diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md index f7e62e1eccf6..4fce5838b6e7 100644 --- a/src/doc/rustc-dev-guide/src/tests/ui.md +++ b/src/doc/rustc-dev-guide/src/tests/ui.md @@ -453,9 +453,9 @@ even run the resulting program. Just add one of the following - `//@ check-fail` — compilation should fail (the codegen phase is skipped). This is the default for UI tests. - `//@ build-fail` — compilation should fail during the codegen phase. - This will run `rustc` twice, once to verify that it compiles successfully - without the codegen phase, then a second time the full compile should - fail. + This will run `rustc` twice: + - First time is to ensure that the compile succeeds without the codegen phase + - Second time is to ensure that the full compile fails - `//@ run-fail` — compilation should succeed, but running the resulting binary should fail. diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index c9530216968b..de920469fdca 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -621,7 +621,7 @@ impl Item { } pub(crate) fn is_non_exhaustive(&self) -> bool { - self.attrs.other_attrs.iter().any(|a| a.has_name(sym::non_exhaustive)) + find_attr!(&self.attrs.other_attrs, AttributeKind::NonExhaustive(..)) } /// Returns a documentation-level item type from the item. @@ -647,7 +647,20 @@ impl Item { ) -> hir::FnHeader { let sig = tcx.fn_sig(def_id).skip_binder(); let constness = if tcx.is_const_fn(def_id) { - hir::Constness::Const + // rustc's `is_const_fn` returns `true` for associated functions that have an `impl const` parent + // or that have a `#[const_trait]` parent. Do not display those as `const` in rustdoc because we + // won't be printing correct syntax plus the syntax is unstable. + match tcx.opt_associated_item(def_id) { + Some(ty::AssocItem { + container: ty::AssocItemContainer::Impl, + trait_item_def_id: Some(_), + .. + }) + | Some(ty::AssocItem { container: ty::AssocItemContainer::Trait, .. }) => { + hir::Constness::NotConst + } + None | Some(_) => hir::Constness::Const, + } } else { hir::Constness::NotConst }; @@ -763,6 +776,8 @@ impl Item { } else if let hir::Attribute::Parsed(AttributeKind::ExportName { name, .. }) = attr { Some(format!("#[export_name = \"{name}\"]")) + } else if let hir::Attribute::Parsed(AttributeKind::NonExhaustive(..)) = attr { + Some("#[non_exhaustive]".to_string()) } else if is_json { match attr { // rustdoc-json stores this in `Item::deprecation`, so we diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs index 86d9038ec45d..7dda3e0fdb91 100644 --- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs +++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs @@ -4,7 +4,9 @@ use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::declare_lint_pass; -use rustc_span::sym; +use rustc_attr_data_structures::AttributeKind; +use rustc_attr_data_structures::find_attr; + declare_clippy_lint! { /// ### What it does @@ -85,7 +87,7 @@ impl LateLintPass<'_> for ExhaustiveItems { }; if cx.effective_visibilities.is_exported(item.owner_id.def_id) && let attrs = cx.tcx.hir_attrs(item.hir_id()) - && !attrs.iter().any(|a| a.has_name(sym::non_exhaustive)) + && !find_attr!(attrs, AttributeKind::NonExhaustive(..)) && fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public()) { span_lint_and_then(cx, lint, item.span, msg, |diag| { diff --git a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs index 3562b1ff5cce..51696b388800 100644 --- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs +++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs @@ -4,7 +4,6 @@ use clippy_utils::is_doc_hidden; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_indent; use itertools::Itertools; -use rustc_ast::attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -12,7 +11,9 @@ use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::impl_lint_pass; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, sym}; +use rustc_span::Span; +use rustc_attr_data_structures::find_attr; +use rustc_attr_data_structures::AttributeKind; declare_clippy_lint! { /// ### What it does @@ -93,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { .then_some((v.def_id, v.span)) }); if let Ok((id, span)) = iter.exactly_one() - && !attr::contains_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive) + && !find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::NonExhaustive(..)) { self.potential_enums.push((item.owner_id.def_id, id, item.span, span)); } @@ -113,10 +114,10 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustive { item.span, "this seems like a manual implementation of the non-exhaustive pattern", |diag| { - if let Some(non_exhaustive) = - attr::find_by_name(cx.tcx.hir_attrs(item.hir_id()), sym::non_exhaustive) + if let Some(non_exhaustive_span) = + find_attr!(cx.tcx.hir_attrs(item.hir_id()), AttributeKind::NonExhaustive(span) => *span) { - diag.span_note(non_exhaustive.span(), "the struct is already non-exhaustive"); + diag.span_note(non_exhaustive_span, "the struct is already non-exhaustive"); } else { let indent = snippet_indent(cx, item.span).unwrap_or_default(); diag.span_suggestion_verbose( diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index d9dda6eadb2a..22fd15d153ab 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -130,7 +130,7 @@ impl LateLintPass<'_> for WildcardImports { } if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind && (self.warn_on_all || !self.check_exceptions(cx, item, use_path.segments)) - && let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id) + && let Some(used_imports) = cx.tcx.resolutions(()).glob_map.get(&item.owner_id.def_id) && !used_imports.is_empty() // Already handled by `unused_imports` && !used_imports.contains(&kw::Underscore) { diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index 8a0ff5323c98..4c7a589e185b 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -7,9 +7,10 @@ use rustc_middle::ty::{AdtDef, TyCtxt}; use rustc_session::Session; use rustc_span::{Span, Symbol}; use std::str::FromStr; - +use rustc_attr_data_structures::find_attr; use crate::source::SpanRangeExt; use crate::{sym, tokenize_with_text}; +use rustc_attr_data_structures::AttributeKind; /// Deprecation status of attributes known by Clippy. pub enum DeprecationStatus { @@ -165,13 +166,13 @@ pub fn is_doc_hidden(attrs: &[impl AttributeExt]) -> bool { pub fn has_non_exhaustive_attr(tcx: TyCtxt<'_>, adt: AdtDef<'_>) -> bool { adt.is_variant_list_non_exhaustive() - || tcx.has_attr(adt.did(), sym::non_exhaustive) + || find_attr!(tcx.get_all_attrs(adt.did()), AttributeKind::NonExhaustive(..)) || adt.variants().iter().any(|variant_def| { - variant_def.is_field_list_non_exhaustive() || tcx.has_attr(variant_def.def_id, sym::non_exhaustive) + variant_def.is_field_list_non_exhaustive() || find_attr!(tcx.get_all_attrs(variant_def.def_id), AttributeKind::NonExhaustive(..)) }) || adt .all_fields() - .any(|field_def| tcx.has_attr(field_def.did, sym::non_exhaustive)) + .any(|field_def| find_attr!(tcx.get_all_attrs(field_def.did), AttributeKind::NonExhaustive(..))) } /// Checks if the given span contains a `#[cfg(..)]` attribute diff --git a/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr b/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr index f3aca6854174..9d6538112bf0 100644 --- a/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr +++ b/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr @@ -3,8 +3,8 @@ error: casting to the same type is unnecessary (`u32` -> `u32`) | LL | let b = a as u32; | ^^^^^^^^ help: try: `a` --Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs:LL:CC | + = note: -Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs:LL:CC = note: `-D clippy::unnecessary-cast` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]` @@ -15,8 +15,8 @@ LL | let d = 42; | ----------- unnecessary `let` binding LL | d | ^ --Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/returns.rs:LL:CC | + = note: -Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/returns.rs:LL:CC = note: `-D clippy::let-and-return` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::let_and_return)]` help: return the expression directly diff --git a/src/tools/clippy/tests/ui/track-diagnostics.rs b/src/tools/clippy/tests/ui/track-diagnostics.rs index 723ea23e9a63..0fbde867390d 100644 --- a/src/tools/clippy/tests/ui/track-diagnostics.rs +++ b/src/tools/clippy/tests/ui/track-diagnostics.rs @@ -8,5 +8,6 @@ struct A; struct B; const S: A = B; //~^ ERROR: mismatched types +//~| NOTE: created at fn main() {} diff --git a/src/tools/clippy/tests/ui/track-diagnostics.stderr b/src/tools/clippy/tests/ui/track-diagnostics.stderr index 83451fb658d0..45262ba618f2 100644 --- a/src/tools/clippy/tests/ui/track-diagnostics.stderr +++ b/src/tools/clippy/tests/ui/track-diagnostics.stderr @@ -3,7 +3,8 @@ error[E0308]: mismatched types | LL | const S: A = B; | ^ expected `A`, found `B` --Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC + | + = note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC error: aborting due to 1 previous error diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 5a4378e78f91..0130cf13a45f 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -837c5dd7de03aa97190593aef4e70d53e1bb574b +733b47ea4b1b86216f14ef56e49440c33933f230 diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs index 5cf9265c7040..49c0c380a08a 100644 --- a/src/tools/miri/src/shims/extern_static.rs +++ b/src/tools/miri/src/shims/extern_static.rs @@ -1,7 +1,5 @@ //! Provides the `extern static` that this platform expects. -use rustc_symbol_mangling::mangle_internal_symbol; - use crate::*; impl<'tcx> MiriMachine<'tcx> { @@ -45,15 +43,6 @@ impl<'tcx> MiriMachine<'tcx> { /// Sets up the "extern statics" for this machine. pub fn init_extern_statics(ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx> { - // "__rust_alloc_error_handler_should_panic" - let val = ecx.tcx.sess.opts.unstable_opts.oom.should_panic(); - let val = ImmTy::from_int(val, ecx.machine.layouts.u8); - Self::alloc_extern_static( - ecx, - &mangle_internal_symbol(*ecx.tcx, "__rust_alloc_error_handler_should_panic"), - val, - )?; - if ecx.target_os_is_unix() { // "environ" is mandated by POSIX. let environ = ecx.machine.env_vars.unix().environ(); diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 97070eb742f3..9ddba8c2b48d 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -615,6 +615,14 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // This is a no-op shim that only exists to prevent making the allocator shims instantly stable. let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; } + name if name + == this.mangle_internal_symbol("__rust_alloc_error_handler_should_panic_v2") => + { + // Gets the value of the `oom` option. + let [] = this.check_shim(abi, CanonAbi::Rust, link_name, args)?; + let val = this.tcx.sess.opts.unstable_opts.oom.should_panic(); + this.write_int(val, dest)?; + } // C memory handling functions "memcmp" => { diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.rs b/src/tools/miri/tests/pass/alloc-access-tracking.rs index c47063bef03c..0e88951dc43f 100644 --- a/src/tools/miri/tests/pass/alloc-access-tracking.rs +++ b/src/tools/miri/tests/pass/alloc-access-tracking.rs @@ -1,7 +1,7 @@ #![no_std] #![no_main] -//@compile-flags: -Zmiri-track-alloc-id=21 -Zmiri-track-alloc-accesses -Cpanic=abort -//@normalize-stderr-test: "id 21" -> "id $$ALLOC" +//@compile-flags: -Zmiri-track-alloc-id=20 -Zmiri-track-alloc-accesses -Cpanic=abort +//@normalize-stderr-test: "id 20" -> "id $$ALLOC" //@only-target: linux # alloc IDs differ between OSes (due to extern static allocations) extern "Rust" { diff --git a/tests/mir-opt/gvn_const_eval_polymorphic.no_optimize.GVN.diff b/tests/mir-opt/gvn_const_eval_polymorphic.no_optimize.GVN.diff new file mode 100644 index 000000000000..a91561ba304b --- /dev/null +++ b/tests/mir-opt/gvn_const_eval_polymorphic.no_optimize.GVN.diff @@ -0,0 +1,12 @@ +- // MIR for `no_optimize` before GVN ++ // MIR for `no_optimize` after GVN + + fn no_optimize() -> bool { + let mut _0: bool; + + bb0: { + _0 = Eq(const no_optimize::::{constant#0}, const no_optimize::::{constant#1}); + return; + } + } + diff --git a/tests/mir-opt/gvn_const_eval_polymorphic.optimize_false.GVN.diff b/tests/mir-opt/gvn_const_eval_polymorphic.optimize_false.GVN.diff new file mode 100644 index 000000000000..bdfa2987b23c --- /dev/null +++ b/tests/mir-opt/gvn_const_eval_polymorphic.optimize_false.GVN.diff @@ -0,0 +1,13 @@ +- // MIR for `optimize_false` before GVN ++ // MIR for `optimize_false` after GVN + + fn optimize_false() -> bool { + let mut _0: bool; + + bb0: { +- _0 = Eq(const optimize_false::::{constant#0}, const optimize_false::::{constant#1}); ++ _0 = const false; + return; + } + } + diff --git a/tests/mir-opt/gvn_const_eval_polymorphic.optimize_true.GVN.diff b/tests/mir-opt/gvn_const_eval_polymorphic.optimize_true.GVN.diff new file mode 100644 index 000000000000..dc337d43fb04 --- /dev/null +++ b/tests/mir-opt/gvn_const_eval_polymorphic.optimize_true.GVN.diff @@ -0,0 +1,13 @@ +- // MIR for `optimize_true` before GVN ++ // MIR for `optimize_true` after GVN + + fn optimize_true() -> bool { + let mut _0: bool; + + bb0: { +- _0 = Eq(const optimize_true::::{constant#0}, const optimize_true::::{constant#1}); ++ _0 = const true; + return; + } + } + diff --git a/tests/mir-opt/gvn_const_eval_polymorphic.rs b/tests/mir-opt/gvn_const_eval_polymorphic.rs new file mode 100644 index 000000000000..7320ad947ff2 --- /dev/null +++ b/tests/mir-opt/gvn_const_eval_polymorphic.rs @@ -0,0 +1,57 @@ +//@ test-mir-pass: GVN +//@ compile-flags: --crate-type lib + +//! Regressions test for a mis-optimization where some functions +//! (`type_id` / `type_name` / `needs_drop`) could be evaluated in +//! a generic context, even though their value depends on some type +//! parameter `T`. +//! +//! In particular, `type_name_of_val(&generic::)` was incorrectly +//! evaluated to the string "crate_name::generic::", and +//! `no_optimize` was incorrectly optimized to `false`. + +#![feature(const_type_name)] + +fn generic() {} + +const fn type_name_contains_i32(_: &T) -> bool { + let pattern = b"i32"; + let name = std::any::type_name::().as_bytes(); + let mut i = 0; + 'outer: while i < name.len() - pattern.len() + 1 { + let mut j = 0; + while j < pattern.len() { + if name[i + j] != pattern[j] { + i += 1; + continue 'outer; + } + j += 1; + } + return true; + } + false +} + +// EMIT_MIR gvn_const_eval_polymorphic.optimize_true.GVN.diff +fn optimize_true() -> bool { + // CHECK-LABEL: fn optimize_true( + // CHECK: _0 = const true; + // CHECK-NEXT: return; + (const { type_name_contains_i32(&generic::) }) == const { true } +} + +// EMIT_MIR gvn_const_eval_polymorphic.optimize_false.GVN.diff +fn optimize_false() -> bool { + // CHECK-LABEL: fn optimize_false( + // CHECK: _0 = const false; + // CHECK-NEXT: return; + (const { type_name_contains_i32(&generic::) }) == const { true } +} + +// EMIT_MIR gvn_const_eval_polymorphic.no_optimize.GVN.diff +fn no_optimize() -> bool { + // CHECK-LABEL: fn no_optimize( + // CHECK: _0 = Eq(const no_optimize::::{constant#0}, const no_optimize::::{constant#1}); + // CHECK-NEXT: return; + (const { type_name_contains_i32(&generic::) }) == const { true } +} diff --git a/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff b/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff deleted file mode 100644 index 2f83f54d2afd..000000000000 --- a/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff +++ /dev/null @@ -1,12 +0,0 @@ -- // MIR for `cursed_is_i32` before GVN -+ // MIR for `cursed_is_i32` after GVN - - fn cursed_is_i32() -> bool { - let mut _0: bool; - - bb0: { - _0 = Eq(const cursed_is_i32::::{constant#0}, const cursed_is_i32::::{constant#1}); - return; - } - } - diff --git a/tests/mir-opt/gvn_type_id_polymorphic.rs b/tests/mir-opt/gvn_type_id_polymorphic.rs deleted file mode 100644 index 39bc5c24ecc6..000000000000 --- a/tests/mir-opt/gvn_type_id_polymorphic.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ test-mir-pass: GVN -//@ compile-flags: -C opt-level=2 - -#![feature(core_intrinsics)] - -fn generic() {} - -const fn type_id_of_val(_: &T) -> u128 { - std::intrinsics::type_id::() -} - -// EMIT_MIR gvn_type_id_polymorphic.cursed_is_i32.GVN.diff -fn cursed_is_i32() -> bool { - // CHECK-LABEL: fn cursed_is_i32( - // CHECK: _0 = Eq(const cursed_is_i32::::{constant#0}, const cursed_is_i32::::{constant#1}); - // CHECK-NEXT: return; - (const { type_id_of_val(&generic::) } == const { type_id_of_val(&generic::) }) -} - -fn main() { - dbg!(cursed_is_i32::()); -} diff --git a/tests/rustdoc-ui/track-diagnostics.rs b/tests/rustdoc-ui/track-diagnostics.rs index d18d26bf7943..f8e710659a5c 100644 --- a/tests/rustdoc-ui/track-diagnostics.rs +++ b/tests/rustdoc-ui/track-diagnostics.rs @@ -1,5 +1,4 @@ //@ compile-flags: -Z track-diagnostics -//@ error-pattern: created at // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. @@ -8,4 +7,7 @@ struct A; struct B; -pub const S: A = B; //~ ERROR mismatched types +pub const S: A = B; +//~^ ERROR mismatched types +//~| NOTE created at +//~| NOTE expected `A`, found `B` diff --git a/tests/rustdoc-ui/track-diagnostics.stderr b/tests/rustdoc-ui/track-diagnostics.stderr index fb0d7b866449..a25fd2862aaf 100644 --- a/tests/rustdoc-ui/track-diagnostics.stderr +++ b/tests/rustdoc-ui/track-diagnostics.stderr @@ -3,7 +3,8 @@ error[E0308]: mismatched types | LL | pub const S: A = B; | ^ expected `A`, found `B` --Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC + | + = note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC error: aborting due to 1 previous error diff --git a/tests/rustdoc/constant/const-trait-and-impl-methods.rs b/tests/rustdoc/constant/const-trait-and-impl-methods.rs new file mode 100644 index 000000000000..30fc539e5533 --- /dev/null +++ b/tests/rustdoc/constant/const-trait-and-impl-methods.rs @@ -0,0 +1,36 @@ +// check that we don't render `#[const_trait]` methods as `const` - even for +// const `trait`s and `impl`s. +#![crate_name = "foo"] +#![feature(const_trait_impl)] + +//@ has foo/trait.Tr.html +//@ has - '//*[@id="tymethod.required"]' 'fn required()' +//@ !has - '//*[@id="tymethod.required"]' 'const' +//@ has - '//*[@id="method.defaulted"]' 'fn defaulted()' +//@ !has - '//*[@id="method.defaulted"]' 'const' +#[const_trait] +pub trait Tr { + fn required(); + fn defaulted() {} +} + +pub struct ConstImpl {} +pub struct NonConstImpl {} + +//@ has foo/struct.ConstImpl.html +//@ has - '//*[@id="method.required"]' 'fn required()' +//@ !has - '//*[@id="method.required"]' 'const' +//@ has - '//*[@id="method.defaulted"]' 'fn defaulted()' +//@ !has - '//*[@id="method.defaulted"]' 'const' +impl const Tr for ConstImpl { + fn required() {} +} + +//@ has foo/struct.NonConstImpl.html +//@ has - '//*[@id="method.required"]' 'fn required()' +//@ !has - '//*[@id="method.required"]' 'const' +//@ has - '//*[@id="method.defaulted"]' 'fn defaulted()' +//@ !has - '//*[@id="method.defaulted"]' 'const' +impl Tr for NonConstImpl { + fn required() {} +} diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index c65eff8a550e..32b0ddf87ba4 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -65,12 +65,6 @@ error: malformed `no_sanitize` attribute input LL | #[no_sanitize] | ^^^^^^^^^^^^^^ help: must be of the form: `#[no_sanitize(address, kcfi, memory, thread)]` -error: malformed `no_implicit_prelude` attribute input - --> $DIR/malformed-attrs.rs:96:1 - | -LL | #[no_implicit_prelude = 23] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[no_implicit_prelude]` - error: malformed `proc_macro` attribute input --> $DIR/malformed-attrs.rs:98:1 | @@ -212,12 +206,6 @@ error: malformed `automatically_derived` attribute input LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[automatically_derived]` -error: malformed `non_exhaustive` attribute input - --> $DIR/malformed-attrs.rs:196:1 - | -LL | #[non_exhaustive = 1] - | ^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]` - error: malformed `thread_local` attribute input --> $DIR/malformed-attrs.rs:202:1 | @@ -514,6 +502,15 @@ error[E0539]: malformed `link_section` attribute input LL | #[link_section] | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]` +error[E0565]: malformed `no_implicit_prelude` attribute input + --> $DIR/malformed-attrs.rs:96:1 + | +LL | #[no_implicit_prelude = 23] + | ^^^^^^^^^^^^^^^^^^^^^^----^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[no_implicit_prelude]` + error[E0539]: malformed `must_use` attribute input --> $DIR/malformed-attrs.rs:118:1 | @@ -549,6 +546,15 @@ LL | #[rustc_layout_scalar_valid_range_end] | expected this to be a list | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]` +error[E0565]: malformed `non_exhaustive` attribute input + --> $DIR/malformed-attrs.rs:196:1 + | +LL | #[non_exhaustive = 1] + | ^^^^^^^^^^^^^^^^^---^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[non_exhaustive]` + error: attribute should be applied to `const fn` --> $DIR/malformed-attrs.rs:34:1 | diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr index feae8528cf7a..eff478d04aee 100644 --- a/tests/ui/lint/unused/unused-attr-duplicate.stderr +++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr @@ -65,18 +65,6 @@ LL | #[should_panic] | ^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:66:1 - | -LL | #[non_exhaustive] - | ^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:65:1 - | -LL | #[non_exhaustive] - | ^^^^^^^^^^^^^^^^^ - error: unused attribute --> $DIR/unused-attr-duplicate.rs:70:1 | @@ -140,18 +128,6 @@ note: attribute also specified here LL | #![no_std] | ^^^^^^^^^^ -error: unused attribute - --> $DIR/unused-attr-duplicate.rs:25:1 - | -LL | #![no_implicit_prelude] - | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute - | -note: attribute also specified here - --> $DIR/unused-attr-duplicate.rs:24:1 - | -LL | #![no_implicit_prelude] - | ^^^^^^^^^^^^^^^^^^^^^^^ - error: unused attribute --> $DIR/unused-attr-duplicate.rs:27:1 | @@ -202,6 +178,18 @@ LL | #[must_use] | ^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:66:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:65:1 + | +LL | #[non_exhaustive] + | ^^^^^^^^^^^^^^^^^ + error: unused attribute --> $DIR/unused-attr-duplicate.rs:74:1 | @@ -302,5 +290,17 @@ LL | #[link_section = ".bss"] | ^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +error: unused attribute + --> $DIR/unused-attr-duplicate.rs:25:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/unused-attr-duplicate.rs:24:1 + | +LL | #![no_implicit_prelude] + | ^^^^^^^^^^^^^^^^^^^^^^^ + error: aborting due to 24 previous errors diff --git a/tests/ui/parser/macro/bad-macro-definition.rs b/tests/ui/parser/macro/bad-macro-definition.rs new file mode 100644 index 000000000000..3c5c93ea3b3e --- /dev/null +++ b/tests/ui/parser/macro/bad-macro-definition.rs @@ -0,0 +1,22 @@ +#![crate_type = "lib"] + +macro_rules! a { {} => } +//~^ ERROR: macro definition ended unexpectedly + +macro_rules! b { 0 => } +//~^ ERROR: macro definition ended unexpectedly +//~| ERROR: invalid macro matcher + +macro_rules! c { x => } +//~^ ERROR: macro definition ended unexpectedly +//~| ERROR: invalid macro matcher + +macro_rules! d { _ => } +//~^ ERROR: macro definition ended unexpectedly +//~| ERROR: invalid macro matcher + +macro_rules! e { {} } +//~^ ERROR: expected `=>`, found end of macro arguments + +macro_rules! f {} +//~^ ERROR: macros must contain at least one rule diff --git a/tests/ui/parser/macro/bad-macro-definition.stderr b/tests/ui/parser/macro/bad-macro-definition.stderr new file mode 100644 index 000000000000..de6d9d6a38b1 --- /dev/null +++ b/tests/ui/parser/macro/bad-macro-definition.stderr @@ -0,0 +1,56 @@ +error: macro definition ended unexpectedly + --> $DIR/bad-macro-definition.rs:3:23 + | +LL | macro_rules! a { {} => } + | ^ expected right-hand side of macro rule + +error: invalid macro matcher; matchers must be contained in balanced delimiters + --> $DIR/bad-macro-definition.rs:6:18 + | +LL | macro_rules! b { 0 => } + | ^ + +error: macro definition ended unexpectedly + --> $DIR/bad-macro-definition.rs:6:22 + | +LL | macro_rules! b { 0 => } + | ^ expected right-hand side of macro rule + +error: invalid macro matcher; matchers must be contained in balanced delimiters + --> $DIR/bad-macro-definition.rs:10:18 + | +LL | macro_rules! c { x => } + | ^ + +error: macro definition ended unexpectedly + --> $DIR/bad-macro-definition.rs:10:22 + | +LL | macro_rules! c { x => } + | ^ expected right-hand side of macro rule + +error: invalid macro matcher; matchers must be contained in balanced delimiters + --> $DIR/bad-macro-definition.rs:14:18 + | +LL | macro_rules! d { _ => } + | ^ + +error: macro definition ended unexpectedly + --> $DIR/bad-macro-definition.rs:14:22 + | +LL | macro_rules! d { _ => } + | ^ expected right-hand side of macro rule + +error: expected `=>`, found end of macro arguments + --> $DIR/bad-macro-definition.rs:18:20 + | +LL | macro_rules! e { {} } + | ^ expected `=>` + +error: macros must contain at least one rule + --> $DIR/bad-macro-definition.rs:21:1 + | +LL | macro_rules! f {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr index 136cd763b05c..1ac017aa08b9 100644 --- a/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr +++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/invalid-attribute.stderr @@ -1,8 +1,11 @@ -error: malformed `non_exhaustive` attribute input +error[E0565]: malformed `non_exhaustive` attribute input --> $DIR/invalid-attribute.rs:1:1 | LL | #[non_exhaustive(anything)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[non_exhaustive]` + | ^^^^^^^^^^^^^^^^----------^ + | | | + | | didn't expect any arguments here + | help: must be of the form: `#[non_exhaustive]` error[E0701]: attribute should be applied to a struct or enum --> $DIR/invalid-attribute.rs:5:1 @@ -27,4 +30,5 @@ LL | | } error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0701`. +Some errors have detailed explanations: E0565, E0701. +For more information about an error, try `rustc --explain E0565`. diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs index 78ff85489bed..1b2558c724bb 100644 --- a/tests/ui/track-diagnostics/track.rs +++ b/tests/ui/track-diagnostics/track.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Z track-diagnostics -//@ error-pattern: created at +//@ dont-require-annotations: NOTE //@ rustc-env:RUST_BACKTRACE=0 //@ failure-status: 101 @@ -16,6 +16,9 @@ fn main() { break rust //~^ ERROR cannot find value `rust` in this scope + //~| NOTE created at //~| ERROR `break` outside of a loop or labeled block + //~| NOTE created at //~| ERROR It looks like you're trying to break rust; would you like some ICE? + //~| NOTE created at } diff --git a/tests/ui/track-diagnostics/track.stderr b/tests/ui/track-diagnostics/track.stderr index 527c0d1b8989..f82764958d46 100644 --- a/tests/ui/track-diagnostics/track.stderr +++ b/tests/ui/track-diagnostics/track.stderr @@ -3,22 +3,24 @@ error[E0425]: cannot find value `rust` in this scope | LL | break rust | ^^^^ not found in this scope --Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC + | + = note: -Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC error[E0268]: `break` outside of a loop or labeled block --> $DIR/track.rs:LL:CC | LL | break rust | ^^^^^^^^^^ cannot `break` outside of a loop or labeled block --Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/loops.rs:LL:CC + | + = note: -Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/loops.rs:LL:CC error: internal compiler error: It looks like you're trying to break rust; would you like some ICE? --> $DIR/track.rs:LL:CC | LL | break rust | ^^^^^^^^^^ --Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/lib.rs:LL:CC | + = note: -Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/lib.rs:LL:CC = note: the compiler expectedly panicked. this is a feature. = note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675 = note: rustc $VERSION running on $TARGET diff --git a/tests/ui/track-diagnostics/track2.rs b/tests/ui/track-diagnostics/track2.rs index f51a42cf86f9..591b84f330b7 100644 --- a/tests/ui/track-diagnostics/track2.rs +++ b/tests/ui/track-diagnostics/track2.rs @@ -1,10 +1,12 @@ //@ compile-flags: -Z track-diagnostics -//@ error-pattern: created at +//@ dont-require-annotations: NOTE // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" fn main() { - let _moved @ _from = String::from("foo"); //~ ERROR use of moved value + let _moved @ _from = String::from("foo"); + //~^ ERROR use of moved value + //~| NOTE created at } diff --git a/tests/ui/track-diagnostics/track2.stderr b/tests/ui/track-diagnostics/track2.stderr index dffa0b0c91c1..02010639c027 100644 --- a/tests/ui/track-diagnostics/track2.stderr +++ b/tests/ui/track-diagnostics/track2.stderr @@ -6,8 +6,8 @@ LL | let _moved @ _from = String::from("foo"); | | | | | value moved here | value used here after move --Ztrack-diagnostics: created at compiler/rustc_borrowck/src/borrowck_errors.rs:LL:CC | + = note: -Ztrack-diagnostics: created at compiler/rustc_borrowck/src/borrowck_errors.rs:LL:CC help: borrow this binding in the pattern to avoid moving the value | LL | let ref _moved @ ref _from = String::from("foo"); diff --git a/tests/ui/track-diagnostics/track3.rs b/tests/ui/track-diagnostics/track3.rs index 428067572af7..a39e71915d90 100644 --- a/tests/ui/track-diagnostics/track3.rs +++ b/tests/ui/track-diagnostics/track3.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Z track-diagnostics -//@ error-pattern: created at +//@ dont-require-annotations: NOTE // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. @@ -8,5 +8,7 @@ fn main() { let _unimported = Blah { field: u8 }; //~^ ERROR cannot find struct, variant or union type `Blah` in this scope + //~| NOTE created at //~| ERROR expected value, found builtin type `u8` + //~| NOTE created at } diff --git a/tests/ui/track-diagnostics/track3.stderr b/tests/ui/track-diagnostics/track3.stderr index dc468d7e8eeb..3e99c8d5f33f 100644 --- a/tests/ui/track-diagnostics/track3.stderr +++ b/tests/ui/track-diagnostics/track3.stderr @@ -3,14 +3,16 @@ error[E0422]: cannot find struct, variant or union type `Blah` in this scope | LL | let _unimported = Blah { field: u8 }; | ^^^^ not found in this scope --Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC + | + = note: -Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC error[E0423]: expected value, found builtin type `u8` --> $DIR/track3.rs:LL:CC | LL | let _unimported = Blah { field: u8 }; | ^^ not a value --Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC + | + = note: -Ztrack-diagnostics: created at compiler/rustc_resolve/src/late/diagnostics.rs:LL:CC error: aborting due to 2 previous errors diff --git a/tests/ui/track-diagnostics/track4.rs b/tests/ui/track-diagnostics/track4.rs index b6edfdba2596..0038c616aa55 100644 --- a/tests/ui/track-diagnostics/track4.rs +++ b/tests/ui/track-diagnostics/track4.rs @@ -1,11 +1,13 @@ //@ compile-flags: -Z track-diagnostics -//@ error-pattern: created at +//@ dont-require-annotations: NOTE // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" -pub onion { //~ ERROR missing `enum` for enum definition +pub onion { + //~^ ERROR missing `enum` for enum definition + //~| NOTE created at Owo(u8), Uwu(i8), } diff --git a/tests/ui/track-diagnostics/track4.stderr b/tests/ui/track-diagnostics/track4.stderr index 19499fa7abc5..2b6805849b52 100644 --- a/tests/ui/track-diagnostics/track4.stderr +++ b/tests/ui/track-diagnostics/track4.stderr @@ -3,8 +3,8 @@ error: missing `enum` for enum definition | LL | pub onion { | ^^^^^^^^^ --Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/item.rs:LL:CC | + = note: -Ztrack-diagnostics: created at compiler/rustc_parse/src/parser/item.rs:LL:CC help: add `enum` here to parse `onion` as an enum | LL | pub enum onion { diff --git a/tests/ui/track-diagnostics/track5.rs b/tests/ui/track-diagnostics/track5.rs index 800bb21b2b16..09fda4eb5273 100644 --- a/tests/ui/track-diagnostics/track5.rs +++ b/tests/ui/track-diagnostics/track5.rs @@ -1,8 +1,10 @@ //@ compile-flags: -Z track-diagnostics -//@ error-pattern: created at +//@ dont-require-annotations: NOTE // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" -} //~ ERROR unexpected closing delimiter: `}` +} +//~^ ERROR unexpected closing delimiter: `}` +//~| NOTE created at diff --git a/tests/ui/track-diagnostics/track5.stderr b/tests/ui/track-diagnostics/track5.stderr index ecc7d81b3c36..5de0550918eb 100644 --- a/tests/ui/track-diagnostics/track5.stderr +++ b/tests/ui/track-diagnostics/track5.stderr @@ -3,7 +3,8 @@ error: unexpected closing delimiter: `}` | LL | } | ^ unexpected closing delimiter --Ztrack-diagnostics: created at compiler/rustc_parse/src/lexer/tokentrees.rs:LL:CC + | + = note: -Ztrack-diagnostics: created at compiler/rustc_parse/src/lexer/tokentrees.rs:LL:CC error: aborting due to 1 previous error diff --git a/tests/ui/track-diagnostics/track6.rs b/tests/ui/track-diagnostics/track6.rs index 55db2ecf939d..11d3b7e9764b 100644 --- a/tests/ui/track-diagnostics/track6.rs +++ b/tests/ui/track-diagnostics/track6.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Z track-diagnostics -//@ error-pattern: created at +//@ dont-require-annotations: NOTE // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. @@ -11,7 +11,9 @@ pub trait Foo { } impl Foo for T { - default fn bar() {} //~ ERROR specialization is unstable + default fn bar() {} + //~^ ERROR specialization is unstable + //~| NOTE created at } fn main() {} diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr index 9ed8a19629df..a61f7855e323 100644 --- a/tests/ui/track-diagnostics/track6.stderr +++ b/tests/ui/track-diagnostics/track6.stderr @@ -3,8 +3,8 @@ error[E0658]: specialization is unstable | LL | default fn bar() {} | ^^^^^^^^^^^^^^^^^^^ --Ztrack-diagnostics: created at compiler/rustc_ast_passes/src/feature_gate.rs:LL:CC | + = note: -Ztrack-diagnostics: created at compiler/rustc_ast_passes/src/feature_gate.rs:LL:CC = note: see issue #31844 for more information = help: add `#![feature(specialization)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date diff --git a/tests/ui/traits/negative-bounds/negative-sized.rs b/tests/ui/traits/negative-bounds/negative-sized.rs new file mode 100644 index 000000000000..18369c784275 --- /dev/null +++ b/tests/ui/traits/negative-bounds/negative-sized.rs @@ -0,0 +1,8 @@ +#![feature(negative_bounds)] + +fn foo() {} + +fn main() { + foo::<()>(); + //~^ ERROR the trait bound `(): !Sized` is not satisfied +} diff --git a/tests/ui/traits/negative-bounds/negative-sized.stderr b/tests/ui/traits/negative-bounds/negative-sized.stderr new file mode 100644 index 000000000000..143933803b81 --- /dev/null +++ b/tests/ui/traits/negative-bounds/negative-sized.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): !Sized` is not satisfied + --> $DIR/negative-sized.rs:6:11 + | +LL | foo::<()>(); + | ^^ the trait bound `(): !Sized` is not satisfied + | +note: required by a bound in `foo` + --> $DIR/negative-sized.rs:3:11 + | +LL | fn foo() {} + | ^^^^^^ required by this bound in `foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/pointer-like.rs b/tests/ui/traits/next-solver/pointer-like.rs deleted file mode 100644 index bdcad4d4c5eb..000000000000 --- a/tests/ui/traits/next-solver/pointer-like.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ compile-flags: -Znext-solver - -#![feature(pointer_like_trait)] - -use std::marker::PointerLike; - -fn require_(_: impl PointerLike) {} - -fn main() { - require_(1usize); - require_(1u16); - //~^ ERROR `u16` needs to have the same ABI as a pointer - require_(&1i16); -} diff --git a/tests/ui/traits/next-solver/pointer-like.stderr b/tests/ui/traits/next-solver/pointer-like.stderr deleted file mode 100644 index 4b624fd0d354..000000000000 --- a/tests/ui/traits/next-solver/pointer-like.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error[E0277]: `u16` needs to have the same ABI as a pointer - --> $DIR/pointer-like.rs:11:14 - | -LL | require_(1u16); - | -------- ^^^^ the trait `PointerLike` is not implemented for `u16` - | | - | required by a bound introduced by this call - | - = note: the trait bound `u16: PointerLike` is not satisfied -note: required by a bound in `require_` - --> $DIR/pointer-like.rs:7:21 - | -LL | fn require_(_: impl PointerLike) {} - | ^^^^^^^^^^^ required by this bound in `require_` -help: consider borrowing here - | -LL | require_(&1u16); - | + -LL | require_(&mut 1u16); - | ++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/uninhabited/uninhabited-patterns.rs b/tests/ui/uninhabited/uninhabited-patterns.rs index b7429464fa5a..1f30af2acc69 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.rs +++ b/tests/ui/uninhabited/uninhabited-patterns.rs @@ -27,7 +27,11 @@ fn main() { let x: Result, &[Result]> = Err(&[]); match x { - Ok(box _) => (), //~ ERROR unreachable pattern + Ok(box _) => (), // We'd get a non-exhaustiveness error if this arm was removed; don't lint. + Err(&[]) => (), + Err(&[..]) => (), + } + match x { //~ ERROR non-exhaustive patterns Err(&[]) => (), Err(&[..]) => (), } diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr index 7a872767d959..62113c82a364 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-patterns.stderr @@ -1,8 +1,26 @@ -error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:30:9 +error[E0004]: non-exhaustive patterns: `Ok(_)` not covered + --> $DIR/uninhabited-patterns.rs:34:11 | -LL | Ok(box _) => (), - | ^^^^^^^^^------- +LL | match x { + | ^ pattern `Ok(_)` not covered + | +note: `Result, &[Result]>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result, &[Result]>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Err(&[..]) => (), +LL ~ Ok(_) => todo!(), + | + +error: unreachable pattern + --> $DIR/uninhabited-patterns.rs:43:9 + | +LL | Err(Ok(_y)) => (), + | ^^^^^^^^^^^------- | | | matches no values because `NotSoSecretlyEmpty` is uninhabited | help: remove the match arm @@ -15,18 +33,7 @@ LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:39:9 - | -LL | Err(Ok(_y)) => (), - | ^^^^^^^^^^^------- - | | - | matches no values because `NotSoSecretlyEmpty` is uninhabited - | help: remove the match arm - | - = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types - -error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:42:15 + --> $DIR/uninhabited-patterns.rs:46:15 | LL | while let Some(_y) = foo() { | ^^^^^^^^ matches no values because `NotSoSecretlyEmpty` is uninhabited @@ -35,3 +42,4 @@ LL | while let Some(_y) = foo() { error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0004`. diff --git a/triagebot.toml b/triagebot.toml index 64a8a7c46b42..4e3dff219f1d 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1404,6 +1404,9 @@ project-exploit-mitigations = [ compiletest = [ "@jieyouxu", ] +dep-bumps = [ + "@clubby789", +] [assign.owners] "/.github/workflows" = ["infra-ci"]