From b33505687b97322ff4f5ee0e65b62a10623f0072 Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Sat, 8 Mar 2025 16:50:19 +0700 Subject: [PATCH 01/11] Turn `Cow::is_borrowed,is_owned` into associated functions. This is done because `Cow` implements `Deref`. Therefore, to avoid conflicts with an inner type having a method of the same name, we use an associated method, like `Box::into_raw`. --- compiler/rustc_mir_transform/src/gvn.rs | 2 +- library/alloc/src/borrow.rs | 24 ++++++++++++++++-------- library/alloctests/tests/borrow.rs | 4 ++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 6b11706d2b55f..86839781086a7 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -746,7 +746,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { } } - if projection.is_owned() { + if Cow::is_owned(&projection) { place.projection = self.tcx.mk_place_elems(&projection); } diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index 07f51b7614ff8..124b6b05f2a17 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -212,6 +212,10 @@ impl Clone for Cow<'_, B> { impl Cow<'_, B> { /// Returns true if the data is borrowed, i.e. if `to_mut` would require additional work. /// + /// Note: this is an associated function, which means that you have to call + /// it as `Cow::is_borrowed(&c)` instead of `c.is_borrowed()`. This is so + /// that there is no conflict with a method on the inner type. + /// /// # Examples /// /// ``` @@ -219,14 +223,14 @@ impl Cow<'_, B> { /// use std::borrow::Cow; /// /// let cow = Cow::Borrowed("moo"); - /// assert!(cow.is_borrowed()); + /// assert!(Cow::is_borrowed(&cow)); /// /// let bull: Cow<'_, str> = Cow::Owned("...moo?".to_string()); - /// assert!(!bull.is_borrowed()); + /// assert!(!Cow::is_borrowed(&bull)); /// ``` #[unstable(feature = "cow_is_borrowed", issue = "65143")] - pub const fn is_borrowed(&self) -> bool { - match *self { + pub const fn is_borrowed(c: &Self) -> bool { + match *c { Borrowed(_) => true, Owned(_) => false, } @@ -234,6 +238,10 @@ impl Cow<'_, B> { /// Returns true if the data is owned, i.e. if `to_mut` would be a no-op. /// + /// Note: this is an associated function, which means that you have to call + /// it as `Cow::is_owned(&c)` instead of `c.is_owned()`. This is so that + /// there is no conflict with a method on the inner type. + /// /// # Examples /// /// ``` @@ -241,14 +249,14 @@ impl Cow<'_, B> { /// use std::borrow::Cow; /// /// let cow: Cow<'_, str> = Cow::Owned("moo".to_string()); - /// assert!(cow.is_owned()); + /// assert!(Cow::is_owned(&cow)); /// /// let bull = Cow::Borrowed("...moo?"); - /// assert!(!bull.is_owned()); + /// assert!(!Cow::is_owned(&bull)); /// ``` #[unstable(feature = "cow_is_borrowed", issue = "65143")] - pub const fn is_owned(&self) -> bool { - !self.is_borrowed() + pub const fn is_owned(c: &Self) -> bool { + !Cow::is_borrowed(c) } /// Acquires a mutable reference to the owned form of the data. diff --git a/library/alloctests/tests/borrow.rs b/library/alloctests/tests/borrow.rs index af7efb7d78223..19695d424db2d 100644 --- a/library/alloctests/tests/borrow.rs +++ b/library/alloctests/tests/borrow.rs @@ -52,9 +52,9 @@ fn cow_const() { const COW: Cow<'_, str> = Cow::Borrowed("moo"); - const IS_BORROWED: bool = COW.is_borrowed(); + const IS_BORROWED: bool = Cow::is_borrowed(&COW); assert!(IS_BORROWED); - const IS_OWNED: bool = COW.is_owned(); + const IS_OWNED: bool = Cow::is_owned(&COW); assert!(!IS_OWNED); } From f0c98c2caa080bf1a69de6d560915c2cafb0b296 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 18 Oct 2025 22:49:38 +0300 Subject: [PATCH 02/11] Allocate vec capacity upfront in coroutine layout computation --- compiler/rustc_mir_transform/src/coroutine.rs | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 26b6003e1095e..46b4e8b86e516 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -52,7 +52,7 @@ mod by_move_body; mod drop; -use std::{iter, ops}; +use std::ops; pub(super) use by_move_body::coroutine_by_move_body_def_id; use drop::{ @@ -60,6 +60,7 @@ use drop::{ create_coroutine_drop_shim_proxy_async, elaborate_coroutine_drops, expand_async_drops, has_expandable_async_drops, insert_clean_drop, }; +use itertools::izip; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; @@ -982,8 +983,8 @@ fn compute_layout<'tcx>( } = liveness; // Gather live local types and their indices. - let mut locals = IndexVec::::new(); - let mut tys = IndexVec::::new(); + let mut locals = IndexVec::::with_capacity(saved_locals.domain_size()); + let mut tys = IndexVec::::with_capacity(saved_locals.domain_size()); for (saved_local, local) in saved_locals.iter_enumerated() { debug!("coroutine saved local {:?} => {:?}", saved_local, local); @@ -1017,38 +1018,39 @@ fn compute_layout<'tcx>( // In debuginfo, these will correspond to the beginning (UNRESUMED) or end // (RETURNED, POISONED) of the function. let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span; - let mut variant_source_info: IndexVec = [ + let mut variant_source_info: IndexVec = IndexVec::with_capacity( + CoroutineArgs::RESERVED_VARIANTS + live_locals_at_suspension_points.len(), + ); + variant_source_info.extend([ SourceInfo::outermost(body_span.shrink_to_lo()), SourceInfo::outermost(body_span.shrink_to_hi()), SourceInfo::outermost(body_span.shrink_to_hi()), - ] - .iter() - .copied() - .collect(); + ]); // Build the coroutine variant field list. // Create a map from local indices to coroutine struct indices. - let mut variant_fields: IndexVec> = - iter::repeat(IndexVec::new()).take(CoroutineArgs::RESERVED_VARIANTS).collect(); + let mut variant_fields: IndexVec = IndexVec::from_elem_n( + IndexVec::new(), + CoroutineArgs::RESERVED_VARIANTS + live_locals_at_suspension_points.len(), + ); let mut remap = IndexVec::from_elem_n(None, saved_locals.domain_size()); - for (suspension_point_idx, live_locals) in live_locals_at_suspension_points.iter().enumerate() { - let variant_index = - VariantIdx::from(CoroutineArgs::RESERVED_VARIANTS + suspension_point_idx); - let mut fields = IndexVec::new(); - for (idx, saved_local) in live_locals.iter().enumerate() { - fields.push(saved_local); + for (live_locals, &source_info_at_suspension_point, (variant_index, fields)) in izip!( + &live_locals_at_suspension_points, + &source_info_at_suspension_points, + variant_fields.iter_enumerated_mut().skip(CoroutineArgs::RESERVED_VARIANTS) + ) { + *fields = live_locals.iter().collect(); + for (idx, &saved_local) in fields.iter_enumerated() { // Note that if a field is included in multiple variants, we will // just use the first one here. That's fine; fields do not move // around inside coroutines, so it doesn't matter which variant // index we access them by. - let idx = FieldIdx::from_usize(idx); remap[locals[saved_local]] = Some((tys[saved_local].ty, variant_index, idx)); } - variant_fields.push(fields); - variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]); + variant_source_info.push(source_info_at_suspension_point); } - debug!("coroutine variant_fields = {:?}", variant_fields); - debug!("coroutine storage_conflicts = {:#?}", storage_conflicts); + debug!(?variant_fields); + debug!(?storage_conflicts); let mut field_names = IndexVec::from_elem(None, &tys); for var in &body.var_debug_info { From a67c615506326bb3ef67d8c1d1b57964525d2615 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 18 Oct 2025 22:50:11 +0300 Subject: [PATCH 03/11] Reduce rightward drift in `locals_live_across_suspend_points` --- compiler/rustc_mir_transform/src/coroutine.rs | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 46b4e8b86e516..b010b37e75cdd 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -736,53 +736,53 @@ fn locals_live_across_suspend_points<'tcx>( let mut live_locals_at_any_suspension_point = DenseBitSet::new_empty(body.local_decls.len()); for (block, data) in body.basic_blocks.iter_enumerated() { - if let TerminatorKind::Yield { .. } = data.terminator().kind { - let loc = Location { block, statement_index: data.statements.len() }; - - liveness.seek_to_block_end(block); - let mut live_locals = liveness.get().clone(); - - if !movable { - // The `liveness` variable contains the liveness of MIR locals ignoring borrows. - // This is correct for movable coroutines since borrows cannot live across - // suspension points. However for immovable coroutines we need to account for - // borrows, so we conservatively assume that all borrowed locals are live until - // we find a StorageDead statement referencing the locals. - // To do this we just union our `liveness` result with `borrowed_locals`, which - // contains all the locals which has been borrowed before this suspension point. - // If a borrow is converted to a raw reference, we must also assume that it lives - // forever. Note that the final liveness is still bounded by the storage liveness - // of the local, which happens using the `intersect` operation below. - borrowed_locals_cursor2.seek_before_primary_effect(loc); - live_locals.union(borrowed_locals_cursor2.get()); - } + let TerminatorKind::Yield { .. } = data.terminator().kind else { continue }; + + let loc = Location { block, statement_index: data.statements.len() }; + + liveness.seek_to_block_end(block); + let mut live_locals = liveness.get().clone(); + + if !movable { + // The `liveness` variable contains the liveness of MIR locals ignoring borrows. + // This is correct for movable coroutines since borrows cannot live across + // suspension points. However for immovable coroutines we need to account for + // borrows, so we conservatively assume that all borrowed locals are live until + // we find a StorageDead statement referencing the locals. + // To do this we just union our `liveness` result with `borrowed_locals`, which + // contains all the locals which has been borrowed before this suspension point. + // If a borrow is converted to a raw reference, we must also assume that it lives + // forever. Note that the final liveness is still bounded by the storage liveness + // of the local, which happens using the `intersect` operation below. + borrowed_locals_cursor2.seek_before_primary_effect(loc); + live_locals.union(borrowed_locals_cursor2.get()); + } - // Store the storage liveness for later use so we can restore the state - // after a suspension point - storage_live.seek_before_primary_effect(loc); - storage_liveness_map[block] = Some(storage_live.get().clone()); + // Store the storage liveness for later use so we can restore the state + // after a suspension point + storage_live.seek_before_primary_effect(loc); + storage_liveness_map[block] = Some(storage_live.get().clone()); - // Locals live are live at this point only if they are used across - // suspension points (the `liveness` variable) - // and their storage is required (the `storage_required` variable) - requires_storage_cursor.seek_before_primary_effect(loc); - live_locals.intersect(requires_storage_cursor.get()); + // Locals live are live at this point only if they are used across + // suspension points (the `liveness` variable) + // and their storage is required (the `storage_required` variable) + requires_storage_cursor.seek_before_primary_effect(loc); + live_locals.intersect(requires_storage_cursor.get()); - // The coroutine argument is ignored. - live_locals.remove(SELF_ARG); + // The coroutine argument is ignored. + live_locals.remove(SELF_ARG); - debug!("loc = {:?}, live_locals = {:?}", loc, live_locals); + debug!(?loc, ?live_locals); - // Add the locals live at this suspension point to the set of locals which live across - // any suspension points - live_locals_at_any_suspension_point.union(&live_locals); + // Add the locals live at this suspension point to the set of locals which live across + // any suspension points + live_locals_at_any_suspension_point.union(&live_locals); - live_locals_at_suspension_points.push(live_locals); - source_info_at_suspension_points.push(data.terminator().source_info); - } + live_locals_at_suspension_points.push(live_locals); + source_info_at_suspension_points.push(data.terminator().source_info); } - debug!("live_locals_anywhere = {:?}", live_locals_at_any_suspension_point); + debug!(?live_locals_at_any_suspension_point); let saved_locals = CoroutineSavedLocals(live_locals_at_any_suspension_point); // Renumber our liveness_map bitsets to include only the locals we are From 11b82e134c3fb3fee493230a166a46dfdef9bd27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 25 Oct 2025 18:47:30 +0200 Subject: [PATCH 04/11] rustdoc: Rename unstable option `--nocapture` to `--no-capture` --- src/doc/rustdoc/src/unstable-features.md | 2 +- src/librustdoc/config.rs | 8 ++++---- src/librustdoc/doctest.rs | 16 ++++++++-------- src/librustdoc/lib.rs | 2 +- .../rustdoc-default-output/output-default.stdout | 2 +- tests/rustdoc-ui/doctest/check-cfg-test.rs | 2 +- .../{nocapture-fail.rs => no-capture-fail.rs} | 2 +- ...apture-fail.stderr => no-capture-fail.stderr} | 2 +- ...apture-fail.stdout => no-capture-fail.stdout} | 2 +- .../doctest/{nocapture.rs => no-capture.rs} | 2 +- .../{nocapture.stderr => no-capture.stderr} | 0 .../{nocapture.stdout => no-capture.stdout} | 2 +- tests/rustdoc-ui/doctest/non_local_defs.rs | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) rename tests/rustdoc-ui/doctest/{nocapture-fail.rs => no-capture-fail.rs} (83%) rename tests/rustdoc-ui/doctest/{nocapture-fail.stderr => no-capture-fail.stderr} (89%) rename tests/rustdoc-ui/doctest/{nocapture-fail.stdout => no-capture-fail.stdout} (62%) rename tests/rustdoc-ui/doctest/{nocapture.rs => no-capture.rs} (79%) rename tests/rustdoc-ui/doctest/{nocapture.stderr => no-capture.stderr} (100%) rename tests/rustdoc-ui/doctest/{nocapture.stdout => no-capture.stdout} (72%) diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 04d3c0cd630f5..a26ae7d284443 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -362,7 +362,7 @@ Using `index-page` option enables `enable-index-page` option as well. This feature allows the generation of a default index-page which lists the generated crates. -## `--nocapture`: disable output capture for test +## `--no-capture`: disable output capture for test When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be captured by rustdoc. Instead, the output will be directed to your terminal, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index cf0858810f55f..35d3a68c7e0e8 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -155,7 +155,7 @@ pub(crate) struct Options { /// Whether doctests should emit unused externs pub(crate) json_unused_externs: JsonUnusedExterns, /// Whether to skip capturing stdout and stderr of tests. - pub(crate) nocapture: bool, + pub(crate) no_capture: bool, /// Configuration for scraping examples from the current crate. If this option is Some(..) then /// the compiler will scrape examples and not generate documentation. @@ -211,7 +211,7 @@ impl fmt::Debug for Options { .field("no_run", &self.no_run) .field("test_builder_wrappers", &self.test_builder_wrappers) .field("remap-file-prefix", &self.remap_path_prefix) - .field("nocapture", &self.nocapture) + .field("no_capture", &self.no_capture) .field("scrape_examples_options", &self.scrape_examples_options) .field("unstable_features", &self.unstable_features) .finish() @@ -785,7 +785,7 @@ impl Options { let run_check = matches.opt_present("check"); let generate_redirect_map = matches.opt_present("generate-redirect-map"); let show_type_layout = matches.opt_present("show-type-layout"); - let nocapture = matches.opt_present("nocapture"); + let no_capture = matches.opt_present("no-capture"); let generate_link_to_definition = matches.opt_present("generate-link-to-definition"); let generate_macro_expansion = matches.opt_present("generate-macro-expansion"); let extern_html_root_takes_precedence = @@ -856,7 +856,7 @@ impl Options { no_run, test_builder_wrappers, remap_path_prefix, - nocapture, + no_capture, crate_name, output_format, json_unused_externs, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 0d551a969d632..c9cd9f7fd4b11 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -326,8 +326,8 @@ pub(crate) fn run_tests( let mut test_args = Vec::with_capacity(rustdoc_options.test_args.len() + 1); test_args.insert(0, "rustdoctest".to_string()); test_args.extend_from_slice(&rustdoc_options.test_args); - if rustdoc_options.nocapture { - test_args.push("--nocapture".to_string()); + if rustdoc_options.no_capture { + test_args.push("--no-capture".to_string()); } let mut nb_errors = 0; @@ -644,8 +644,8 @@ fn run_test( // tested as standalone tests. return (Duration::default(), Err(TestFailure::CompileError)); } - if !rustdoc_options.nocapture { - // If `nocapture` is disabled, then we don't display rustc's output when compiling + if !rustdoc_options.no_capture { + // If `no_capture` is disabled, then we don't display rustc's output when compiling // the merged doctests. compiler.stderr(Stdio::null()); } @@ -721,8 +721,8 @@ fn run_test( // tested as standalone tests. return (instant.elapsed(), Err(TestFailure::CompileError)); } - if !rustdoc_options.nocapture { - // If `nocapture` is disabled, then we don't display rustc's output when compiling + if !rustdoc_options.no_capture { + // If `no_capture` is disabled, then we don't display rustc's output when compiling // the merged doctests. runner_compiler.stderr(Stdio::null()); } @@ -821,7 +821,7 @@ fn run_test( cmd.current_dir(run_directory); } - let result = if doctest.is_multiple_tests() || rustdoc_options.nocapture { + let result = if doctest.is_multiple_tests() || rustdoc_options.no_capture { cmd.status().map(|status| process::Output { status, stdout: Vec::new(), @@ -1016,7 +1016,7 @@ impl CreateRunnableDocTests { .span(scraped_test.span) .build(dcx); let is_standalone = !doctest.can_be_merged - || self.rustdoc_options.nocapture + || self.rustdoc_options.no_capture || self.rustdoc_options.test_args.iter().any(|arg| arg == "--show-output"); if is_standalone { let test_desc = self.generate_test_desc_and_fn(doctest, scraped_test); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 5f72064f0a8ce..f5d94dc010988 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -585,7 +585,7 @@ fn opts() -> Vec { "Include the memory layout of types in the docs", "", ), - opt(Unstable, Flag, "", "nocapture", "Don't capture stdout and stderr of tests", ""), + opt(Unstable, Flag, "", "no-capture", "Don't capture stdout and stderr of tests", ""), opt( Unstable, Flag, diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout index badbc0b6d15b7..f1116d65cabbc 100644 --- a/tests/run-make/rustdoc-default-output/output-default.stdout +++ b/tests/run-make/rustdoc-default-output/output-default.stdout @@ -158,7 +158,7 @@ Options: Remap source names in compiler messages --show-type-layout Include the memory layout of types in the docs - --nocapture Don't capture stdout and stderr of tests + --no-capture Don't capture stdout and stderr of tests --generate-link-to-definition Make the identifiers in the HTML source code pages navigable diff --git a/tests/rustdoc-ui/doctest/check-cfg-test.rs b/tests/rustdoc-ui/doctest/check-cfg-test.rs index 39fdb3a5853fc..201d6d60672d2 100644 --- a/tests/rustdoc-ui/doctest/check-cfg-test.rs +++ b/tests/rustdoc-ui/doctest/check-cfg-test.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: --test --nocapture --check-cfg=cfg(feature,values("test")) -Z unstable-options +//@ compile-flags: --test --no-capture --check-cfg=cfg(feature,values("test")) -Z unstable-options //@ normalize-stderr: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.rs b/tests/rustdoc-ui/doctest/no-capture-fail.rs similarity index 83% rename from tests/rustdoc-ui/doctest/nocapture-fail.rs rename to tests/rustdoc-ui/doctest/no-capture-fail.rs index 8c64a49f65005..c58d2495aee0d 100644 --- a/tests/rustdoc-ui/doctest/nocapture-fail.rs +++ b/tests/rustdoc-ui/doctest/no-capture-fail.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags:--test -Zunstable-options --nocapture +//@ compile-flags:--test -Zunstable-options --no-capture //@ normalize-stderr: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.stderr b/tests/rustdoc-ui/doctest/no-capture-fail.stderr similarity index 89% rename from tests/rustdoc-ui/doctest/nocapture-fail.stderr rename to tests/rustdoc-ui/doctest/no-capture-fail.stderr index c6a5785a24fe4..2817a66b514ce 100644 --- a/tests/rustdoc-ui/doctest/nocapture-fail.stderr +++ b/tests/rustdoc-ui/doctest/no-capture-fail.stderr @@ -1,5 +1,5 @@ error: struct literal body without path - --> $DIR/nocapture-fail.rs:8:10 + --> $DIR/no-capture-fail.rs:8:10 | LL | fn foo() { | __________^ diff --git a/tests/rustdoc-ui/doctest/nocapture-fail.stdout b/tests/rustdoc-ui/doctest/no-capture-fail.stdout similarity index 62% rename from tests/rustdoc-ui/doctest/nocapture-fail.stdout rename to tests/rustdoc-ui/doctest/no-capture-fail.stdout index 754f77db53ca3..ee94540e37b43 100644 --- a/tests/rustdoc-ui/doctest/nocapture-fail.stdout +++ b/tests/rustdoc-ui/doctest/no-capture-fail.stdout @@ -1,6 +1,6 @@ running 1 test -test $DIR/nocapture-fail.rs - Foo (line 7) - compile fail ... ok +test $DIR/no-capture-fail.rs - Foo (line 7) - compile fail ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/doctest/nocapture.rs b/tests/rustdoc-ui/doctest/no-capture.rs similarity index 79% rename from tests/rustdoc-ui/doctest/nocapture.rs rename to tests/rustdoc-ui/doctest/no-capture.rs index c4360341864fd..b1e3014798f9a 100644 --- a/tests/rustdoc-ui/doctest/nocapture.rs +++ b/tests/rustdoc-ui/doctest/no-capture.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags:--test -Zunstable-options --nocapture +//@ compile-flags:--test -Zunstable-options --no-capture //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" diff --git a/tests/rustdoc-ui/doctest/nocapture.stderr b/tests/rustdoc-ui/doctest/no-capture.stderr similarity index 100% rename from tests/rustdoc-ui/doctest/nocapture.stderr rename to tests/rustdoc-ui/doctest/no-capture.stderr diff --git a/tests/rustdoc-ui/doctest/nocapture.stdout b/tests/rustdoc-ui/doctest/no-capture.stdout similarity index 72% rename from tests/rustdoc-ui/doctest/nocapture.stdout rename to tests/rustdoc-ui/doctest/no-capture.stdout index 4880e75da7062..9916d3d1f8095 100644 --- a/tests/rustdoc-ui/doctest/nocapture.stdout +++ b/tests/rustdoc-ui/doctest/no-capture.stdout @@ -1,7 +1,7 @@ running 1 test hello! -test $DIR/nocapture.rs - Foo (line 6) ... ok +test $DIR/no-capture.rs - Foo (line 6) ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/doctest/non_local_defs.rs b/tests/rustdoc-ui/doctest/non_local_defs.rs index ce65ad2cf72c2..1b87b04148a88 100644 --- a/tests/rustdoc-ui/doctest/non_local_defs.rs +++ b/tests/rustdoc-ui/doctest/non_local_defs.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags:--test --test-args --test-threads=1 --nocapture -Zunstable-options +//@ compile-flags:--test --test-args --test-threads=1 --no-capture -Zunstable-options //@ normalize-stdout: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stderr: "tests/rustdoc-ui/doctest" -> "$$DIR" //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" From 857a18735f99e6e3e520a2e3330643e74df797ba Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 27 Oct 2025 15:58:56 +0100 Subject: [PATCH 05/11] rustdoc search: Include attribute and derive macros when filtering on "macros" --- src/librustdoc/html/static/js/search.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 337c973a2c84f..0a73d32dac2de 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -3904,6 +3904,8 @@ class DocSearch { return name === "primitive" || name === "associatedtype"; case "trait": return name === "traitalias"; + case "macro": + return name === "attr" || name === "derive"; } // No match From 52c99e6d0dd40b1331d24fc5b71910e7e0de6e5e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 27 Oct 2025 16:00:32 +0100 Subject: [PATCH 06/11] Add regression test for including derive macros in macro filtering --- tests/rustdoc-js-std/filter-macro-attr-derive.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/rustdoc-js-std/filter-macro-attr-derive.js diff --git a/tests/rustdoc-js-std/filter-macro-attr-derive.js b/tests/rustdoc-js-std/filter-macro-attr-derive.js new file mode 100644 index 0000000000000..4c8ec77030b42 --- /dev/null +++ b/tests/rustdoc-js-std/filter-macro-attr-derive.js @@ -0,0 +1,9 @@ +// This test ensures that filtering on "macro" will also include attribute and derive +// macros. + +const EXPECTED = { + 'query': 'macro:debug', + 'others': [ + { 'path': 'std::fmt', 'name': 'Debug', 'href': '../std/fmt/derive.Debug.html' }, + ], +}; From bd61985bb63e22551c859c1d157d690ad0dfd285 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Fri, 3 Oct 2025 09:11:24 -0600 Subject: [PATCH 07/11] Disable crt_static_allows_dylibs in redox targets --- compiler/rustc_target/src/spec/base/redox.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/base/redox.rs b/compiler/rustc_target/src/spec/base/redox.rs index e0a0c20c56d63..e9b47f3fa3fdb 100644 --- a/compiler/rustc_target/src/spec/base/redox.rs +++ b/compiler/rustc_target/src/spec/base/redox.rs @@ -12,7 +12,7 @@ pub(crate) fn opts() -> TargetOptions { has_thread_local: true, crt_static_default: true, crt_static_respected: true, - crt_static_allows_dylibs: true, + crt_static_allows_dylibs: false, late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-lgcc"]), ..Default::default() } From fa0f1630d67d06c03ceb61b4a7fb970032b161db Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 26 Oct 2025 11:41:23 +0000 Subject: [PATCH 08/11] Add riscv64gc-unknown-redox Co-Authored-By: Jeremy Soller --- compiler/rustc_target/src/spec/mod.rs | 1 + .../spec/targets/riscv64gc_unknown_redox.rs | 25 +++++++++++++++++++ src/bootstrap/src/core/sanity.rs | 1 + src/doc/rustc/src/platform-support.md | 1 + src/doc/rustc/src/platform-support/redox.md | 2 ++ tests/assembly-llvm/targets/targets-elf.rs | 3 +++ 6 files changed, 33 insertions(+) create mode 100644 compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1638c87c9ca9a..39a260f9a9b44 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1553,6 +1553,7 @@ supported_targets! { ("aarch64-unknown-redox", aarch64_unknown_redox), ("i586-unknown-redox", i586_unknown_redox), + ("riscv64gc-unknown-redox", riscv64gc_unknown_redox), ("x86_64-unknown-redox", x86_64_unknown_redox), ("x86_64-unknown-managarm-mlibc", x86_64_unknown_managarm_mlibc), diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs new file mode 100644 index 0000000000000..01276a8be465e --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_redox.rs @@ -0,0 +1,25 @@ +use crate::spec::{CodeModel, Target, TargetMetadata, base}; + +pub(crate) fn target() -> Target { + let mut base = base::redox::opts(); + base.code_model = Some(CodeModel::Medium); + base.cpu = "generic-rv64".into(); + base.features = "+m,+a,+f,+d,+c".into(); + base.llvm_abiname = "lp64d".into(); + base.plt_by_default = false; + base.max_atomic_width = Some(64); + + Target { + llvm_target: "riscv64-unknown-redox".into(), + metadata: TargetMetadata { + description: Some("Redox OS".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(true), + }, + pointer_width: 64, + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), + arch: "riscv64".into(), + options: base, + } +} diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index d0405270f6634..08e5abc0a03b1 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -34,6 +34,7 @@ pub struct Finder { // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined + "riscv64gc-unknown-redox", ]; /// Minimum version threshold for libstdc++ required when using prebuilt LLVM diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 4eb0dabe5952c..99739ee734e4c 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -393,6 +393,7 @@ target | std | host | notes [`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD [`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64 +[`riscv64gc-unknown-redox`](platform-support/redox.md) | ✓ | | RISC-V 64bit Redox OS [`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ | | RISC-V 64bit with NuttX [`riscv64a23-unknown-linux-gnu`](platform-support/riscv64a23-unknown-linux-gnu.md) | ✓ | ✓ | RISC-V Linux (kernel 6.8.0+, glibc 2.39) [`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | ✓ | | S390x Linux (kernel 3.2, musl 1.2.3) diff --git a/src/doc/rustc/src/platform-support/redox.md b/src/doc/rustc/src/platform-support/redox.md index fc36a551c8617..02ba5254d196c 100644 --- a/src/doc/rustc/src/platform-support/redox.md +++ b/src/doc/rustc/src/platform-support/redox.md @@ -10,6 +10,7 @@ Target triplets available so far: - `x86_64-unknown-redox` (tier 2) - `aarch64-unknown-redox` (tier 3) - `i586-unknown-redox` (tier 3) +- `riscv64gc-unknown-redox` (tier 3) ## Target maintainers @@ -37,6 +38,7 @@ target = [ "x86_64-unknown-redox", "aarch64-unknown-redox", "i586-unknown-redox", + "riscv64gc-unknown-redox", ] ``` diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index e26c213837066..6c85dbcfed1a5 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -505,6 +505,9 @@ //@ revisions: riscv64gc_unknown_openbsd //@ [riscv64gc_unknown_openbsd] compile-flags: --target riscv64gc-unknown-openbsd //@ [riscv64gc_unknown_openbsd] needs-llvm-components: riscv +//@ revisions: riscv64gc_unknown_redox +//@ [riscv64gc_unknown_redox] compile-flags: --target riscv64gc-unknown-redox +//@ [riscv64gc_unknown_redox] needs-llvm-components: riscv //@ revisions: riscv64imac_unknown_none_elf //@ [riscv64imac_unknown_none_elf] compile-flags: --target riscv64imac-unknown-none-elf //@ [riscv64imac_unknown_none_elf] needs-llvm-components: riscv From 4d7c784caf1964d75cc41f8243560fb3553f2474 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:43:14 +0000 Subject: [PATCH 09/11] Handle default features and -Ctarget-features in the dummy backend This prevents a warning about ABI relevant target features not being set on x86 and arm. In addition it is required for miri to report correct features in is_*_feature_detected!() if miri switches to the dummy backend. --- compiler/rustc_interface/src/util.rs | 30 +++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 5e9cb42365049..56c3f65d8ae8e 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -9,8 +9,9 @@ use rustc_ast as ast; use rustc_attr_parsing::{ShouldEmit, validate_attr}; use rustc_codegen_ssa::back::archive::ArArchiveBuilderBuilder; use rustc_codegen_ssa::back::link::link_binary; +use rustc_codegen_ssa::target_features::{self, cfg_target_feature}; use rustc_codegen_ssa::traits::CodegenBackend; -use rustc_codegen_ssa::{CodegenResults, CrateInfo}; +use rustc_codegen_ssa::{CodegenResults, CrateInfo, TargetConfig}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::sync; @@ -354,6 +355,33 @@ impl CodegenBackend for DummyCodegenBackend { "dummy" } + fn target_config(&self, sess: &Session) -> TargetConfig { + let (target_features, unstable_target_features) = cfg_target_feature(sess, |feature| { + // This is a standin for the list of features a backend is expected to enable. + // It would be better to parse target.features instead and handle implied features, + // but target.features is a list of LLVM target features, not Rust target features. + // The dummy backend doesn't know the mapping between LLVM and Rust target features. + sess.target.abi_required_features().required.contains(&feature) + }); + + // To report warnings about unknown features + target_features::flag_to_backend_features::<0>( + sess, + true, + |_| Default::default(), + |_, _| {}, + ); + + TargetConfig { + target_features, + unstable_target_features, + has_reliable_f16: true, + has_reliable_f16_math: true, + has_reliable_f128: true, + has_reliable_f128_math: true, + } + } + fn supported_crate_types(&self, _sess: &Session) -> Vec { // This includes bin despite failing on the link step to ensure that you // can still get the frontend handling for binaries. For all library From 958d0a3836de16d10b3dee2cfa5aa74671cf04c4 Mon Sep 17 00:00:00 2001 From: Lewis McClelland Date: Wed, 29 Oct 2025 17:52:05 -0400 Subject: [PATCH 10/11] Align VEX V5 boot routine to 4 bytes --- .../src/spec/targets/armv7a_vex_v5_linker_script.ld | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/armv7a_vex_v5_linker_script.ld b/compiler/rustc_target/src/spec/targets/armv7a_vex_v5_linker_script.ld index 0f3e6eeee19a3..e0fa5dc301846 100644 --- a/compiler/rustc_target/src/spec/targets/armv7a_vex_v5_linker_script.ld +++ b/compiler/rustc_target/src/spec/targets/armv7a_vex_v5_linker_script.ld @@ -60,7 +60,7 @@ SECTIONS { /* * Executable program instructions. */ - .text : { + .text ALIGN(4) : { /* _boot routine (entry point from VEXos, must be at 0x03800020) */ *(.boot) From e0b8dd38bc5657df6dd6d78d0930f530f90361f0 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 20 Oct 2025 20:38:04 +0000 Subject: [PATCH 11/11] Simplify rustc_public context handling We no longer need two thread-local variables to store the context. We used to have two because the conversion logic used to live in a separate crate from the rest of the business logic. I'm also removing the Container struct and replacing the CompilerInterface trait with a struct. This removes the unnecessary indirection and code duplication. Using a trait would also block us from adding any generic method to the compiler interface. --- .../rustc_public/src/compiler_interface.rs | 449 +++++------------- .../rustc_public/src/rustc_internal/mod.rs | 42 +- compiler/rustc_public_bridge/src/lib.rs | 7 - 3 files changed, 124 insertions(+), 374 deletions(-) diff --git a/compiler/rustc_public/src/compiler_interface.rs b/compiler/rustc_public/src/compiler_interface.rs index 5a09c3b24f0f1..b17d31f2b91ab 100644 --- a/compiler/rustc_public/src/compiler_interface.rs +++ b/compiler/rustc_public/src/compiler_interface.rs @@ -3,11 +3,11 @@ //! rustc_public users should not use any of the items in this module directly. //! These APIs have no stability guarantee. -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use rustc_hir::def::DefKind; use rustc_public_bridge::context::CompilerCtxt; -use rustc_public_bridge::{Bridge, Container}; +use rustc_public_bridge::{Bridge, Tables}; use tracing::debug; use crate::abi::{FnAbi, Layout, LayoutShape, ReprOptions}; @@ -68,256 +68,17 @@ impl Bridge for BridgeTys { /// Public API for querying compiler information. /// -/// All queries are delegated to [`rustc_public_bridge::context::CompilerCtxt`] that provides -/// similar APIs but based on internal rustc constructs. +/// All queries are delegated to [`rustc_public_bridge::context::CompilerCtxt`] +/// 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) trait CompilerInterface { - 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; +pub(crate) struct CompilerInterface<'tcx> { + pub tables: RefCell>, + pub cx: RefCell>, } -impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { - fn entry_fn(&self) -> Option { +impl<'tcx> CompilerInterface<'tcx> { + pub(crate) fn entry_fn(&self) -> Option { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = cx.entry_fn(); @@ -325,7 +86,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&self) -> CrateItems { + pub(crate) 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() @@ -333,7 +94,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { /// Retrieve the body of a function. /// This function will panic if the body is not available. - fn mir_body(&self, item: DefId) -> mir::Body { + pub(crate) fn mir_body(&self, item: DefId) -> mir::Body { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let did = tables[item]; @@ -341,14 +102,14 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Check whether the body of a function is available. - fn has_body(&self, item: DefId) -> bool { + pub(crate) 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) } - fn foreign_modules(&self, crate_num: CrateNum) -> Vec { + pub(crate) 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)) @@ -358,7 +119,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve all functions defined in this crate. - fn crate_functions(&self, crate_num: CrateNum) -> Vec { + pub(crate) 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); @@ -366,75 +127,75 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve all static items defined in this crate. - fn crate_statics(&self, crate_num: CrateNum) -> Vec { + pub(crate) 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() } - fn foreign_module(&self, mod_def: ForeignModuleDef) -> ForeignModule { + pub(crate) 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) } - fn foreign_items(&self, mod_def: ForeignModuleDef) -> Vec { + pub(crate) 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() } - fn all_trait_decls(&self) -> TraitDecls { + pub(crate) 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() } - fn trait_decls(&self, crate_num: CrateNum) -> TraitDecls { + pub(crate) 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() } - fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl { + pub(crate) 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) } - fn all_trait_impls(&self) -> ImplTraitDecls { + pub(crate) 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() } - fn trait_impls(&self, crate_num: CrateNum) -> ImplTraitDecls { + pub(crate) 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() } - fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait { + pub(crate) 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) } - fn generics_of(&self, def_id: DefId) -> Generics { + pub(crate) 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) } - fn predicates_of(&self, def_id: DefId) -> GenericPredicates { + pub(crate) 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]; @@ -448,7 +209,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } } - fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates { + pub(crate) 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]; @@ -463,25 +224,25 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get information about the local crate. - fn local_crate(&self) -> Crate { + pub(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. - fn external_crates(&self) -> Vec { + pub(crate) 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. - fn find_crates(&self, name: &str) -> Vec { + pub(crate) 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`. - fn def_name(&self, def_id: DefId, trimmed: bool) -> Symbol { + pub(crate) 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]; @@ -495,7 +256,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { /// /// 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 { + pub(crate) 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]; @@ -506,7 +267,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get all tool attributes of a definition. - fn all_tool_attrs(&self, def_id: DefId) -> Vec { + pub(crate) 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]; @@ -517,7 +278,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns printable, human readable form of `Span`. - fn span_to_string(&self, span: Span) -> String { + pub(crate) fn span_to_string(&self, span: Span) -> String { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let sp = tables.spans[span]; @@ -525,7 +286,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Return filename from given `Span`, for diagnostic purposes. - fn get_filename(&self, span: &Span) -> Filename { + pub(crate) fn get_filename(&self, span: &Span) -> Filename { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let sp = tables.spans[*span]; @@ -533,7 +294,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Return lines corresponding to this `Span`. - fn get_lines(&self, span: &Span) -> LineInfo { + pub(crate) fn get_lines(&self, span: &Span) -> LineInfo { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let sp = tables.spans[*span]; @@ -542,7 +303,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the `kind` of given `DefId`. - fn item_kind(&self, item: CrateItem) -> ItemKind { + pub(crate) fn item_kind(&self, item: CrateItem) -> ItemKind { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); let did = tables[item.0]; @@ -550,7 +311,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns whether this is a foreign item. - fn is_foreign_item(&self, item: DefId) -> bool { + pub(crate) fn is_foreign_item(&self, item: DefId) -> bool { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); let did = tables[item]; @@ -558,7 +319,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the kind of a given foreign item. - fn foreign_item_kind(&self, def: ForeignDef) -> ForeignItemKind { + pub(crate) 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()]; @@ -575,42 +336,42 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the kind of a given algebraic data type. - fn adt_kind(&self, def: AdtDef) -> AdtKind { + pub(crate) 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. - fn adt_is_box(&self, def: AdtDef) -> bool { + pub(crate) 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. - fn adt_is_simd(&self, def: AdtDef) -> bool { + pub(crate) 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. - fn adt_is_cstr(&self, def: AdtDef) -> bool { + pub(crate) 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 - fn adt_repr(&self, def: AdtDef) -> ReprOptions { + pub(crate) 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. - fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig { + pub(crate) 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); @@ -619,7 +380,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve the intrinsic definition if the item corresponds one. - fn intrinsic(&self, item: DefId) -> Option { + pub(crate) 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); @@ -627,7 +388,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve the plain function name of an intrinsic. - fn intrinsic_name(&self, def: IntrinsicDef) -> Symbol { + pub(crate) 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); @@ -635,7 +396,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve the closure signature for the given generic arguments. - fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig { + pub(crate) 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); @@ -643,14 +404,14 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// The number of variants in this ADT. - fn adt_variants_len(&self, def: AdtDef) -> usize { + pub(crate) 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. - fn adt_discr_for_variant(&self, adt: AdtDef, variant: VariantIdx) -> Discr { + pub(crate) 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( @@ -661,7 +422,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Discriminant for a given variand index and args of a coroutine. - fn coroutine_discr_for_variant( + pub(crate) fn coroutine_discr_for_variant( &self, coroutine: CoroutineDef, args: &GenericArgs, @@ -677,13 +438,13 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// The name of a variant. - fn variant_name(&self, def: VariantDef) -> Symbol { + pub(crate) 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)) } - fn variant_fields(&self, def: VariantDef) -> Vec { + pub(crate) 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) @@ -694,14 +455,14 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Evaluate constant as a target usize. - fn eval_target_usize(&self, mir_const: &MirConst) -> Result { + pub(crate) 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) } - fn eval_target_usize_ty(&self, ty_const: &TyConst) -> Result { + pub(crate) 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); @@ -709,7 +470,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Create a new zero-sized constant. - fn try_new_const_zst(&self, ty: Ty) -> Result { + pub(crate) 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); @@ -717,28 +478,36 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Create a new constant that represents the given string value. - fn new_const_str(&self, value: &str) -> MirConst { + pub(crate) 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. - fn new_const_bool(&self, value: bool) -> MirConst { + pub(crate) 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. - fn try_new_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + pub(crate) 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)) } - fn try_new_ty_const_uint(&self, value: u128, uint_ty: UintTy) -> Result { + pub(crate) 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)); @@ -746,7 +515,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Create a new type from the given kind. - fn new_rigid_ty(&self, kind: RigidTy) -> Ty { + pub(crate) 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); @@ -754,7 +523,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Create a new box type, `Box`, for the given inner type `T`. - fn new_box_ty(&self, ty: Ty) -> Ty { + pub(crate) 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); @@ -762,7 +531,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the type of given crate item. - fn def_ty(&self, item: DefId) -> Ty { + pub(crate) 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); @@ -770,7 +539,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns the type of given definition instantiated with the given arguments. - fn def_ty_with_args(&self, item: DefId, args: &GenericArgs) -> Ty { + pub(crate) 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); @@ -779,42 +548,42 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Returns literal value of a const as a string. - fn mir_const_pretty(&self, cnst: &MirConst) -> String { + pub(crate) 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. - fn span_of_an_item(&self, def_id: DefId) -> Span { + pub(crate) 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) } - fn ty_const_pretty(&self, ct: TyConstId) -> String { + pub(crate) 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. - fn ty_pretty(&self, ty: Ty) -> String { + pub(crate) 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 kind of a type. - fn ty_kind(&self, ty: Ty) -> TyKind { + pub(crate) 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. - fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> Ty { + pub(crate) 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); @@ -822,7 +591,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the body of an Instance which is already monomorphized. - fn instance_body(&self, instance: InstanceDef) -> Option { + pub(crate) fn instance_body(&self, instance: InstanceDef) -> Option { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[instance]; @@ -830,7 +599,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the instance type with generic instantiations applied and lifetimes erased. - fn instance_ty(&self, instance: InstanceDef) -> Ty { + pub(crate) fn instance_ty(&self, instance: InstanceDef) -> Ty { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[instance]; @@ -838,7 +607,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the instantiation types. - fn instance_args(&self, def: InstanceDef) -> GenericArgs { + pub(crate) fn instance_args(&self, def: InstanceDef) -> GenericArgs { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[def]; @@ -846,7 +615,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the instance. - fn instance_def_id(&self, instance: InstanceDef) -> DefId { + pub(crate) 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]; @@ -854,7 +623,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the instance mangled name. - fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol { + pub(crate) fn instance_mangled_name(&self, instance: InstanceDef) -> Symbol { let tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[instance]; @@ -862,7 +631,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Check if this is an empty DropGlue shim. - fn is_empty_drop_shim(&self, def: InstanceDef) -> bool { + pub(crate) 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]; @@ -871,7 +640,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { /// 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 { + pub(crate) 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]; @@ -879,7 +648,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Item requires monomorphization. - fn requires_monomorphization(&self, def_id: DefId) -> bool { + pub(crate) fn requires_monomorphization(&self, def_id: DefId) -> bool { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); let did = tables[def_id]; @@ -887,7 +656,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option { + pub(crate) 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); @@ -896,7 +665,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Resolve an instance for drop_in_place for the given type. - fn resolve_drop_in_place(&self, ty: Ty) -> Instance { + pub(crate) 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); @@ -905,7 +674,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Resolve instance for a function pointer. - fn resolve_for_fn_ptr(&self, def: FnDef, args: &GenericArgs) -> Option { + pub(crate) 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); @@ -914,7 +683,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Resolve instance for a closure with the requested type. - fn resolve_closure( + pub(crate) fn resolve_closure( &self, def: ClosureDef, args: &GenericArgs, @@ -929,7 +698,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Evaluate a static's initializer. - fn eval_static_initializer(&self, def: StaticDef) -> Result { + pub(crate) 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); @@ -938,7 +707,11 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Try to evaluate an instance into a constant. - fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result { + pub(crate) 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(); @@ -949,7 +722,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve global allocation for the given allocation ID. - fn global_alloc(&self, id: AllocId) -> GlobalAlloc { + pub(crate) 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); @@ -957,7 +730,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Retrieve the id for the virtual table. - fn vtable_allocation(&self, global_alloc: &GlobalAlloc) -> Option { + pub(crate) 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; @@ -969,13 +742,13 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { Some(alloc_id.stable(&mut *tables, cx)) } - fn krate(&self, def_id: DefId) -> Crate { + pub(crate) fn krate(&self, def_id: DefId) -> Crate { let tables = self.tables.borrow(); let cx = &*self.cx.borrow(); smir_crate(cx, tables[def_id].krate) } - fn instance_name(&self, def: InstanceDef, trimmed: bool) -> Symbol { + pub(crate) 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]; @@ -983,7 +756,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Return information about the target machine. - fn target_info(&self) -> MachineInfo { + pub(crate) fn target_info(&self) -> MachineInfo { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); MachineInfo { @@ -993,7 +766,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get an instance ABI. - fn instance_abi(&self, def: InstanceDef) -> Result { + pub(crate) fn instance_abi(&self, def: InstanceDef) -> Result { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); let instance = tables.instances[def]; @@ -1001,7 +774,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the ABI of a function pointer. - fn fn_ptr_abi(&self, fn_ptr: PolyFnSig) -> Result { + pub(crate) 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); @@ -1009,7 +782,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the layout of a type. - fn ty_layout(&self, ty: Ty) -> Result { + pub(crate) 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); @@ -1017,14 +790,14 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the layout shape. - fn layout_shape(&self, id: Layout) -> LayoutShape { + pub(crate) 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. - fn place_pretty(&self, place: &Place) -> String { + pub(crate) fn place_pretty(&self, place: &Place) -> String { let mut tables = self.tables.borrow_mut(); let cx = &*self.cx.borrow(); @@ -1032,7 +805,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the resulting type of binary operation. - fn binop_ty(&self, bin_op: BinOp, rhs: Ty, lhs: Ty) -> Ty { + pub(crate) 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); @@ -1042,7 +815,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get the resulting type of unary operation. - fn unop_ty(&self, un_op: UnOp, arg: Ty) -> Ty { + pub(crate) 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); @@ -1051,7 +824,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { } /// Get all associated items of a definition. - fn associated_items(&self, def_id: DefId) -> AssocItems { + pub(crate) 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]; @@ -1062,7 +835,7 @@ impl<'tcx> CompilerInterface for Container<'tcx, BridgeTys> { // A thread local variable that stores a pointer to [`CompilerInterface`]. scoped_tls::scoped_thread_local!(static TLV: Cell<*const ()>); -pub(crate) fn run(interface: &dyn CompilerInterface, f: F) -> Result +pub(crate) fn run<'tcx, F, T>(interface: &CompilerInterface<'tcx>, f: F) -> Result where F: FnOnce() -> T, { @@ -1078,12 +851,12 @@ 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(&dyn CompilerInterface) -> R) -> R { +pub(crate) fn with(f: impl for<'tcx> FnOnce(&CompilerInterface<'tcx>) -> R) -> R { assert!(TLV.is_set()); TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - f(unsafe { *(ptr as *const &dyn CompilerInterface) }) + f(unsafe { *(ptr as *const &CompilerInterface<'_>) }) }) } diff --git a/compiler/rustc_public/src/rustc_internal/mod.rs b/compiler/rustc_public/src/rustc_internal/mod.rs index 225c811ab3a54..7772a3982a7cb 100644 --- a/compiler/rustc_public/src/rustc_internal/mod.rs +++ b/compiler/rustc_public/src/rustc_internal/mod.rs @@ -3,15 +3,15 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until rustc_public's IR is complete. -use std::cell::{Cell, RefCell}; +use std::cell::RefCell; use rustc_middle::ty::TyCtxt; +use rustc_public_bridge::Tables; use rustc_public_bridge::context::CompilerCtxt; -use rustc_public_bridge::{Bridge, Container, Tables}; use rustc_span::def_id::CrateNum; -use scoped_tls::scoped_thread_local; use crate::Error; +use crate::compiler_interface::{BridgeTys, CompilerInterface, with}; use crate::unstable::{RustcInternal, Stable}; pub mod pretty; @@ -28,7 +28,7 @@ pub mod pretty; /// /// This function will panic if rustc_public has not been properly initialized. pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T { - with_container(|tables, cx| item.stable(tables, cx)) + with_bridge(|tables, cx| item.stable(tables, cx)) } /// Convert a stable item into its internal Rust compiler counterpart, if one exists. @@ -49,38 +49,21 @@ where // The tcx argument ensures that the item won't outlive the type context. // See https://github.com/rust-lang/rust/pull/120128/commits/9aace6723572438a94378451793ca37deb768e72 // for more details. - with_container(|tables, _| item.internal(tables, tcx)) + with_bridge(|tables, _| item.internal(tables, tcx)) } pub fn crate_num(item: &crate::Crate) -> CrateNum { item.id.into() } -// A thread local variable that stores a pointer to the tables mapping between TyCtxt -// datastructures and rustc_public's IR datastructures -scoped_thread_local! (static TLV: Cell<*const ()>); - -pub(crate) fn init<'tcx, F, T, B: Bridge>(container: &Container<'tcx, B>, f: F) -> T -where - F: FnOnce() -> T, -{ - assert!(!TLV.is_set()); - 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_container( - f: impl for<'tcx> FnOnce(&mut Tables<'tcx, B>, &CompilerCtxt<'tcx, B>) -> R, +pub(crate) fn with_bridge( + f: impl for<'tcx> FnOnce(&mut Tables<'tcx, BridgeTys>, &CompilerCtxt<'tcx, BridgeTys>) -> R, ) -> R { - assert!(TLV.is_set()); - TLV.with(|tlv| { - let ptr = tlv.get(); - assert!(!ptr.is_null()); - let container = ptr as *const Container<'_, B>; - let mut tables = unsafe { (*container).tables.borrow_mut() }; - let cx = unsafe { (*container).cx.borrow() }; + with(|compiler| { + let mut tables = compiler.tables.borrow_mut(); + let cx = compiler.cx.borrow(); f(&mut *tables, &*cx) }) } @@ -90,9 +73,10 @@ where F: FnOnce() -> T, { let compiler_cx = RefCell::new(CompilerCtxt::new(tcx)); - let container = Container { tables: RefCell::new(Tables::default()), cx: compiler_cx }; + let compiler_interface = + CompilerInterface { tables: RefCell::new(Tables::default()), cx: compiler_cx }; - crate::compiler_interface::run(&container, || init(&container, f)) + crate::compiler_interface::run(&compiler_interface, || f()) } /// Instantiate and run the compiler with the provided arguments and callback. diff --git a/compiler/rustc_public_bridge/src/lib.rs b/compiler/rustc_public_bridge/src/lib.rs index 1c38cb6c4bdfc..d0b417c550dc9 100644 --- a/compiler/rustc_public_bridge/src/lib.rs +++ b/compiler/rustc_public_bridge/src/lib.rs @@ -24,7 +24,6 @@ #![feature(trait_alias)] // tidy-alphabetical-end -use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::ops::Index; @@ -49,12 +48,6 @@ pub mod rustc_internal {} /// Trait alias for types that can be cached in [`Tables`]. pub trait Cacheable = Copy + Debug + PartialEq + IndexedVal; -/// A container which is used for TLS. -pub struct Container<'tcx, B: Bridge> { - pub tables: RefCell>, - pub cx: RefCell>, -} - pub struct Tables<'tcx, B: Bridge> { pub def_ids: IndexMap, pub alloc_ids: IndexMap,