From b347a01b5448c644adcb1905cee7283a35a25460 Mon Sep 17 00:00:00 2001 From: "Farya L. M." Date: Wed, 28 Oct 2026 21:09:50 +0100 Subject: [PATCH 01/11] stuff --- compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs | 3 +++ compiler/rustc_metadata/src/rmeta/mod.rs | 3 +++ compiler/rustc_middle/src/queries.rs | 8 ++++++++ compiler/rustc_middle/src/query/keys.rs | 6 ++++++ compiler/rustc_session/src/options.rs | 4 +++- 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 154cf4f060a9e..9c6a283318de9 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -621,6 +621,9 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { .map(|c| *c), ) }, + experimental_comptime_fetch_file: |tcx, (crate, filename): (CrateNum, &str)| { + panic!() + }, ..providers.queries }; provide_extern(&mut providers.extern_queries); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index c389a5ea6afcf..e27c068618a7b 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -722,6 +722,9 @@ define_tables! { associated_types_for_impl_traits_in_trait_or_impl: Table>>>, args_known_to_outlive_alias_params: Table)>>>, mut_restriction: Table>, + + comptime_used_files: Table>>, + } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 56889f84f38d6..a29718a004d3d 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2852,6 +2852,14 @@ rustc_queries! { desc { "calculating all fake doc items" } } + /// Query data from non-local crates + query experimental_comptime_fetch_file(key: (CrateNum, &'tcx str)) -> Option<&'tcx Box<[u8]>> { + desc { "fetch file {} from crate {}", key.1, key.0 } + eval_always + no_hash + separate_provide_extern + } + //----------------------------------------------------------------------------- // "Non-queries" are special dep kinds that are not queries. //----------------------------------------------------------------------------- diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 2bfe80f444090..4323a8f463189 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -420,6 +420,12 @@ impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) { } } +impl<'tcx> QueryKey for (CrateNum, &'tcx str) { + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} + /// Gets a `DefId` associated with a type /// /// Visited set is needed to avoid full iteration over diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9ac479e8abe51..088e68eea682b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2448,7 +2448,7 @@ options! { codegen_emit_retag: Option = (None, parse_codegen_retag_options, [TRACKED], "emit retag function calls in generated code"), codegen_source_order: bool = (false, parse_bool, [UNTRACKED], - "emit mono items in the order of spans in source files (default: no)"), + "emit mono items in the order of spans in source files (default: no)"), contract_checks: Option = (None, parse_opt_bool, [TRACKED], "emit runtime checks for contract pre- and post-conditions (default: no)"), coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED], @@ -2527,6 +2527,8 @@ options! { "emit a section containing stack size metadata (default: no)"), enforce_type_length_limit: bool = (false, parse_bool, [TRACKED], "enforce the type length limit when monomorphizing instances in codegen"), + experimental_comptime_files: Vec = (Vec::new(), parse_string_push, [UNTRACKED], + "enable access to a file in comptime"), experimental_default_bounds: bool = (false, parse_bool, [TRACKED], "enable default bounds for experimental group of auto traits"), export_executable_symbols: bool = (false, parse_bool, [TRACKED], From 7da399f59d50210f2d170ddac73a230b7121954a Mon Sep 17 00:00:00 2001 From: Lamb Date: Thu, 29 Oct 2026 22:22:44 +0000 Subject: [PATCH 02/11] feat: add file reading query and rmeta encoding/decoding of comptime files --- .../src/const_eval/comptime_fs.rs | 17 +++++++++++++++++ compiler/rustc_const_eval/src/const_eval/mod.rs | 1 + compiler/rustc_const_eval/src/lib.rs | 2 ++ compiler/rustc_metadata/src/rmeta/decoder.rs | 7 +++++++ .../src/rmeta/decoder/cstore_impl.rs | 13 ++++++++++--- compiler/rustc_metadata/src/rmeta/encoder.rs | 8 ++++++++ compiler/rustc_metadata/src/rmeta/mod.rs | 7 ++++--- .../rustc_metadata/src/rmeta/parameterized.rs | 1 + compiler/rustc_middle/src/queries.rs | 4 +--- compiler/rustc_middle/src/query/erase.rs | 1 + compiler/rustc_middle/src/query/keys.rs | 9 ++++++++- compiler/rustc_middle/src/ty/context.rs | 5 ++++- 12 files changed, 64 insertions(+), 11 deletions(-) create mode 100644 compiler/rustc_const_eval/src/const_eval/comptime_fs.rs diff --git a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs new file mode 100644 index 0000000000000..f2440927e17a6 --- /dev/null +++ b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs @@ -0,0 +1,17 @@ +use rustc_middle::ty::TyCtxt; +use tracing::instrument; + +#[instrument(skip(tcx), level = "debug")] +pub fn experimental_comptime_fetch_file_provider<'tcx>( + tcx: TyCtxt<'tcx>, + key: &'tcx String, +) -> Option<&'tcx [u8]> { + let mut files = tcx.caches.experimental_comptime_files.lock(); + if let Some(value) = files.get(&key) { + Some(*value) + } else { + let file = std::fs::read(key).ok()?; + files.insert(&key, tcx.arena.alloc_slice(&file)); + files.get(&key).map(|d| *d) + } +} diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 58b8418707eff..aca2c085c157c 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -8,6 +8,7 @@ use tracing::instrument; use crate::interpret::InterpCx; +pub(crate) mod comptime_fs; mod dummy_machine; mod dyn_trait; mod error; diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 091f0f71cc50d..b82b60b657094 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -61,6 +61,8 @@ pub fn provide(providers: &mut Providers) { }; providers.hooks.validate_scalar_in_layout = |tcx, scalar, layout| util::validate_scalar_in_layout(tcx, scalar, layout); + providers.queries.experimental_comptime_fetch_file = + const_eval::comptime_fs::experimental_comptime_fetch_file_provider; } /// `rustc_driver::main` installs a handler that will set this to `true` if diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 8ac88f0c9bd63..b7314fc9ae2f7 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1029,6 +1029,13 @@ impl CrateRoot { ) -> impl ExactSizeIterator { self.denied_partial_mitigations.decode(metadata) } + + pub(crate) fn decode_comptime_files<'a>( + &self, + metadata: &'a MetadataBlob, + ) -> impl ExactSizeIterator)> { + self.comptime_files.decode(metadata) + } } impl CrateMetadata { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9c6a283318de9..b51b2abc396c8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -621,12 +621,19 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { .map(|c| *c), ) }, - experimental_comptime_fetch_file: |tcx, (crate, filename): (CrateNum, &str)| { - panic!() - }, ..providers.queries }; provide_extern(&mut providers.extern_queries); + + providers.extern_queries.experimental_comptime_fetch_file = |tcx, (cnum, key)| { + let cstore = CStore::from_tcx(tcx); + let crate_data = cstore.get_crate_data(cnum); + crate_data + .root + .decode_comptime_files(&crate_data.blob) + .find(|(path, _)| key == path) + .map(|(_, data)| &*tcx.arena.alloc_slice(data.as_ref())) + }; } impl CStore { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index b107b1fe13c7f..0f382ea40a19e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -771,6 +771,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let denied_partial_mitigations = stat!("denied-partial-mitigations", || self .encode_enabled_denied_partial_mitigations()); + let comptime_files = tcx.caches.experimental_comptime_files.borrow(); + let comptime_files = + comptime_files.iter().map(|(k, v)| ((*k).clone(), v.to_vec())).collect::>(); + + // Should I somehow sort by filename here in case this does *anything* with the parallel frontend stuff or something? + let comptime_files = self.lazy_array(comptime_files); + let root = stat!("crate-root", || { let attrs = tcx.hir_krate_attrs(); self.lazy(CrateRoot { @@ -829,6 +836,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { expn_hashes, def_path_hash_map, specialization_enabled_in: tcx.specialization_enabled_in(LOCAL_CRATE), + comptime_files, }) }); diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index e27c068618a7b..9c41a0357de7f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -331,6 +331,9 @@ pub(crate) struct CrateRoot { symbol_mangling_version: SymbolManglingVersion, specialization_enabled_in: bool, + + // LazyTable maybe?? + comptime_files: LazyArray<(String, Vec)>, } /// A separate struct for extra metadata that must be encoded *after* @@ -653,6 +656,7 @@ define_tables! { defaultness: Table, impl_is_fully_generic_for_reflection: Table, + - optional: opt_rpitit_info: Table>, attributes: Table>, @@ -722,9 +726,6 @@ define_tables! { associated_types_for_impl_traits_in_trait_or_impl: Table>>>, args_known_to_outlive_alias_params: Table)>>>, mut_restriction: Table>, - - comptime_used_files: Table>>, - } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index f7a4661430916..1c631b5838739 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -70,6 +70,7 @@ macro_rules! trivially_parameterized_over_tcx { trivially_parameterized_over_tcx! { bool, + u8, u32, u64, usize, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index a29718a004d3d..4db81edde4cc8 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2853,10 +2853,8 @@ rustc_queries! { } /// Query data from non-local crates - query experimental_comptime_fetch_file(key: (CrateNum, &'tcx str)) -> Option<&'tcx Box<[u8]>> { + query experimental_comptime_fetch_file(key: (CrateNum, &'tcx String)) -> Option<&'tcx [u8]> { desc { "fetch file {} from crate {}", key.1, key.0 } - eval_always - no_hash separate_provide_extern } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index b0281a70eeb73..72f9c94c0dc51 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -181,6 +181,7 @@ impl_erasable_for_types_with_no_type_params! { (traits::solve::QueryResult<'_>, &'_ traits::solve::inspect::Probe>, ty::RequiredDepth), Option<&'_ OsStr>, Option<&'_ [rustc_hir::PreciseCapturingArgKind]>, + Option<&'_ [u8]>, Option<(mir::ConstValue, Ty<'_>)>, Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>, Option, diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 4323a8f463189..fe96d91fa8aee 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -420,7 +420,14 @@ impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) { } } -impl<'tcx> QueryKey for (CrateNum, &'tcx str) { +impl<'tcx> QueryKey for (CrateNum, &'tcx String) { + type LocalQueryKey = &'tcx String; + + #[inline(always)] + fn as_local_key(&self) -> Option { + (self.0 == LOCAL_CRATE).then(|| self.1) + } + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 2e71a7c72603d..9b126aea0f1f0 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -21,7 +21,7 @@ use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; use rustc_crate_store::{CrateStoreDyn, Untracked}; use rustc_data_structures::defer; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_data_structures::intern::Interned; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -711,6 +711,9 @@ pub struct GlobalCaches<'tcx> { /// Caches the instantiation of a canonical binder given a set of args. pub clauses_cache: Lock, &'tcx [ty::GenericArg<'tcx>]), ty::Clauses<'tcx>>>, + + /// Cache of files that have been read by the const evaluator + pub experimental_comptime_files: Lock>, } /// The central data structure of the compiler. It stores references From 3a0e624159a534e3e85d9dcd7aa24164e7532cb2 Mon Sep 17 00:00:00 2001 From: Lamb Date: Fri, 30 Oct 2026 22:42:41 +0000 Subject: [PATCH 03/11] remove caching and use CLI flags for comptime files --- .../rustc_const_eval/src/const_eval/comptime_fs.rs | 12 ++++++------ compiler/rustc_metadata/src/rmeta/encoder.rs | 9 ++++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs index f2440927e17a6..05c8794972d15 100644 --- a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs +++ b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs @@ -6,12 +6,12 @@ pub fn experimental_comptime_fetch_file_provider<'tcx>( tcx: TyCtxt<'tcx>, key: &'tcx String, ) -> Option<&'tcx [u8]> { - let mut files = tcx.caches.experimental_comptime_files.lock(); - if let Some(value) = files.get(&key) { - Some(*value) - } else { + // Very simple implementation where we whitelist paths directly. We don't even attempt + // to canonilize for now. + if tcx.sess.opts.unstable_opts.experimental_comptime_files.contains(key) { let file = std::fs::read(key).ok()?; - files.insert(&key, tcx.arena.alloc_slice(&file)); - files.get(&key).map(|d| *d) + Some(&*tcx.arena.alloc_slice(&file)) + } else { + None } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0f382ea40a19e..9f2f5efc059af 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -771,9 +771,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let denied_partial_mitigations = stat!("denied-partial-mitigations", || self .encode_enabled_denied_partial_mitigations()); - let comptime_files = tcx.caches.experimental_comptime_files.borrow(); - let comptime_files = - comptime_files.iter().map(|(k, v)| ((*k).clone(), v.to_vec())).collect::>(); + let mut comptime_files = Vec::new(); + for file in &tcx.sess.opts.unstable_opts.experimental_comptime_files { + if let Some(file_data) = tcx.experimental_comptime_fetch_file((LOCAL_CRATE, file)) { + comptime_files.push((file.clone(), file_data.to_vec())); + } + } // Should I somehow sort by filename here in case this does *anything* with the parallel frontend stuff or something? let comptime_files = self.lazy_array(comptime_files); From 2c5497e3da5b17c67618f88655d42705b9cafecc Mon Sep 17 00:00:00 2001 From: Lamb Date: Sat, 31 Oct 2026 16:08:07 +0000 Subject: [PATCH 04/11] implement intrinsic and add core support for it --- .../src/const_eval/machine.rs | 32 ++++++++++++++++++- .../rustc_const_eval/src/interpret/operand.rs | 10 ++++-- .../rustc_hir_analysis/src/check/intrinsic.rs | 12 +++++++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics/comptime.rs | 11 +++++++ library/core/src/intrinsics/mod.rs | 1 + library/core/src/mem/comptime.rs | 11 +++++++ library/core/src/mem/mod.rs | 4 +++ 8 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 library/core/src/intrinsics/comptime.rs create mode 100644 library/core/src/mem/comptime.rs diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index cb9432f9832e5..ad97cfa9171ba 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -7,7 +7,7 @@ use rustc_ast::Mutability; use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_lint_defs::builtin::LONG_RUNNING_CONST_EVAL; use rustc_middle::mir::AssertMessage; @@ -598,6 +598,36 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } } + sym::comptime_fetch_file => { + let arg_place = ecx.deref_pointer(&args[0])?; + let key = ecx.read_str(&arg_place)?; + let key = ecx.tcx.arena.alloc(key.to_string()); + + let krate = LOCAL_CRATE; // somehow fetch crate of the object + + let content = ecx.tcx.experimental_comptime_fetch_file((krate, key)); + let variant_index = if let Some(value) = content { + let ptr = ecx.allocate_bytes_dedup(value)?; + + let (variant_idx, variant_place) = + ecx.project_downcast_named(dest, sym::Some)?; + let field_place = ecx.project_field(&variant_place, FieldIdx::ZERO)?; + ecx.write_immediate( + Immediate::ScalarPair( + Scalar::from_pointer(ptr, ecx), + Scalar::from_target_usize(value.len() as u64, ecx), + ), + &field_place, + )?; + + variant_idx + } else { + ecx.project_downcast_named(dest, sym::None)?.0 + }; + + ecx.write_discriminant(variant_index, dest)?; + } + sym::type_id_vtable => { let tp_ty = ecx.read_type_id(&args[0])?; let result_ty = ecx.read_type_id(&args[1])?; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 84cf61c06e790..4c39f23d3596b 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -714,10 +714,16 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { self.read_scalar(op)?.to_target_isize(self) } - /// Turn the wide MPlace into a string (must already be dereferenced!) - pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, &str> { + /// Turn the wide MPlace into a slice of bytes (must already be dereferenced!) + pub fn read_bytes(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, &[u8]> { let len = mplace.len(self)?; let bytes = self.read_bytes_ptr_strip_provenance(mplace.ptr(), Size::from_bytes(len))?; + interp_ok(bytes) + } + + /// Turn the wide MPlace into a string (must already be dereferenced!) + pub fn read_str(&self, mplace: &MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx, &str> { + let bytes = self.read_bytes(mplace)?; let s = std::str::from_utf8(bytes).map_err(|err| err_ub!(InvalidStr(err)))?; interp_ok(s) } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index f30e3c235cbc1..2eb8e649ed177 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -85,6 +85,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::ceil | sym::codeview_annotation | sym::cold_path + | sym::comptime_fetch_file | sym::const_eval_select | sym::contract_check_ensures | sym::contract_check_requires @@ -288,6 +289,17 @@ pub(crate) fn check_intrinsic_type( } sym::needs_drop => (1, 0, vec![], tcx.types.bool), + sym::comptime_fetch_file => { + let slice_u8 = Ty::new_slice(tcx, tcx.types.u8); + let slice_u8_static: Ty<'_> = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, slice_u8); + + let br = ty::BoundRegion { var: ty::BoundVar::ZERO, kind: ty::BoundRegionKind::Anon }; + let var_name = + Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), tcx.types.str_); + + (0, 0, vec![var_name], Ty::new_option(tcx, slice_u8_static)) + } + sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)), sym::type_id => (1, 0, vec![], type_id_ty()), sym::type_id_array_len => (0, 0, vec![type_id_ty()], tcx.types.usize), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 95197e6c98a9f..84526e359026e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -680,6 +680,7 @@ symbols! { compiler_fence, compiler_move, complex, + comptime_fetch_file, concat, concat_bytes, concat_str, diff --git a/library/core/src/intrinsics/comptime.rs b/library/core/src/intrinsics/comptime.rs new file mode 100644 index 0000000000000..341271980e4a1 --- /dev/null +++ b/library/core/src/intrinsics/comptime.rs @@ -0,0 +1,11 @@ +//! Intrinsics for compile time operations + +/// Read a file from the system at comptime time, and returns its bytes. +/// +/// Returns [Option::None] if the file cannot be read. This includes when the file does not exist, or hasn't been +/// made available at comptile time by the compiler. +#[rustc_nounwind] +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn comptime_read_file(file_path_raw: &[u8]) -> Option<&'static [u8]>; diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index d12543e6b35e2..ea6df76b5acf7 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -84,6 +84,7 @@ use crate::num::imp::libm; use crate::{mem, ptr}; mod bounds; +pub mod comptime; pub mod fallback; pub mod gpu; mod macros; diff --git a/library/core/src/mem/comptime.rs b/library/core/src/mem/comptime.rs new file mode 100644 index 0000000000000..febe3cf02109c --- /dev/null +++ b/library/core/src/mem/comptime.rs @@ -0,0 +1,11 @@ +//! MVP for compile-type only operations like reading files + +use std::path::Path; + +#[unstable(feature = "type_info", issue = "146922")] +#[rustc_const_unstable(feature = "type_info", issue = "146922")] +#[rustc_comptime] +pub fn read_file>(path: P) -> Option<&'static [u8]> { + let path = Path::from(path).as_os_str().as_encoded_bytes(); + intrinsics::comptime::comptime_read_file(path) +} diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index a22e52f3a3bc7..8c693a2d9f0e1 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -39,6 +39,7 @@ use crate::ub_checks::assert_unsafe_precondition; use crate::{clone, cmp, fmt, hash, intrinsics, ptr}; mod alignment; + #[unstable(feature = "ptr_alignment_type", issue = "102070")] pub use alignment::Alignment; @@ -71,6 +72,9 @@ pub use crate::intrinsics::transmute; #[unstable(feature = "type_info", issue = "146922")] pub mod type_info; +#[unstable(feature = "type_info", issue = "146922")] +pub mod comptime; + /// Takes ownership and "forgets" about the value **without running its destructor**. /// /// Any resources the value manages, such as heap memory or a file handle, will linger From e5a1b72579412b41c16c31f3cc50b4158273b268 Mon Sep 17 00:00:00 2001 From: Lamb Date: Sat, 31 Oct 2026 17:05:04 +0000 Subject: [PATCH 05/11] use symbol in fetch file query and resolve paths from crate root --- .../src/const_eval/comptime_fs.rs | 34 ++++++++++++++++--- .../src/const_eval/machine.rs | 6 ++-- .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 7 ++-- compiler/rustc_middle/src/queries.rs | 2 +- compiler/rustc_middle/src/query/keys.rs | 4 +-- library/core/src/intrinsics/comptime.rs | 2 +- library/core/src/mem/comptime.rs | 8 ++--- 8 files changed, 44 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs index 05c8794972d15..0a7af3a75f1d4 100644 --- a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs +++ b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs @@ -1,17 +1,41 @@ use rustc_middle::ty::TyCtxt; +use rustc_span::Symbol; use tracing::instrument; #[instrument(skip(tcx), level = "debug")] pub fn experimental_comptime_fetch_file_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: &'tcx String, + key: Symbol, ) -> Option<&'tcx [u8]> { + let Some(crate_root_path) = tcx.sess.io.input.opt_path() else { + return None; + }; + + let requested_path = key.as_str(); + + // Always resolve path from the crate root to provide consistent behavior. + let resolved_path = crate_root_path.with_file_name(requested_path); + // Very simple implementation where we whitelist paths directly. We don't even attempt - // to canonilize for now. - if tcx.sess.opts.unstable_opts.experimental_comptime_files.contains(key) { - let file = std::fs::read(key).ok()?; - Some(&*tcx.arena.alloc_slice(&file)) + // to canonicalize for now. + if tcx + .sess + .opts + .unstable_opts + .experimental_comptime_files + .iter() + .find(|s| requested_path == *s) + .is_some() + { + match std::fs::read(resolved_path) { + Ok(content) => Some(tcx.arena.alloc_slice(&content)), + Err(err) => { + tracing::debug!(%err, "failed to read file"); + None + } + } } else { + tracing::debug!("not allowed to read file"); None } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index ad97cfa9171ba..7a3d94d8ec682 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -600,12 +600,12 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { sym::comptime_fetch_file => { let arg_place = ecx.deref_pointer(&args[0])?; - let key = ecx.read_str(&arg_place)?; - let key = ecx.tcx.arena.alloc(key.to_string()); + let path = ecx.read_str(&arg_place)?; + let path_sym = Symbol::intern(path); let krate = LOCAL_CRATE; // somehow fetch crate of the object - let content = ecx.tcx.experimental_comptime_fetch_file((krate, key)); + let content = ecx.tcx.experimental_comptime_fetch_file((krate, path_sym)); let variant_index = if let Some(value) = content { let ptr = ecx.allocate_bytes_dedup(value)?; diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index b51b2abc396c8..723a4a9451655 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -626,6 +626,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { provide_extern(&mut providers.extern_queries); providers.extern_queries.experimental_comptime_fetch_file = |tcx, (cnum, key)| { + let key = key.as_str(); let cstore = CStore::from_tcx(tcx); let crate_data = cstore.get_crate_data(cnum); crate_data diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 9f2f5efc059af..4015b0241bd5d 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -772,9 +772,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { .encode_enabled_denied_partial_mitigations()); let mut comptime_files = Vec::new(); - for file in &tcx.sess.opts.unstable_opts.experimental_comptime_files { - if let Some(file_data) = tcx.experimental_comptime_fetch_file((LOCAL_CRATE, file)) { - comptime_files.push((file.clone(), file_data.to_vec())); + for raw_path in &tcx.sess.opts.unstable_opts.experimental_comptime_files { + let path = Symbol::intern(raw_path); + if let Some(file_data) = tcx.experimental_comptime_fetch_file((LOCAL_CRATE, path)) { + comptime_files.push((raw_path.clone(), file_data.to_vec())); } } diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 4db81edde4cc8..792cf2693494a 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2853,7 +2853,7 @@ rustc_queries! { } /// Query data from non-local crates - query experimental_comptime_fetch_file(key: (CrateNum, &'tcx String)) -> Option<&'tcx [u8]> { + query experimental_comptime_fetch_file(key: (CrateNum, Symbol)) -> Option<&'tcx [u8]> { desc { "fetch file {} from crate {}", key.1, key.0 } separate_provide_extern } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index fe96d91fa8aee..e81957a568948 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -420,8 +420,8 @@ impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) { } } -impl<'tcx> QueryKey for (CrateNum, &'tcx String) { - type LocalQueryKey = &'tcx String; +impl QueryKey for (CrateNum, Symbol) { + type LocalQueryKey = Symbol; #[inline(always)] fn as_local_key(&self) -> Option { diff --git a/library/core/src/intrinsics/comptime.rs b/library/core/src/intrinsics/comptime.rs index 341271980e4a1..036a31b99ca2e 100644 --- a/library/core/src/intrinsics/comptime.rs +++ b/library/core/src/intrinsics/comptime.rs @@ -8,4 +8,4 @@ #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_comptime] -pub fn comptime_read_file(file_path_raw: &[u8]) -> Option<&'static [u8]>; +pub fn comptime_fetch_file(file_path: &str) -> Option<&'static [u8]>; diff --git a/library/core/src/mem/comptime.rs b/library/core/src/mem/comptime.rs index febe3cf02109c..7fe13e7adbac4 100644 --- a/library/core/src/mem/comptime.rs +++ b/library/core/src/mem/comptime.rs @@ -1,11 +1,9 @@ //! MVP for compile-type only operations like reading files -use std::path::Path; - +/// Read a file at compile time #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] -pub fn read_file>(path: P) -> Option<&'static [u8]> { - let path = Path::from(path).as_os_str().as_encoded_bytes(); - intrinsics::comptime::comptime_read_file(path) +pub fn read_file(path: &str) -> Option<&'static [u8]> { + crate::intrinsics::comptime::comptime_fetch_file(path) } From bca30b772934bcf3f596bc71fb8d3759e868d521 Mon Sep 17 00:00:00 2001 From: Lamb Date: Sat, 31 Oct 2026 18:03:26 +0000 Subject: [PATCH 06/11] feat: properly track comptime files in crates deps --- compiler/rustc_interface/src/passes.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 73bebb22bc508..5fcfe22005460 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -621,6 +621,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P // Account for explicitly marked-to-track files // (e.g. accessed in proc macros). let file_depinfo = sess.file_depinfo.borrow(); + tracing::error!("{:?}", *file_depinfo); let normalize_path = |path: PathBuf| escape_dep_filename(&path.to_string_lossy()); @@ -657,6 +658,18 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P ); files.extend(extra_tracked_files); + let comptime_tracked_files = hash_iter_files( + tcx.sess + .opts + .unstable_opts + .experimental_comptime_files + .iter() + .map(PathBuf::from) + .map(normalize_path), + checksum_hash_algo, + ); + files.extend(comptime_tracked_files); + // We also need to track used PGO profile files if let Some(ref profile_instr) = sess.opts.cg.profile_use { files.extend(hash_iter_files( From b460626be7c7cfd32068106c6396cc2607d945f0 Mon Sep 17 00:00:00 2001 From: Lamb Date: Sun, 1 Nov 2026 18:32:36 +0000 Subject: [PATCH 07/11] enable proper cross-crate execution of read_file --- .../src/const_eval/machine.rs | 10 ++++++-- compiler/rustc_interface/src/passes.rs | 1 - compiler/rustc_metadata/src/rmeta/decoder.rs | 7 ------ .../src/rmeta/decoder/cstore_impl.rs | 11 +++++---- compiler/rustc_metadata/src/rmeta/encoder.rs | 23 +++++++++++-------- compiler/rustc_metadata/src/rmeta/mod.rs | 4 ++-- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 7a3d94d8ec682..17f5b5d3ee171 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -7,7 +7,7 @@ use rustc_ast::Mutability; use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_lint_defs::builtin::LONG_RUNNING_CONST_EVAL; use rustc_middle::mir::AssertMessage; @@ -603,7 +603,13 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { let path = ecx.read_str(&arg_place)?; let path_sym = Symbol::intern(path); - let krate = LOCAL_CRATE; // somehow fetch crate of the object + let krate = ecx + .stack() + .first() + .expect("should have a call frame if we are here") + .instance() + .def_id() + .krate; let content = ecx.tcx.experimental_comptime_fetch_file((krate, path_sym)); let variant_index = if let Some(value) = content { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 5fcfe22005460..964e879d8c114 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -621,7 +621,6 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P // Account for explicitly marked-to-track files // (e.g. accessed in proc macros). let file_depinfo = sess.file_depinfo.borrow(); - tracing::error!("{:?}", *file_depinfo); let normalize_path = |path: PathBuf| escape_dep_filename(&path.to_string_lossy()); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index b7314fc9ae2f7..8ac88f0c9bd63 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1029,13 +1029,6 @@ impl CrateRoot { ) -> impl ExactSizeIterator { self.denied_partial_mitigations.decode(metadata) } - - pub(crate) fn decode_comptime_files<'a>( - &self, - metadata: &'a MetadataBlob, - ) -> impl ExactSizeIterator)> { - self.comptime_files.decode(metadata) - } } impl CrateMetadata { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 723a4a9451655..41a8b28bb3999 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -26,6 +26,7 @@ use rustc_span::{Span, Symbol, bug, kw}; use super::{Decodable, DecodeIterator}; use crate::creader::{CStore, LoadedMacro}; use crate::rmeta::AttrFlags; +use crate::rmeta::decoder::MetaBlob; use crate::rmeta::table::IsDefault; use crate::{eii, foreign_modules, native_libs}; @@ -625,15 +626,15 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { }; provide_extern(&mut providers.extern_queries); - providers.extern_queries.experimental_comptime_fetch_file = |tcx, (cnum, key)| { - let key = key.as_str(); + providers.extern_queries.experimental_comptime_fetch_file = |tcx, (cnum, path)| { let cstore = CStore::from_tcx(tcx); let crate_data = cstore.get_crate_data(cnum); crate_data .root - .decode_comptime_files(&crate_data.blob) - .find(|(path, _)| key == path) - .map(|(_, data)| &*tcx.arena.alloc_slice(data.as_ref())) + .comptime_files + .get(&path) + .map(|lv| lv.decode(crate_data.blob())) + .map(|v| &*tcx.arena.alloc_slice(&v)) }; } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4015b0241bd5d..472a058910564 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -771,16 +771,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let denied_partial_mitigations = stat!("denied-partial-mitigations", || self .encode_enabled_denied_partial_mitigations()); - let mut comptime_files = Vec::new(); - for raw_path in &tcx.sess.opts.unstable_opts.experimental_comptime_files { - let path = Symbol::intern(raw_path); - if let Some(file_data) = tcx.experimental_comptime_fetch_file((LOCAL_CRATE, path)) { - comptime_files.push((raw_path.clone(), file_data.to_vec())); - } - } - - // Should I somehow sort by filename here in case this does *anything* with the parallel frontend stuff or something? - let comptime_files = self.lazy_array(comptime_files); + let comptime_files = stat!("comptime-files", || self.encode_comptime_files(tcx)); let root = stat!("crate-root", || { let attrs = tcx.hir_krate_attrs(); @@ -2477,6 +2468,18 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } LazyArray::default() } + + fn encode_comptime_files(&mut self, tcx: TyCtxt<'_>) -> IndexMap>> { + let mut comptime_files = IndexMap::default(); + for raw_path in &tcx.sess.opts.unstable_opts.experimental_comptime_files { + let path = Symbol::intern(raw_path); + if let Some(file_data) = tcx.experimental_comptime_fetch_file((LOCAL_CRATE, path)) { + comptime_files.insert_full(path, self.lazy(file_data.to_vec())); + } + } + + comptime_files + } } /// Used to prefetch queries which will be needed later by metadata encoding. diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9c41a0357de7f..e2b377c56d871 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -41,6 +41,7 @@ use rustc_middle::middle::resolve::{AmbigModChild, DocLinkResMap, ModChild}; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::mir; use rustc_middle::mir::ConstValue; +use rustc_middle::ty::data_structures::IndexMap; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::util::Providers; @@ -332,8 +333,7 @@ pub(crate) struct CrateRoot { specialization_enabled_in: bool, - // LazyTable maybe?? - comptime_files: LazyArray<(String, Vec)>, + comptime_files: IndexMap>>, } /// A separate struct for extra metadata that must be encoded *after* From 2f8569cef0f7636e1e2a5eaa606cbc8911623f76 Mon Sep 17 00:00:00 2001 From: Lamb Date: Tue, 3 Nov 2026 16:22:28 +0000 Subject: [PATCH 08/11] feat: add file list query --- .../src/const_eval/comptime_fs.rs | 18 ++++++++++++++++++ compiler/rustc_const_eval/src/lib.rs | 2 ++ .../src/rmeta/decoder/cstore_impl.rs | 12 +++++++++++- compiler/rustc_middle/src/queries.rs | 8 +++++++- compiler/rustc_middle/src/query/erase.rs | 3 ++- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs index 0a7af3a75f1d4..7c9aaff794601 100644 --- a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs +++ b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs @@ -1,7 +1,25 @@ +use rustc_middle::query::LocalCrate; use rustc_middle::ty::TyCtxt; use rustc_span::Symbol; use tracing::instrument; +#[instrument(skip(tcx), level = "debug")] +pub fn experimental_comptime_list_files_provider( + tcx: TyCtxt<'_>, + _: LocalCrate, +) -> Option<&[Symbol]> { + let filelist = tcx + .sess + .opts + .unstable_opts + .experimental_comptime_files + .iter() + .map(|p| Symbol::intern(p)) + .collect::>(); + + Some(tcx.arena.alloc_slice(&filelist)) +} + #[instrument(skip(tcx), level = "debug")] pub fn experimental_comptime_fetch_file_provider<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index b82b60b657094..3d6ff03f0c8fd 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -63,6 +63,8 @@ pub fn provide(providers: &mut Providers) { |tcx, scalar, layout| util::validate_scalar_in_layout(tcx, scalar, layout); providers.queries.experimental_comptime_fetch_file = const_eval::comptime_fs::experimental_comptime_fetch_file_provider; + providers.queries.experimental_comptime_list_files = + const_eval::comptime_fs::experimental_comptime_list_files_provider; } /// `rustc_driver::main` installs a handler that will set this to `true` if diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 41a8b28bb3999..8f5d58349e34b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -625,8 +625,18 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { ..providers.queries }; provide_extern(&mut providers.extern_queries); + provide_extern_comptime(&mut providers.extern_queries); +} + +fn provide_extern_comptime(extern_queries: &mut ExternProviders) { + extern_queries.experimental_comptime_list_files = |tcx, cnum| { + let cstore = CStore::from_tcx(tcx); + let crate_data = cstore.get_crate_data(cnum); + let filelist = crate_data.root.comptime_files.keys().copied().collect::>(); + Some(tcx.arena.alloc_slice(&filelist)) + }; - providers.extern_queries.experimental_comptime_fetch_file = |tcx, (cnum, path)| { + extern_queries.experimental_comptime_fetch_file = |tcx, (cnum, path)| { let cstore = CStore::from_tcx(tcx); let crate_data = cstore.get_crate_data(cnum); crate_data diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 792cf2693494a..8da5f52dc7793 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2852,12 +2852,18 @@ rustc_queries! { desc { "calculating all fake doc items" } } - /// Query data from non-local crates + /// Query the content of a file during const evaluation query experimental_comptime_fetch_file(key: (CrateNum, Symbol)) -> Option<&'tcx [u8]> { desc { "fetch file {} from crate {}", key.1, key.0 } separate_provide_extern } + /// Query list of files available during const evaluation + query experimental_comptime_list_files(key: CrateNum) -> Option<&'tcx [Symbol]> { + desc { "fetch const eval file list from crate {}", key } + separate_provide_extern + } + //----------------------------------------------------------------------------- // "Non-queries" are special dep kinds that are not queries. //----------------------------------------------------------------------------- diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 72f9c94c0dc51..f67b95779809f 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -15,7 +15,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_index::{Idx, IndexSlice}; use rustc_span::def_id::ModId; -use rustc_span::{ErrorGuaranteed, Spanned}; +use rustc_span::{ErrorGuaranteed, Spanned, Symbol}; use crate::mono::{MonoItem, NormalizationErrorInMono}; use crate::ty::{self, Ty, TyCtxt}; @@ -180,6 +180,7 @@ impl_erasable_for_types_with_no_type_params! { (), (traits::solve::QueryResult<'_>, &'_ traits::solve::inspect::Probe>, ty::RequiredDepth), Option<&'_ OsStr>, + Option<&'_ [Symbol]>, Option<&'_ [rustc_hir::PreciseCapturingArgKind]>, Option<&'_ [u8]>, Option<(mir::ConstValue, Ty<'_>)>, From 4cd4705e51e41f6a22c5e57f4b7ffb7327dc4e91 Mon Sep 17 00:00:00 2001 From: Lamb Date: Sat, 7 Nov 2026 17:28:13 +0000 Subject: [PATCH 09/11] feat: implement intrinsics and lib functions --- .../src/const_eval/machine.rs | 45 +++++++++++++++++-- .../rustc_hir_analysis/src/check/intrinsic.rs | 7 +++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics/comptime.rs | 7 +++ library/core/src/mem/comptime.rs | 8 ++++ 5 files changed, 64 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 17f5b5d3ee171..558155ead2862 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -24,10 +24,10 @@ use super::error::*; use crate::diagnostics::{LongRunning, LongRunningWarn}; use crate::interpret::{ self, AllocId, AllocInit, AllocRange, ConstAllocation, CtfeProvenance, FnArg, Frame, - GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, RangeSet, - RetagMode, Scalar, compile_time_machine, ensure_monomorphic_enough, err_inval, interp_ok, - throw_exhaust, throw_inval, throw_ub, throw_ub_format, throw_unsup, throw_unsup_format, - type_implements_dyn_trait, + GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, OpTy, PlaceTy, Pointer, Projectable, + RangeSet, RetagMode, Scalar, compile_time_machine, ensure_monomorphic_enough, err_inval, + interp_ok, throw_exhaust, throw_inval, throw_ub, throw_ub_format, throw_unsup, + throw_unsup_format, type_implements_dyn_trait, }; /// When hitting this many interpreted terminators we emit a deny by default lint @@ -634,6 +634,43 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { ecx.write_discriminant(variant_index, dest)?; } + sym::comptime_list_files => { + let krate = ecx + .stack() + .first() + .expect("should have a call frame if we are here") + .instance() + .def_id() + .krate; + + let filelist = + ecx.tcx().experimental_comptime_list_files(krate).unwrap_or_default(); + + let element_type = + dest.layout().ty.builtin_deref(false).unwrap().sequence_element_type(ecx.tcx()); + + // type and layout of [&str, filelist.len()]; + let array_ty = + ecx.layout_of(Ty::new_array(ecx.tcx(), element_type, filelist.len() as _))?; + + // actual allocated array + let array_place = ecx.allocate(array_ty, interpret::MemoryKind::Stack)?; + + let mut array_iter = ecx.project_array_fields(&array_place)?; + while let Some((idx, entry_place)) = array_iter.next(ecx)? { + let file = filelist[idx as usize]; + let file_place = ecx.allocate_str_dedup(file.as_str())?; + let imm = file_place.to_ref(ecx); + ecx.write_immediate(imm, &entry_place)?; + } + + let array_place = array_place.map_provenance(CtfeProvenance::as_immutable); + ecx.write_immediate( + Immediate::new_slice(array_place.ptr(), filelist.len() as _, ecx), + dest, + )?; + } + sym::type_id_vtable => { let tp_ty = ecx.read_type_id(&args[0])?; let result_ty = ecx.read_type_id(&args[1])?; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 2eb8e649ed177..85657ccea8470 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -86,6 +86,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::codeview_annotation | sym::cold_path | sym::comptime_fetch_file + | sym::comptime_list_files | sym::const_eval_select | sym::contract_check_ensures | sym::contract_check_requires @@ -300,6 +301,12 @@ pub(crate) fn check_intrinsic_type( (0, 0, vec![var_name], Ty::new_option(tcx, slice_u8_static)) } + sym::comptime_list_files => { + let slice = Ty::new_slice(tcx, Ty::new_static_str(tcx)); + let slice_static: Ty<'_> = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, slice); + (0, 0, vec![], slice_static) + } + sym::type_name => (1, 0, vec![], Ty::new_static_str(tcx)), sym::type_id => (1, 0, vec![], type_id_ty()), sym::type_id_array_len => (0, 0, vec![type_id_ty()], tcx.types.usize), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 84526e359026e..9e568e2aaf30d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -681,6 +681,7 @@ symbols! { compiler_move, complex, comptime_fetch_file, + comptime_list_files, concat, concat_bytes, concat_str, diff --git a/library/core/src/intrinsics/comptime.rs b/library/core/src/intrinsics/comptime.rs index 036a31b99ca2e..c9b77a5411fc2 100644 --- a/library/core/src/intrinsics/comptime.rs +++ b/library/core/src/intrinsics/comptime.rs @@ -9,3 +9,10 @@ #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_comptime] pub fn comptime_fetch_file(file_path: &str) -> Option<&'static [u8]>; + +/// Returns the list of files that can be read at compile time +#[rustc_nounwind] +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn comptime_list_files() -> &'static [&'static str]; diff --git a/library/core/src/mem/comptime.rs b/library/core/src/mem/comptime.rs index 7fe13e7adbac4..53aa33cfe3120 100644 --- a/library/core/src/mem/comptime.rs +++ b/library/core/src/mem/comptime.rs @@ -7,3 +7,11 @@ pub fn read_file(path: &str) -> Option<&'static [u8]> { crate::intrinsics::comptime::comptime_fetch_file(path) } + +/// Read a file at compile time +#[unstable(feature = "type_info", issue = "146922")] +#[rustc_const_unstable(feature = "type_info", issue = "146922")] +#[rustc_comptime] +pub fn list_files() -> &'static [&'static str] { + crate::intrinsics::comptime::comptime_list_files() +} From b7e2e7547fc2c3fe0b914ca08e045b5ea8d6f324 Mon Sep 17 00:00:00 2001 From: Lamb Date: Sat, 7 Nov 2026 18:45:09 +0000 Subject: [PATCH 10/11] feat: add error handling for comptime file reading --- .../src/const_eval/comptime_fs.rs | 28 ++++++------- .../src/const_eval/machine.rs | 42 +++++++++++++++++-- .../src/rmeta/decoder/cstore_impl.rs | 7 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 13 ++++-- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/comptime.rs | 12 ++++++ compiler/rustc_middle/src/lib.rs | 1 + compiler/rustc_middle/src/queries.rs | 5 ++- compiler/rustc_middle/src/query/erase.rs | 6 +-- 9 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 compiler/rustc_middle/src/comptime.rs diff --git a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs index 7c9aaff794601..241cfd591601f 100644 --- a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs +++ b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs @@ -1,13 +1,13 @@ +use std::io::ErrorKind; + +use rustc_middle::comptime::ReadFileError; use rustc_middle::query::LocalCrate; use rustc_middle::ty::TyCtxt; use rustc_span::Symbol; use tracing::instrument; #[instrument(skip(tcx), level = "debug")] -pub fn experimental_comptime_list_files_provider( - tcx: TyCtxt<'_>, - _: LocalCrate, -) -> Option<&[Symbol]> { +pub fn experimental_comptime_list_files_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[Symbol] { let filelist = tcx .sess .opts @@ -17,16 +17,19 @@ pub fn experimental_comptime_list_files_provider( .map(|p| Symbol::intern(p)) .collect::>(); - Some(tcx.arena.alloc_slice(&filelist)) + tcx.arena.alloc_slice(&filelist) } #[instrument(skip(tcx), level = "debug")] pub fn experimental_comptime_fetch_file_provider<'tcx>( tcx: TyCtxt<'tcx>, key: Symbol, -) -> Option<&'tcx [u8]> { +) -> Result, ReadFileError<'tcx>> { + // In case we are in a context without a crate root, just return that + // every file is whitelisted but does not exist. Is this code path + // taken by rustdoc when checking a comment code block? let Some(crate_root_path) = tcx.sess.io.input.opt_path() else { - return None; + return Ok(None); }; let requested_path = key.as_str(); @@ -46,14 +49,11 @@ pub fn experimental_comptime_fetch_file_provider<'tcx>( .is_some() { match std::fs::read(resolved_path) { - Ok(content) => Some(tcx.arena.alloc_slice(&content)), - Err(err) => { - tracing::debug!(%err, "failed to read file"); - None - } + Ok(content) => Ok(Some(tcx.arena.alloc_slice(&content))), + Err(e) if e.kind() == ErrorKind::NotFound => Ok(None), + Err(e) => Err(ReadFileError::IO(tcx.arena.alloc_str(&e.to_string()))), } } else { - tracing::debug!("not allowed to read file"); - None + Err(ReadFileError::NotWhitelisted) } } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 558155ead2862..f2d8a8fc6db23 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -10,6 +10,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_lint_defs::builtin::LONG_RUNNING_CONST_EVAL; +use rustc_middle::comptime::ReadFileError; use rustc_middle::mir::AssertMessage; use rustc_middle::mir::interpret::ReportedErrorInfo; use rustc_middle::query::TyCtxtAt; @@ -611,8 +612,42 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { .def_id() .krate; - let content = ecx.tcx.experimental_comptime_fetch_file((krate, path_sym)); - let variant_index = if let Some(value) = content { + let content_maybe = match ecx + .tcx + .experimental_comptime_fetch_file((krate, path_sym)) + { + Ok(content) => content, + Err(ReadFileError::IO(err)) => { + let guard = ecx + .tcx + .dcx() + .struct_err("error while reading file in constant evaluation") + .with_span(ecx.cur_span()) + .with_span_help(ecx.tcx.span, "while evaluating this constant") + .with_note(format!("filename: {path_sym}")) + .with_note(format!("error: {err}")) + .emit_err(); + throw_inval!(AlreadyReported(ReportedErrorInfo::allowed_in_infallible( + guard + ))); + } + Err(ReadFileError::NotWhitelisted) => { + let guard = ecx + .tcx + .dcx() + .struct_err("this file cannot be accessed during const-evaluation") + .with_span(ecx.cur_span()) + .with_span_help(ecx.tcx.span, "while evaluating this constant") + .with_note(format!("filename: {path_sym}")) + .with_help("pass -Zexperimental-comptime-files= to the compiler to allow reading this file") + .emit_err(); + throw_inval!(AlreadyReported(ReportedErrorInfo::allowed_in_infallible( + guard + ))); + } + }; + + let variant_index = if let Some(value) = content_maybe { let ptr = ecx.allocate_bytes_dedup(value)?; let (variant_idx, variant_place) = @@ -643,8 +678,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { .def_id() .krate; - let filelist = - ecx.tcx().experimental_comptime_list_files(krate).unwrap_or_default(); + let filelist = ecx.tcx().experimental_comptime_list_files(krate); let element_type = dest.layout().ty.builtin_deref(false).unwrap().sequence_element_type(ecx.tcx()); diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 8f5d58349e34b..0179b507cb8ea 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -633,18 +633,19 @@ fn provide_extern_comptime(extern_queries: &mut ExternProviders) { let cstore = CStore::from_tcx(tcx); let crate_data = cstore.get_crate_data(cnum); let filelist = crate_data.root.comptime_files.keys().copied().collect::>(); - Some(tcx.arena.alloc_slice(&filelist)) + tcx.arena.alloc_slice(&filelist) }; extern_queries.experimental_comptime_fetch_file = |tcx, (cnum, path)| { let cstore = CStore::from_tcx(tcx); let crate_data = cstore.get_crate_data(cnum); - crate_data + let data = crate_data .root .comptime_files .get(&path) .map(|lv| lv.decode(crate_data.blob())) - .map(|v| &*tcx.arena.alloc_slice(&v)) + .and_then(|v| v.map(|d| &*tcx.arena.alloc_slice(&d))); + Ok(data) }; } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 472a058910564..c7c7b220f329c 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2469,12 +2469,19 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { LazyArray::default() } - fn encode_comptime_files(&mut self, tcx: TyCtxt<'_>) -> IndexMap>> { + fn encode_comptime_files( + &mut self, + tcx: TyCtxt<'_>, + ) -> IndexMap>>> { let mut comptime_files = IndexMap::default(); for raw_path in &tcx.sess.opts.unstable_opts.experimental_comptime_files { let path = Symbol::intern(raw_path); - if let Some(file_data) = tcx.experimental_comptime_fetch_file((LOCAL_CRATE, path)) { - comptime_files.insert_full(path, self.lazy(file_data.to_vec())); + /// Must encode None too, as we depend on the keys of the IndexMap to store the list + /// of files that we export from this crate. + if let Ok(file_data) = tcx.experimental_comptime_fetch_file((LOCAL_CRATE, path)) { + comptime_files.insert_full(path, self.lazy(file_data.map(|d| d.to_vec()))); + } else { + bug!("a comptile time file read error should fail crate compilation") } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index e2b377c56d871..a930684e1eb72 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -333,7 +333,7 @@ pub(crate) struct CrateRoot { specialization_enabled_in: bool, - comptime_files: IndexMap>>, + comptime_files: IndexMap>>>, } /// A separate struct for extra metadata that must be encoded *after* diff --git a/compiler/rustc_middle/src/comptime.rs b/compiler/rustc_middle/src/comptime.rs new file mode 100644 index 0000000000000..209789ce697b5 --- /dev/null +++ b/compiler/rustc_middle/src/comptime.rs @@ -0,0 +1,12 @@ +use rustc_macros::StableHash; + +/// This error is emitted by comptime files queries when a file cannot be read. +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(StableHash)] +pub enum ReadFileError<'tcx> { + /// Another IO error happened while trying to read the file + IO(&'tcx str), + + /// The file being accessed at comptime has not been whitelisted + NotWhitelisted, +} diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 695eca6225858..67b31ba4fec37 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -69,6 +69,7 @@ mod macros; #[macro_use] pub mod arena; +pub mod comptime; pub mod dep_graph; pub mod diagnostics; pub mod hir; diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 8da5f52dc7793..074a4eb0b1e8b 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -79,6 +79,7 @@ use rustc_span::def_id::{LOCAL_CRATE, ModId}; use rustc_span::{DUMMY_SP, LocalExpnId, Span, Spanned, Symbol}; use rustc_target::spec::PanicStrategy; +use crate::comptime::ReadFileError; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintExpectation; use crate::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; @@ -2853,13 +2854,13 @@ rustc_queries! { } /// Query the content of a file during const evaluation - query experimental_comptime_fetch_file(key: (CrateNum, Symbol)) -> Option<&'tcx [u8]> { + query experimental_comptime_fetch_file(key: (CrateNum, Symbol)) -> Result, ReadFileError<'tcx>> { desc { "fetch file {} from crate {}", key.1, key.0 } separate_provide_extern } /// Query list of files available during const evaluation - query experimental_comptime_list_files(key: CrateNum) -> Option<&'tcx [Symbol]> { + query experimental_comptime_list_files(key: CrateNum) -> &'tcx [Symbol] { desc { "fetch const eval file list from crate {}", key } separate_provide_extern } diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index f67b95779809f..2597d1abf1f11 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -15,8 +15,9 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_index::{Idx, IndexSlice}; use rustc_span::def_id::ModId; -use rustc_span::{ErrorGuaranteed, Spanned, Symbol}; +use rustc_span::{ErrorGuaranteed, Spanned}; +use crate::comptime::ReadFileError; use crate::mono::{MonoItem, NormalizationErrorInMono}; use crate::ty::{self, Ty, TyCtxt}; use crate::{mir, thir, traits}; @@ -180,9 +181,7 @@ impl_erasable_for_types_with_no_type_params! { (), (traits::solve::QueryResult<'_>, &'_ traits::solve::inspect::Probe>, ty::RequiredDepth), Option<&'_ OsStr>, - Option<&'_ [Symbol]>, Option<&'_ [rustc_hir::PreciseCapturingArgKind]>, - Option<&'_ [u8]>, Option<(mir::ConstValue, Ty<'_>)>, Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>, Option, @@ -213,6 +212,7 @@ impl_erasable_for_types_with_no_type_params! { Result<(&'_ Steal>, thir::ExprId), ErrorGuaranteed>, Result<(&'_ [Spanned>], &'_ [Spanned>]), NormalizationErrorInMono>, Result<(), ErrorGuaranteed>, + Result, ReadFileError<'_>>, Result>>, ErrorGuaranteed>, Result>, ErrorGuaranteed>, Result>, From 28a914f84bcc44abf6b48e03de38f8f34b908962 Mon Sep 17 00:00:00 2001 From: Lamb Date: Sat, 7 Nov 2026 19:01:46 +0000 Subject: [PATCH 11/11] refactor: use query to get comptime filelist --- compiler/rustc_const_eval/src/const_eval/comptime_fs.rs | 8 +++----- compiler/rustc_interface/src/passes.rs | 7 ++----- compiler/rustc_metadata/src/rmeta/encoder.rs | 7 +++---- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs index 241cfd591601f..5c579d66298c1 100644 --- a/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs +++ b/compiler/rustc_const_eval/src/const_eval/comptime_fs.rs @@ -1,5 +1,6 @@ use std::io::ErrorKind; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::comptime::ReadFileError; use rustc_middle::query::LocalCrate; use rustc_middle::ty::TyCtxt; @@ -40,12 +41,9 @@ pub fn experimental_comptime_fetch_file_provider<'tcx>( // Very simple implementation where we whitelist paths directly. We don't even attempt // to canonicalize for now. if tcx - .sess - .opts - .unstable_opts - .experimental_comptime_files + .experimental_comptime_list_files(LOCAL_CRATE) .iter() - .find(|s| requested_path == *s) + .find(|s| requested_path == s.as_str()) .is_some() { match std::fs::read(resolved_path) { diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 964e879d8c114..5fc7ff915563d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -658,12 +658,9 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P files.extend(extra_tracked_files); let comptime_tracked_files = hash_iter_files( - tcx.sess - .opts - .unstable_opts - .experimental_comptime_files + tcx.experimental_comptime_list_files(LOCAL_CRATE) .iter() - .map(PathBuf::from) + .map(|s| PathBuf::from(s.as_str())) .map(normalize_path), checksum_hash_algo, ); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c7c7b220f329c..72ff4814c1a26 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2474,10 +2474,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { tcx: TyCtxt<'_>, ) -> IndexMap>>> { let mut comptime_files = IndexMap::default(); - for raw_path in &tcx.sess.opts.unstable_opts.experimental_comptime_files { - let path = Symbol::intern(raw_path); - /// Must encode None too, as we depend on the keys of the IndexMap to store the list - /// of files that we export from this crate. + for &path in tcx.experimental_comptime_list_files(LOCAL_CRATE) { + // Must encode None too, as we depend on the keys of the IndexMap to store the list + // of files that we export from this crate. if let Ok(file_data) = tcx.experimental_comptime_fetch_file((LOCAL_CRATE, path)) { comptime_files.insert_full(path, self.lazy(file_data.map(|d| d.to_vec()))); } else {