Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f123df5
reflection: adds `TypeId::points_to` and `TypeId::is_mutable_pointer`
yara-blue Aug 27, 2026
9c36788
reflection: remove field from TypeKind::Pointer variant
yara-blue Aug 31, 2026
e46de86
reflection: make `points_to` and `points_mutably` support references
yara-blue Sep 1, 2026
f4cdf28
reflection: remove field from TypeKind::Reference
yara-blue Sep 1, 2026
98d68aa
reflection: adds `TypeId::function_ptr` returning FnPtr
yara-blue Sep 1, 2026
06fa642
reflection: remove field from TypeKind::FnPtr
yara-blue Sep 4, 2026
0238ef9
change compile-flags for asm ui tests to not embed bitcode or use LTO
susitsm Sep 3, 2026
fa5601d
add test for inline asm cookie reproducibility
susitsm Sep 3, 2026
970cb98
Disable inline asm line info cookies when llvm bitcode is saved or LT…
susitsm Jul 30, 2026
714b06b
add test ensuring we refuse to const-eval the body of a rustc_do_not_…
RalfJung Sep 6, 2026
eb2326a
avoid spurious lifetime diagnostic in async generic case
pbkx Jun 19, 2026
018b9ad
std: remove exceed whitespace in docs
HigherOrderLogic Sep 7, 2026
d3cba0b
Temporarily add a crashtest for instrumenting comptime functions
Zalathar Sep 7, 2026
0027ee1
Make comptime functions ineligible for coverage
Zalathar Sep 6, 2026
eec967a
Also invalidate library when checking it if rustc has changed
Kobzol Sep 7, 2026
2250637
Don't pass a redundant `scrutinee_span` to some MIR-build methods
Zalathar Sep 7, 2026
eb3c2a4
Rollup merge of #158153 - pbkx:issue-115376-async-spurious-static-bou…
JonathanBrouwer Sep 7, 2026
2fbabb7
Rollup merge of #160197 - susitsm:restrict-inline-asm-cookies, r=petr…
JonathanBrouwer Sep 7, 2026
24d2665
Rollup merge of #162413 - Kobzol:check-compiler-invalidate, r=jieyouxu
JonathanBrouwer Sep 7, 2026
280c747
Rollup merge of #162294 - yara-blue:reflection-refactor-ptrs, r=oli-obk
JonathanBrouwer Sep 7, 2026
d9fa919
Rollup merge of #162354 - Zalathar:comptime, r=oli-obk
JonathanBrouwer Sep 7, 2026
2933a07
Rollup merge of #162379 - RalfJung:rustc_do_not_const_check, r=oli-obk
JonathanBrouwer Sep 7, 2026
9e8f51d
Rollup merge of #162410 - HigherOrderLogic:master, r=Darksonn
JonathanBrouwer Sep 7, 2026
89c5615
Rollup merge of #162420 - Zalathar:scrutinee-span, r=petrochenkov
JonathanBrouwer Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_attr_ir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,9 @@ language_item_table! {
// Used to fallback `{float}` to `f32` when `f32: From<{float}>`
From, sym::From, from_trait, Target::Trait, GenericRequirement::Exact(1);
FromFn, sym::from, from_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;

// Experimental lang item for `Reflection and comptime`(https://goals.rust-lang.org/2025h2/reflection-and-comptime.html)
FnPtr, sym::FnPtr, fn_ptr, Target::Struct, GenericRequirement::None;
}

/// The requirement imposed on the generics of a lang item
Expand Down
35 changes: 34 additions & 1 deletion compiler/rustc_borrowck/src/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// result in basically the exact same error being reported to
// the user. Avoid that.
let mut deduplicate_errors = FxIndexSet::default();
let mut failed_type_tests = Vec::new();

for type_test in &self.type_tests {
debug!("check_type_test: {:?}", type_test);
Expand All @@ -609,8 +610,40 @@ impl<'tcx> RegionInferenceContext<'tcx> {
continue;
}

// Type-test failed. Report the error.
// Type-test failed. Collect it so we can suppress redundant errors below.
let erased_generic_kind = infcx.tcx.erase_and_anonymize_regions(type_test.generic_kind);
failed_type_tests.push((erased_generic_kind, type_test));
}

// An async body can produce both `G: 'static` and `G: 'a` type-test failures at
// the same span, as in `tests/ui/async-await/spurious-static-bound-issue-115376.rs`.
// Reporting the weaker bound adds a redundant diagnostic and suggests a lifetime
// bound that cannot fix the missing `G: 'static` requirement. Keep the `'static`
// error and suppress weaker failures for the same erased generic kind and span.
// This is a diagnostic heuristic, using the same erasure as deduplication below.
//
// Collect all failed `'static` bounds before reporting errors so suppression does
// not depend on the order of the type tests. Compare SCCs because a lower-bound
// region can be equivalent to `'static` without being `fr_static` itself.
let static_scc = self.constraint_sccs.scc(self.universal_regions().fr_static);
let static_bound_errors: FxIndexSet<_> = failed_type_tests
.iter()
.filter_map(|&(erased_generic_kind, type_test)| {
if self.constraint_sccs.scc(type_test.lower_bound) == static_scc {
Some((erased_generic_kind, type_test.span))
} else {
None
}
})
.collect();

// If `G: 'static` failed at this span, then same-span `G: 'a` failures are weaker.
for (erased_generic_kind, type_test) in failed_type_tests {
if self.constraint_sccs.scc(type_test.lower_bound) != static_scc
&& static_bound_errors.contains(&(erased_generic_kind, type_test.span))
{
continue;
}

// Skip duplicate-ish errors.
if deduplicate_errors.insert((
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ impl ExtraBackendMethods for AotDriver {
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
_bitcode_needed: bool,
) -> (ModuleCodegen<Self::Module>, u64) {
let start_time = Instant::now();

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_gcc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
_bitcode_needed: bool,
) -> (ModuleCodegen<Self::Module>, u64) {
base::compile_codegen_unit(
tcx,
Expand Down
55 changes: 36 additions & 19 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use rustc_middle::mir::interpret::{PointerArithmetic, Scalar as ConstScalar};
use rustc_middle::ty::Instance;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{bug, span_bug};
use rustc_session::Session;
use rustc_session::config::Lto;
use rustc_span::{Pos, Span, Symbol, sym};
use rustc_target::asm::*;
use rustc_target::spec::HasTargetSpec;
Expand Down Expand Up @@ -594,30 +596,45 @@ pub(crate) fn inline_asm_call<'ll>(
let key = "srcloc";
let kind = bx.get_md_kind_id(key);

// `srcloc` contains one 64-bit integer for each line of assembly code,
// where the lower 32 bits hold the lo byte position and the upper 32 bits
// hold the hi byte position.
let mut srcloc = vec![];
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
// LLVM inserts an extra line to add the ".intel_syntax", so add
// a dummy srcloc entry for it.
//
// Don't do this if we only have 1 line span since that may be
// due to the asm template string coming from a macro. LLVM will
// default to the first srcloc for lines that don't have an
// associated srcloc.
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
if allow_raw_span_inline_asm_srcloc(bx.tcx.sess, bx.bitcode_needed) {
// `srcloc` contains one 64-bit integer for each line of assembly code,
// where the lower 32 bits hold the lo byte position and the upper 32 bits
// hold the hi byte position.
let mut srcloc = vec![];
if dia == llvm::AsmDialect::Intel && line_spans.len() > 1 {
// LLVM inserts an extra line to add the ".intel_syntax", so add
// a dummy srcloc entry for it.
//
// Don't do this if we only have 1 line span since that may be
// due to the asm template string coming from a macro. LLVM will
// default to the first srcloc for lines that don't have an
// associated srcloc.
srcloc.push(llvm::LLVMValueAsMetadata(bx.const_u64(0)));
}
srcloc.extend(line_spans.iter().map(|span| {
llvm::LLVMValueAsMetadata(
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)),
)
}));
bx.cx.set_metadata_node(call, kind, &srcloc);
}
srcloc.extend(line_spans.iter().map(|span| {
llvm::LLVMValueAsMetadata(
bx.const_u64(u64::from(span.lo().to_u32()) | (u64::from(span.hi().to_u32()) << 32)),
)
}));
bx.cx.set_metadata_node(call, kind, &srcloc);

Some(call)
}

/// Whenever inline assembly bitcode is built, its `srcloc` contains the raw span numbers
/// as location cookies. This is problematic since that is nondeterministic when using
/// the parallel frontend. Even without parallelism, the cookies are meaningless in another
/// rustc session.
///
/// Discussion about replacing the cookies with something stable: rust-lang/rust#150451
fn allow_raw_span_inline_asm_srcloc(sess: &Session, bitcode_needed: bool) -> bool {
// even for Lto::ThinLocal, where the bitcode isn't serialized into files, the changes in
// raw span positions would reflect in the LTO module hashes, which could lead to
// nondeterminism
sess.lto() == Lto::No && !bitcode_needed
}

/// If the register is an xmm/ymm/zmm register then return its index.
fn xmm_reg_index(reg: InlineAsmReg) -> Option<u32> {
use X86InlineAsmReg::*;
Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_codegen_llvm/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,15 @@ pub(crate) fn iter_global_aliases(llmod: &llvm::Module) -> ValueIter<'_> {
pub(crate) fn compile_codegen_unit(
tcx: TyCtxt<'_>,
cgu_name: Symbol,
bitcode_needed: bool,
) -> (ModuleCodegen<ModuleLlvm>, u64) {
let start_time = Instant::now();

let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
let (module, _) = tcx.dep_graph.with_task(
dep_node,
tcx,
|| module_codegen(tcx, cgu_name),
|| module_codegen(tcx, cgu_name, bitcode_needed),
Some(dep_graph::hash_result),
);
let time_to_codegen = start_time.elapsed();
Expand All @@ -80,7 +81,11 @@ pub(crate) fn compile_codegen_unit(
// the time we needed for codegenning it.
let cost = time_to_codegen.as_nanos() as u64;

fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
fn module_codegen(
tcx: TyCtxt<'_>,
cgu_name: Symbol,
needs_bitcode: bool,
) -> ModuleCodegen<ModuleLlvm> {
let cgu = tcx.codegen_unit(cgu_name);
let _prof_timer =
tcx.prof.generic_activity_with_arg_recorder("codegen_module", |recorder| {
Expand All @@ -90,7 +95,7 @@ pub(crate) fn compile_codegen_unit(
// Instantiate monomorphizations without filling out definitions yet...
let llvm_module = ModuleLlvm::new(tcx, cgu_name.as_str());
{
let mut cx = CodegenCx::new(tcx, cgu, &llvm_module);
let mut cx = CodegenCx::new(tcx, cgu, &llvm_module, needs_bitcode);

// Declare and store globals shared by all offload kernels
//
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ pub(crate) type CodegenCx<'ll, 'tcx> = GenericCx<'ll, FullCx<'ll, 'tcx>>;

pub(crate) struct FullCx<'ll, 'tcx> {
pub tcx: TyCtxt<'tcx>,
pub bitcode_needed: bool,
pub scx: SimpleCx<'ll>,
pub use_dll_storage_attrs: bool,
pub tls_model: llvm::ThreadLocalMode,
Expand Down Expand Up @@ -608,6 +609,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
tcx: TyCtxt<'tcx>,
codegen_unit: &'tcx CodegenUnit<'tcx>,
llvm_module: &'ll crate::ModuleLlvm,
bitcode_needed: bool,
) -> Self {
// An interesting part of Windows which MSVC forces our hand on (and
// apparently MinGW didn't) is the usage of `dllimport` and `dllexport`
Expand Down Expand Up @@ -703,6 +705,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
GenericCx(
FullCx {
tcx,
bitcode_needed,
scx: SimpleCx::new(llmod, llcx, tcx.data_layout.pointer_size()),
use_dll_storage_attrs,
tls_model,
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,9 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
bitcode_needed: bool,
) -> (ModuleCodegen<ModuleLlvm>, u64) {
base::compile_codegen_unit(tcx, cgu_name)
base::compile_codegen_unit(tcx, cgu_name, bitcode_needed)
}
}

Expand Down
14 changes: 5 additions & 9 deletions compiler/rustc_codegen_ssa/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use rustc_errors::{
Level, MultiSpan, Style, Suggestions, catch_fatal_errors,
};
use rustc_fs_util::link_or_copy;
use rustc_hir::find_attr;
use rustc_incremental::{copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess};
use rustc_macros::{Decodable, Encodable};
use rustc_metadata::fs::copy_to_stdout;
Expand Down Expand Up @@ -114,7 +113,7 @@ pub struct ModuleConfig {
}

impl ModuleConfig {
fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
pub(crate) fn new(kind: ModuleKind, tcx: TyCtxt<'_>, no_builtins: bool) -> ModuleConfig {
// If it's a regular module, use `$regular`, otherwise use `$other`.
// `$regular` and `$other` are evaluated lazily.
macro_rules! if_regular {
Expand Down Expand Up @@ -426,15 +425,12 @@ fn need_pre_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
pub(crate) fn start_async_codegen<B: WriteBackendMethods>(
backend: B,
tcx: TyCtxt<'_>,
regular_config: Arc<ModuleConfig>,
allocator_config: Arc<ModuleConfig>,
allocator_module: Option<ModuleCodegen<B::Module>>,
) -> OngoingCodegen<B> {
let (coordinator_send, coordinator_receive) = channel();

let no_builtins = find_attr!(tcx, crate, NoBuiltins);

let regular_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
let allocator_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);

let (shared_emitter, shared_emitter_main) = SharedEmitter::new();
let (codegen_worker_send, codegen_worker_receive) = channel();

Expand All @@ -444,8 +440,8 @@ pub(crate) fn start_async_codegen<B: WriteBackendMethods>(
shared_emitter,
codegen_worker_send,
coordinator_receive,
Arc::new(regular_config),
Arc::new(allocator_config),
regular_config,
allocator_config,
allocator_module,
coordinator_send.clone(),
);
Expand Down
22 changes: 17 additions & 5 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use tracing::{debug, info};
use crate::assert_module_sources::CguReuse;
use crate::back::link::are_upstream_rust_objects_already_included;
use crate::back::write::{
ComputedLtoType, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen,
ComputedLtoType, ModuleConfig, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen,
submit_codegened_module_to_llvm, submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm,
};
use crate::common::{self, IntPredicate, RealPredicate, TypeKind};
Expand All @@ -52,7 +52,7 @@ use crate::mir::place::PlaceRef;
use crate::traits::*;
use crate::{
CachedModuleCodegen, CodegenLintLevelSpecs, CrateInfo, EiiLinkageImplInfo, EiiLinkageInfo,
ModuleCodegen, diagnostics, meth, mir,
ModuleCodegen, ModuleKind, diagnostics, meth, mir,
};

pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
Expand Down Expand Up @@ -762,7 +762,18 @@ pub fn codegen_crate<
None
};

let ongoing_codegen = start_async_codegen(backend.clone(), tcx, allocator_module);
let no_builtins = find_attr!(tcx, crate, NoBuiltins);
let regular_module_config = ModuleConfig::new(ModuleKind::Regular, tcx, no_builtins);
let bitcode_needed = regular_module_config.bitcode_needed();
let allocator_module_config = ModuleConfig::new(ModuleKind::Allocator, tcx, no_builtins);

let ongoing_codegen = start_async_codegen(
backend.clone(),
tcx,
Arc::new(regular_module_config),
Arc::new(allocator_module_config),
allocator_module,
);

// For better throughput during parallel processing by LLVM, we used to sort
// CGUs largest to smallest. This would lead to better thread utilization
Expand Down Expand Up @@ -822,7 +833,8 @@ pub fn codegen_crate<
let start_time = Instant::now();

let pre_compiled_cgus = par_map(cgus, |(i, _)| {
let module = backend.compile_codegen_unit(tcx, codegen_units[i].name());
let module =
backend.compile_codegen_unit(tcx, codegen_units[i].name(), bitcode_needed);
(i, IntoDynSyncSend(module))
});

Expand All @@ -846,7 +858,7 @@ pub fn codegen_crate<
cgu.0
} else {
let start_time = Instant::now();
let module = backend.compile_codegen_unit(tcx, cgu.name());
let module = backend.compile_codegen_unit(tcx, cgu.name(), bitcode_needed);
total_codegen_time += start_time.elapsed();
module
};
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/traits/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,5 +177,6 @@ pub trait ExtraBackendMethods: Send + Sync + DynSend + DynSync {
&self,
tcx: TyCtxt<'_>,
cgu_name: Symbol,
bitcode_needed: bool,
) -> (ModuleCodegen<Self::Module>, u64);
}
36 changes: 36 additions & 0 deletions compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,15 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
ecx.write_scalar(Scalar::from_bool(ty.is_signed()), dest)?;
}

sym::type_id_points_mutably => {
let ty = ecx.read_type_id(&args[0])?;
let is_mutable = matches!(
ty.kind(),
ty::RawPtr(_, Mutability::Mut) | &ty::Ref(_, _, Mutability::Mut)
);
ecx.write_scalar(Scalar::from_bool(is_mutable), dest)?;
}

sym::size_of_type_id => {
let ty = ecx.read_type_id(&args[0])?;
let layout = ecx.layout_of(ty)?;
Expand Down Expand Up @@ -691,6 +700,33 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
);
ecx.write_type_id(frt, dest)?;
}
sym::type_id_function_ptr => {
let ty = ecx.read_type_id(&args[0])?;
let variant_index = if let ty::FnPtr(sig, fn_header) = ty.kind() {
let (variant, variant_place) = ecx.project_downcast_named(dest, sym::Some)?;
let field_place = ecx.project_field(&variant_place, FieldIdx::ZERO)?;
let sig = sig.skip_binder(); // FIXME: handle lifetime bounds
ecx.write_fn_ptr_type_info(field_place, &sig, fn_header)?;
variant
} else {
ecx.project_downcast_named(dest, sym::None)?.0
};
ecx.write_discriminant(variant_index, dest)?;
}
sym::type_id_points_to => {
let ty = ecx.read_type_id(&args[0])?;
let variant_index = if let ty::RawPtr(pointee_ty, _) | ty::Ref(_, pointee_ty, _) =
ty.kind()
{
let (variant, variant_place) = ecx.project_downcast_named(dest, sym::Some)?;
let field_place = ecx.project_field(&variant_place, FieldIdx::ZERO)?;
ecx.write_type_id(*pointee_ty, &field_place)?;
variant
} else {
ecx.project_downcast_named(dest, sym::None)?.0
};
ecx.write_discriminant(variant_index, dest)?;
}

sym::type_id_variants => {
let ty = ecx.read_type_id(&args[0])?;
Expand Down
Loading
Loading