Auto merge of #144562 - matthiaskrgr:rollup-mlvn7qo, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang/rust#144072 (update `Atomic*::from_ptr` and `Atomic*::as_ptr` docs)
 - rust-lang/rust#144151 (`tests/ui/issues/`: The Issues Strike Back [1/N])
 - rust-lang/rust#144300 (Clippy fixes for miropt-test-tools)
 - rust-lang/rust#144399 (Add a ratchet for moving all standard library tests to separate packages)
 - rust-lang/rust#144472 (str: Mark unstable `round_char_boundary` feature functions as const)
 - rust-lang/rust#144503 (Various refactors to the codegen coordinator code (part 3))
 - rust-lang/rust#144530 (coverage: Infer `instances_used` from `pgo_func_name_var_map`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-07-28 08:50:59 +00:00
commit 65b6cdb6a6
68 changed files with 350 additions and 324 deletions

View file

@ -4,7 +4,6 @@ use gccjit::{Context, OutputKind};
use rustc_codegen_ssa::back::link::ensure_removed;
use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
use rustc_errors::DiagCtxtHandle;
use rustc_fs_util::link_or_copy;
use rustc_session::config::OutputType;
use rustc_span::fatal_error::FatalError;
@ -258,14 +257,6 @@ pub(crate) fn codegen(
))
}
pub(crate) fn link(
_cgcx: &CodegenContext<GccCodegenBackend>,
_dcx: DiagCtxtHandle<'_>,
mut _modules: Vec<ModuleCodegen<GccContext>>,
) -> Result<ModuleCodegen<GccContext>, FatalError> {
unimplemented!();
}
pub(crate) fn save_temp_bitcode(
cgcx: &CodegenContext<GccCodegenBackend>,
_module: &ModuleCodegen<GccContext>,

View file

@ -426,14 +426,6 @@ impl WriteBackendMethods for GccCodegenBackend {
fn serialize_module(_module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
unimplemented!();
}
fn run_link(
cgcx: &CodegenContext<Self>,
dcx: DiagCtxtHandle<'_>,
modules: Vec<ModuleCodegen<Self::Module>>,
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
back::write::link(cgcx, dcx, modules)
}
}
/// This is the entrypoint for a hot plugged rustc_codegen_gccjit

View file

@ -12,7 +12,7 @@ codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_
codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$llvm_err})
codegen_llvm_lto_bitcode_from_rlib = failed to get bitcode from object file for LTO ({$err})
codegen_llvm_mismatch_data_layout =
data-layout for target `{$rustc_target}`, `{$rustc_layout}`, differs from LLVM target's `{$llvm_target}` default layout, `{$llvm_layout}`

View file

@ -7,6 +7,7 @@ use std::sync::Arc;
use std::{io, iter, slice};
use object::read::archive::ArchiveFile;
use object::{Object, ObjectSection};
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
use rustc_codegen_ssa::traits::*;
@ -105,31 +106,15 @@ fn get_bitcode_slice_from_object_data<'a>(
// name" which in the public API for sections gets treated as part of the section name, but
// internally in MachOObjectFile.cpp gets treated separately.
let section_name = bitcode_section_name(cgcx).to_str().unwrap().trim_start_matches("__LLVM,");
let mut len = 0;
let data = unsafe {
llvm::LLVMRustGetSliceFromObjectDataByName(
obj.as_ptr(),
obj.len(),
section_name.as_ptr(),
section_name.len(),
&mut len,
)
};
if !data.is_null() {
assert!(len != 0);
let bc = unsafe { slice::from_raw_parts(data, len) };
// `bc` must be a sub-slice of `obj`.
assert!(obj.as_ptr() <= bc.as_ptr());
assert!(bc[bc.len()..bc.len()].as_ptr() <= obj[obj.len()..obj.len()].as_ptr());
let obj =
object::File::parse(obj).map_err(|err| LtoBitcodeFromRlib { err: err.to_string() })?;
Ok(bc)
} else {
assert!(len == 0);
Err(LtoBitcodeFromRlib {
llvm_err: llvm::last_error().unwrap_or_else(|| "unknown LLVM error".to_string()),
})
}
let section = obj
.section_by_name(section_name)
.ok_or_else(|| LtoBitcodeFromRlib { err: format!("Can't find section {section_name}") })?;
section.data().map_err(|err| LtoBitcodeFromRlib { err: err.to_string() })
}
/// Performs fat LTO by merging all modules into a single one and returning it

View file

@ -796,29 +796,6 @@ pub(crate) fn optimize(
Ok(())
}
pub(crate) fn link(
cgcx: &CodegenContext<LlvmCodegenBackend>,
dcx: DiagCtxtHandle<'_>,
mut modules: Vec<ModuleCodegen<ModuleLlvm>>,
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
use super::lto::{Linker, ModuleBuffer};
// Sort the modules by name to ensure deterministic behavior.
modules.sort_by(|a, b| a.name.cmp(&b.name));
let (first, elements) =
modules.split_first().expect("Bug! modules must contain at least one module.");
let mut linker = Linker::new(first.module_llvm.llmod());
for module in elements {
let _timer = cgcx.prof.generic_activity_with_arg("LLVM_link_module", &*module.name);
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
linker
.add(buffer.data())
.map_err(|()| llvm_err(dcx, LlvmError::SerializeModule { name: &module.name }))?;
}
drop(linker);
Ok(modules.remove(0))
}
pub(crate) fn codegen(
cgcx: &CodegenContext<LlvmCodegenBackend>,
module: ModuleCodegen<ModuleLlvm>,

View file

@ -46,21 +46,17 @@ pub(crate) fn finalize(cx: &mut CodegenCx<'_, '_>) {
debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
// FIXME(#132395): Can this be none even when coverage is enabled?
let instances_used = match cx.coverage_cx {
Some(ref cx) => cx.instances_used.borrow(),
None => return,
};
let Some(ref coverage_cx) = cx.coverage_cx else { return };
let mut covfun_records = instances_used
.iter()
.copied()
let mut covfun_records = coverage_cx
.instances_used()
.into_iter()
// Sort by symbol name, so that the global file table is built in an
// order that doesn't depend on the stable-hash-based order in which
// instances were visited during codegen.
.sorted_by_cached_key(|&instance| tcx.symbol_name(instance).name)
.filter_map(|instance| prepare_covfun_record(tcx, instance, true))
.collect::<Vec<_>>();
drop(instances_used);
// In a single designated CGU, also prepare covfun records for functions
// in this crate that were instrumented for coverage, but are unused.

View file

@ -5,7 +5,7 @@ use rustc_abi::Size;
use rustc_codegen_ssa::traits::{
BuilderMethods, ConstCodegenMethods, CoverageInfoBuilderMethods, MiscCodegenMethods,
};
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::ty::Instance;
use tracing::{debug, instrument};
@ -20,9 +20,14 @@ mod mapgen;
/// Extra per-CGU context/state needed for coverage instrumentation.
pub(crate) struct CguCoverageContext<'ll, 'tcx> {
/// Coverage data for each instrumented function identified by DefId.
pub(crate) instances_used: RefCell<FxIndexSet<Instance<'tcx>>>,
pub(crate) pgo_func_name_var_map: RefCell<FxHashMap<Instance<'tcx>, &'ll llvm::Value>>,
/// Associates function instances with an LLVM global that holds the
/// function's symbol name, as needed by LLVM coverage intrinsics.
///
/// Instances in this map are also considered "used" for the purposes of
/// emitting covfun records. Every covfun record holds a hash of its
/// symbol name, and `llvm-cov` will exit fatally if it can't resolve that
/// hash back to an entry in the binary's `__llvm_prf_names` linker section.
pub(crate) pgo_func_name_var_map: RefCell<FxIndexMap<Instance<'tcx>, &'ll llvm::Value>>,
pub(crate) mcdc_condition_bitmap_map: RefCell<FxHashMap<Instance<'tcx>, Vec<&'ll llvm::Value>>>,
covfun_section_name: OnceCell<CString>,
@ -31,7 +36,6 @@ pub(crate) struct CguCoverageContext<'ll, 'tcx> {
impl<'ll, 'tcx> CguCoverageContext<'ll, 'tcx> {
pub(crate) fn new() -> Self {
Self {
instances_used: RefCell::<FxIndexSet<_>>::default(),
pgo_func_name_var_map: Default::default(),
mcdc_condition_bitmap_map: Default::default(),
covfun_section_name: Default::default(),
@ -53,6 +57,14 @@ impl<'ll, 'tcx> CguCoverageContext<'ll, 'tcx> {
.and_then(|bitmap_map| bitmap_map.get(decision_depth as usize))
.copied() // Dereference Option<&&Value> to Option<&Value>
}
/// Returns the list of instances considered "used" in this CGU, as
/// inferred from the keys of `pgo_func_name_var_map`.
pub(crate) fn instances_used(&self) -> Vec<Instance<'tcx>> {
// Collecting into a Vec is way easier than trying to juggle RefCell
// projections, and this should only run once per CGU anyway.
self.pgo_func_name_var_map.borrow().keys().copied().collect::<Vec<_>>()
}
}
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
@ -78,7 +90,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
/// string, to hold the function name passed to LLVM intrinsic
/// `instrprof.increment()`. The `Value` is only created once per instance.
/// Multiple invocations with the same instance return the same `Value`.
fn get_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value {
///
/// This has the side-effect of causing coverage codegen to consider this
/// function "used", making it eligible to emit an associated covfun record.
fn ensure_pgo_func_name_var(&self, instance: Instance<'tcx>) -> &'ll llvm::Value {
debug!("getting pgo_func_name_var for instance={:?}", instance);
let mut pgo_func_name_var_map = self.coverage_cx().pgo_func_name_var_map.borrow_mut();
pgo_func_name_var_map.entry(instance).or_insert_with(|| {
@ -102,7 +117,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
return;
}
let fn_name = self.get_pgo_func_name_var(instance);
let fn_name = self.ensure_pgo_func_name_var(instance);
let hash = self.const_u64(function_coverage_info.function_source_hash);
let bitmap_bits = self.const_u32(function_coverage_info.mcdc_bitmap_bits as u32);
self.mcdc_parameters(fn_name, hash, bitmap_bits);
@ -151,11 +166,6 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
return;
};
// Mark the instance as used in this CGU, for coverage purposes.
// This includes functions that were not partitioned into this CGU,
// but were MIR-inlined into one of this CGU's functions.
coverage_cx.instances_used.borrow_mut().insert(instance);
match *kind {
CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!(
"marker statement {kind:?} should have been removed by CleanupPostBorrowck"
@ -163,7 +173,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
CoverageKind::VirtualCounter { bcb }
if let Some(&id) = ids_info.phys_counter_for_node.get(&bcb) =>
{
let fn_name = bx.get_pgo_func_name_var(instance);
let fn_name = bx.ensure_pgo_func_name_var(instance);
let hash = bx.const_u64(function_coverage_info.function_source_hash);
let num_counters = bx.const_u32(ids_info.num_counters);
let index = bx.const_u32(id.as_u32());
@ -193,7 +203,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
"bitmap index of the decision out of range"
);
let fn_name = bx.get_pgo_func_name_var(instance);
let fn_name = bx.ensure_pgo_func_name_var(instance);
let hash = bx.const_u64(function_coverage_info.function_source_hash);
let bitmap_index = bx.const_u32(bitmap_idx);
bx.mcdc_tvbitmap_update(fn_name, hash, bitmap_index, cond_bitmap);

View file

@ -39,7 +39,7 @@ pub(crate) struct AutoDiffWithoutEnable;
#[derive(Diagnostic)]
#[diag(codegen_llvm_lto_bitcode_from_rlib)]
pub(crate) struct LtoBitcodeFromRlib {
pub llvm_err: String,
pub err: String,
}
#[derive(Diagnostic)]

View file

@ -168,13 +168,6 @@ impl WriteBackendMethods for LlvmCodegenBackend {
let stats = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatistics(s) }).unwrap();
print!("{stats}");
}
fn run_link(
cgcx: &CodegenContext<Self>,
dcx: DiagCtxtHandle<'_>,
modules: Vec<ModuleCodegen<Self::Module>>,
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
back::write::link(cgcx, dcx, modules)
}
fn run_and_optimize_fat_lto(
cgcx: &CodegenContext<Self>,
exported_symbols_for_lto: &[String],

View file

@ -2612,13 +2612,6 @@ unsafe extern "C" {
len: usize,
Identifier: *const c_char,
) -> Option<&Module>;
pub(crate) fn LLVMRustGetSliceFromObjectDataByName(
data: *const u8,
len: usize,
name: *const u8,
name_len: usize,
out_len: &mut usize,
) -> *const u8;
pub(crate) fn LLVMRustLinkerNew(M: &Module) -> &mut Linker<'_>;
pub(crate) fn LLVMRustLinkerAdd(

View file

@ -1,4 +1,3 @@
use std::any::Any;
use std::assert_matches::assert_matches;
use std::marker::PhantomData;
use std::path::{Path, PathBuf};
@ -372,8 +371,6 @@ pub struct CodegenContext<B: WriteBackendMethods> {
/// The incremental compilation session directory, or None if we are not
/// compiling incrementally
pub incr_comp_session_dir: Option<PathBuf>,
/// Channel back to the main control thread to send messages to
pub coordinator_send: Sender<Box<dyn Any + Send>>,
/// `true` if the codegen should be run in parallel.
///
/// Depends on [`ExtraBackendMethods::supports_parallel()`] and `-Zno_parallel_backend`.
@ -800,10 +797,6 @@ pub(crate) enum WorkItemResult<B: WriteBackendMethods> {
/// The backend has finished compiling a CGU, nothing more required.
Finished(CompiledModule),
/// The backend has finished compiling a CGU, which now needs linking
/// because `-Zcombine-cgu` was specified.
NeedsLink(ModuleCodegen<B::Module>),
/// The backend has finished compiling a CGU, which now needs to go through
/// fat LTO.
NeedsFatLto(FatLtoInput<B>),
@ -887,7 +880,10 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
};
match lto_type {
ComputedLtoType::No => finish_intra_module_work(cgcx, module, module_config),
ComputedLtoType::No => {
let module = B::codegen(cgcx, module, module_config)?;
Ok(WorkItemResult::Finished(module))
}
ComputedLtoType::Thin => {
let (name, thin_buffer) = B::prepare_thin(module, false);
if let Some(path) = bitcode {
@ -1027,20 +1023,8 @@ fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
module_config: &ModuleConfig,
) -> Result<WorkItemResult<B>, FatalError> {
let module = B::optimize_thin(cgcx, module)?;
finish_intra_module_work(cgcx, module, module_config)
}
fn finish_intra_module_work<B: ExtraBackendMethods>(
cgcx: &CodegenContext<B>,
module: ModuleCodegen<B::Module>,
module_config: &ModuleConfig,
) -> Result<WorkItemResult<B>, FatalError> {
if !cgcx.opts.unstable_opts.combine_cgu || module.kind == ModuleKind::Allocator {
let module = B::codegen(cgcx, module, module_config)?;
Ok(WorkItemResult::Finished(module))
} else {
Ok(WorkItemResult::NeedsLink(module))
}
let module = B::codegen(cgcx, module, module_config)?;
Ok(WorkItemResult::Finished(module))
}
/// Messages sent to the coordinator.
@ -1122,10 +1106,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
autodiff_items: &[AutoDiffItem],
shared_emitter: SharedEmitter,
codegen_worker_send: Sender<CguMessage>,
coordinator_receive: Receiver<Box<dyn Any + Send>>,
coordinator_receive: Receiver<Message<B>>,
regular_config: Arc<ModuleConfig>,
allocator_config: Arc<ModuleConfig>,
tx_to_llvm_workers: Sender<Box<dyn Any + Send>>,
tx_to_llvm_workers: Sender<Message<B>>,
) -> thread::JoinHandle<Result<CompiledModules, ()>> {
let coordinator_send = tx_to_llvm_workers;
let sess = tcx.sess;
@ -1153,7 +1137,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
let coordinator_send2 = coordinator_send.clone();
let helper = jobserver::client()
.into_helper_thread(move |token| {
drop(coordinator_send2.send(Box::new(Message::Token::<B>(token))));
drop(coordinator_send2.send(Message::Token::<B>(token)));
})
.expect("failed to spawn helper thread");
@ -1187,7 +1171,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
remark: sess.opts.cg.remark.clone(),
remark_dir,
incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()),
coordinator_send,
expanded_args: tcx.sess.expanded_args.clone(),
diag_emitter: shared_emitter.clone(),
output_filenames: Arc::clone(tcx.output_filenames(())),
@ -1347,7 +1330,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
// through codegen and LLVM.
let mut compiled_modules = vec![];
let mut compiled_allocator_module = None;
let mut needs_link = Vec::new();
let mut needs_fat_lto = Vec::new();
let mut needs_thin_lto = Vec::new();
let mut lto_import_only_modules = Vec::new();
@ -1423,7 +1405,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
let (item, _) =
work_items.pop().expect("queue empty - queue_full_enough() broken?");
main_thread_state = MainThreadState::Lending;
spawn_work(&cgcx, &mut llvm_start_time, item);
spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item);
}
}
} else if codegen_state == Completed {
@ -1502,7 +1484,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
MainThreadState::Idle => {
if let Some((item, _)) = work_items.pop() {
main_thread_state = MainThreadState::Lending;
spawn_work(&cgcx, &mut llvm_start_time, item);
spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item);
} else {
// There is no unstarted work, so let the main thread
// take over for a running worker. Otherwise the
@ -1538,7 +1520,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
while running_with_own_token < tokens.len()
&& let Some((item, _)) = work_items.pop()
{
spawn_work(&cgcx, &mut llvm_start_time, item);
spawn_work(&cgcx, coordinator_send.clone(), &mut llvm_start_time, item);
running_with_own_token += 1;
}
}
@ -1546,8 +1528,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
// Relinquish accidentally acquired extra tokens.
tokens.truncate(running_with_own_token);
let msg = coordinator_receive.recv().unwrap();
match *msg.downcast::<Message<B>>().ok().unwrap() {
match coordinator_receive.recv().unwrap() {
// Save the token locally and the next turn of the loop will use
// this to spawn a new unit of work, or it may get dropped
// immediately if we have no more work to spawn.
@ -1630,7 +1611,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
Ok(WorkItemResult::Finished(compiled_module)) => {
match compiled_module.kind {
ModuleKind::Regular => {
assert!(needs_link.is_empty());
compiled_modules.push(compiled_module);
}
ModuleKind::Allocator => {
@ -1639,10 +1619,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
}
}
}
Ok(WorkItemResult::NeedsLink(module)) => {
assert!(compiled_modules.is_empty());
needs_link.push(module);
}
Ok(WorkItemResult::NeedsFatLto(fat_lto_input)) => {
assert!(!started_lto);
assert!(needs_thin_lto.is_empty());
@ -1679,17 +1655,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
return Err(());
}
let needs_link = mem::take(&mut needs_link);
if !needs_link.is_empty() {
assert!(compiled_modules.is_empty());
let dcx = cgcx.create_dcx();
let dcx = dcx.handle();
let module = B::run_link(&cgcx, dcx, needs_link).map_err(|_| ())?;
let module =
B::codegen(&cgcx, module, cgcx.config(ModuleKind::Regular)).map_err(|_| ())?;
compiled_modules.push(module);
}
// Drop to print timings
drop(llvm_start_time);
@ -1769,6 +1734,7 @@ pub(crate) struct WorkerFatalError;
fn spawn_work<'a, B: ExtraBackendMethods>(
cgcx: &'a CodegenContext<B>,
coordinator_send: Sender<Message<B>>,
llvm_start_time: &mut Option<VerboseTimingGuard<'a>>,
work: WorkItem<B>,
) {
@ -1782,7 +1748,7 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
// Set up a destructor which will fire off a message that we're done as
// we exit.
struct Bomb<B: ExtraBackendMethods> {
coordinator_send: Sender<Box<dyn Any + Send>>,
coordinator_send: Sender<Message<B>>,
result: Option<Result<WorkItemResult<B>, FatalError>>,
}
impl<B: ExtraBackendMethods> Drop for Bomb<B> {
@ -1794,11 +1760,11 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
}
None => Message::WorkItem::<B> { result: Err(None) },
};
drop(self.coordinator_send.send(Box::new(msg)));
drop(self.coordinator_send.send(msg));
}
}
let mut bomb = Bomb::<B> { coordinator_send: cgcx.coordinator_send.clone(), result: None };
let mut bomb = Bomb::<B> { coordinator_send, result: None };
// Execute the work itself, and if it finishes successfully then flag
// ourselves as a success as well.
@ -2003,7 +1969,7 @@ impl SharedEmitterMain {
}
pub struct Coordinator<B: ExtraBackendMethods> {
pub sender: Sender<Box<dyn Any + Send>>,
sender: Sender<Message<B>>,
future: Option<thread::JoinHandle<Result<CompiledModules, ()>>>,
// Only used for the Message type.
phantom: PhantomData<B>,
@ -2020,7 +1986,7 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
if let Some(future) = self.future.take() {
// If we haven't joined yet, signal to the coordinator that it should spawn no more
// work, and wait for worker threads to finish.
drop(self.sender.send(Box::new(Message::CodegenAborted::<B>)));
drop(self.sender.send(Message::CodegenAborted::<B>));
drop(future.join());
}
}
@ -2079,7 +2045,7 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
pub(crate) fn codegen_finished(&self, tcx: TyCtxt<'_>) {
self.wait_for_signal_to_codegen_item();
self.check_for_errors(tcx.sess);
drop(self.coordinator.sender.send(Box::new(Message::CodegenComplete::<B>)));
drop(self.coordinator.sender.send(Message::CodegenComplete::<B>));
}
pub(crate) fn check_for_errors(&self, sess: &Session) {
@ -2100,28 +2066,25 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
}
pub(crate) fn submit_codegened_module_to_llvm<B: ExtraBackendMethods>(
_backend: &B,
tx_to_llvm_workers: &Sender<Box<dyn Any + Send>>,
coordinator: &Coordinator<B>,
module: ModuleCodegen<B::Module>,
cost: u64,
) {
let llvm_work_item = WorkItem::Optimize(module);
drop(tx_to_llvm_workers.send(Box::new(Message::CodegenDone::<B> { llvm_work_item, cost })));
drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost }));
}
pub(crate) fn submit_post_lto_module_to_llvm<B: ExtraBackendMethods>(
_backend: &B,
tx_to_llvm_workers: &Sender<Box<dyn Any + Send>>,
coordinator: &Coordinator<B>,
module: CachedModuleCodegen,
) {
let llvm_work_item = WorkItem::CopyPostLtoArtifacts(module);
drop(tx_to_llvm_workers.send(Box::new(Message::CodegenDone::<B> { llvm_work_item, cost: 0 })));
drop(coordinator.sender.send(Message::CodegenDone::<B> { llvm_work_item, cost: 0 }));
}
pub(crate) fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>(
_backend: &B,
tcx: TyCtxt<'_>,
tx_to_llvm_workers: &Sender<Box<dyn Any + Send>>,
coordinator: &Coordinator<B>,
module: CachedModuleCodegen,
) {
let filename = pre_lto_bitcode_filename(&module.name);
@ -2135,10 +2098,10 @@ pub(crate) fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>(
})
};
// Schedule the module to be loaded
drop(tx_to_llvm_workers.send(Box::new(Message::AddImportOnlyModule::<B> {
drop(coordinator.sender.send(Message::AddImportOnlyModule::<B> {
module_data: SerializedModule::FromUncompressedFile(mmap),
work_product: module.source,
})));
}));
}
fn pre_lto_bitcode_filename(module_name: &str) -> String {

View file

@ -702,8 +702,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// These modules are generally cheap and won't throw off scheduling.
let cost = 0;
submit_codegened_module_to_llvm(
&backend,
&ongoing_codegen.coordinator.sender,
&ongoing_codegen.coordinator,
ModuleCodegen::new_allocator(llmod_id, module_llvm),
cost,
);
@ -800,18 +799,12 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
// compilation hang on post-monomorphization errors.
tcx.dcx().abort_if_errors();
submit_codegened_module_to_llvm(
&backend,
&ongoing_codegen.coordinator.sender,
module,
cost,
);
submit_codegened_module_to_llvm(&ongoing_codegen.coordinator, module, cost);
}
CguReuse::PreLto => {
submit_pre_lto_module_to_llvm(
&backend,
tcx,
&ongoing_codegen.coordinator.sender,
&ongoing_codegen.coordinator,
CachedModuleCodegen {
name: cgu.name().to_string(),
source: cgu.previous_work_product(tcx),
@ -820,8 +813,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
}
CguReuse::PostLto => {
submit_post_lto_module_to_llvm(
&backend,
&ongoing_codegen.coordinator.sender,
&ongoing_codegen.coordinator,
CachedModuleCodegen {
name: cgu.name().to_string(),
source: cgu.previous_work_product(tcx),

View file

@ -16,12 +16,6 @@ pub trait WriteBackendMethods: Clone + 'static {
type ThinData: Send + Sync;
type ThinBuffer: ThinBufferMethods;
/// Merge all modules into main_module and returning it
fn run_link(
cgcx: &CodegenContext<Self>,
dcx: DiagCtxtHandle<'_>,
modules: Vec<ModuleCodegen<Self::Module>>,
) -> Result<ModuleCodegen<Self::Module>, FatalError>;
/// Performs fat LTO by merging all modules into a single one, running autodiff
/// if necessary and running any further optimizations
fn run_and_optimize_fat_lto(

View file

@ -1650,40 +1650,6 @@ extern "C" LLVMModuleRef LLVMRustParseBitcodeForLTO(LLVMContextRef Context,
return wrap(std::move(*SrcOrError).release());
}
// Find a section of an object file by name. Fail if the section is missing or
// empty.
extern "C" const char *LLVMRustGetSliceFromObjectDataByName(const char *data,
size_t len,
const char *name,
size_t name_len,
size_t *out_len) {
*out_len = 0;
auto Name = StringRef(name, name_len);
auto Data = StringRef(data, len);
auto Buffer = MemoryBufferRef(Data, ""); // The id is unused.
file_magic Type = identify_magic(Buffer.getBuffer());
Expected<std::unique_ptr<object::ObjectFile>> ObjFileOrError =
object::ObjectFile::createObjectFile(Buffer, Type);
if (!ObjFileOrError) {
LLVMRustSetLastError(toString(ObjFileOrError.takeError()).c_str());
return nullptr;
}
for (const object::SectionRef &Sec : (*ObjFileOrError)->sections()) {
Expected<StringRef> SecName = Sec.getName();
if (SecName && *SecName == Name) {
Expected<StringRef> SectionOrError = Sec.getContents();
if (!SectionOrError) {
LLVMRustSetLastError(toString(SectionOrError.takeError()).c_str());
return nullptr;
}
*out_len = SectionOrError->size();
return SectionOrError->data();
}
}
LLVMRustSetLastError("could not find requested section");
return nullptr;
}
// Computes the LTO cache key for the provided 'ModId' in the given 'Data',
// storing the result in 'KeyOut'.
// Currently, this cache key is a SHA-1 hash of anything that could affect

View file

@ -2168,8 +2168,6 @@ options! {
"hash algorithm of source files used to check freshness in cargo (`blake3` or `sha256`)"),
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
"the backend to use"),
combine_cgu: bool = (false, parse_bool, [TRACKED],
"combine CGUs into a single one"),
contract_checks: Option<bool> = (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],

View file

@ -407,17 +407,22 @@ impl str {
/// ```
#[unstable(feature = "round_char_boundary", issue = "93743")]
#[inline]
pub fn floor_char_boundary(&self, index: usize) -> usize {
pub const fn floor_char_boundary(&self, index: usize) -> usize {
if index >= self.len() {
self.len()
} else {
let lower_bound = index.saturating_sub(3);
let new_index = self.as_bytes()[lower_bound..=index]
.iter()
.rposition(|b| b.is_utf8_char_boundary());
let mut i = index;
while i > 0 {
if self.as_bytes()[i].is_utf8_char_boundary() {
break;
}
i -= 1;
}
// SAFETY: we know that the character boundary will be within four bytes
unsafe { lower_bound + new_index.unwrap_unchecked() }
// The character boundary will be within four bytes of the index
debug_assert!(i >= index.saturating_sub(3));
i
}
}
@ -445,15 +450,22 @@ impl str {
/// ```
#[unstable(feature = "round_char_boundary", issue = "93743")]
#[inline]
pub fn ceil_char_boundary(&self, index: usize) -> usize {
pub const fn ceil_char_boundary(&self, index: usize) -> usize {
if index >= self.len() {
self.len()
} else {
let upper_bound = Ord::min(index + 4, self.len());
self.as_bytes()[index..upper_bound]
.iter()
.position(|b| b.is_utf8_char_boundary())
.map_or(upper_bound, |pos| pos + index)
let mut i = index;
while i < self.len() {
if self.as_bytes()[i].is_utf8_char_boundary() {
break;
}
i += 1;
}
// The character boundary will be within four bytes of the index
debug_assert!(i <= index + 3);
i
}
}

View file

@ -563,8 +563,8 @@ impl AtomicBool {
/// `align_of::<AtomicBool>() == 1`).
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
/// without synchronization.
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
@ -1246,7 +1246,7 @@ impl AtomicBool {
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
/// restriction: operations on it must be atomic.
/// restriction in [Memory model for atomic accesses].
///
/// # Examples
///
@ -1264,6 +1264,8 @@ impl AtomicBool {
/// }
/// # }
/// ```
///
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
@ -1519,8 +1521,8 @@ impl<T> AtomicPtr<T> {
/// can be bigger than `align_of::<*mut T>()`).
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
/// without synchronization.
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
@ -2488,7 +2490,7 @@ impl<T> AtomicPtr<T> {
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
/// restriction: operations on it must be atomic.
/// restriction in [Memory model for atomic accesses].
///
/// # Examples
///
@ -2507,6 +2509,8 @@ impl<T> AtomicPtr<T> {
/// my_atomic_op(atomic.as_ptr());
/// }
/// ```
///
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]
@ -2698,8 +2702,8 @@ macro_rules! atomic_int {
}]
/// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
/// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
/// allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
/// without synchronization.
/// allowed to mix conflicting atomic and non-atomic accesses, or atomic accesses of different
/// sizes, without synchronization.
///
/// [valid]: crate::ptr#safety
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
@ -3620,7 +3624,7 @@ macro_rules! atomic_int {
/// atomic types work with interior mutability. All modifications of an atomic change the value
/// through a shared reference, and can do so safely as long as they use atomic operations. Any
/// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
/// restriction: operations on it must be atomic.
/// restriction in [Memory model for atomic accesses].
///
/// # Examples
///
@ -3640,6 +3644,8 @@ macro_rules! atomic_int {
/// }
/// # }
/// ```
///
/// [Memory model for atomic accesses]: self#memory-model-for-atomic-accesses
#[inline]
#[stable(feature = "atomic_as_ptr", since = "1.70.0")]
#[rustc_const_stable(feature = "atomic_as_ptr", since = "1.70.0")]

View file

@ -9,6 +9,9 @@ edition = "2024"
[lib]
path = "lib.rs"
test = false
bench = false
doc = false
[dependencies]
alloc = { path = "../alloc" }

View file

@ -11,6 +11,9 @@ edition = "2024"
[lib]
path = "lib.rs"
test = false
bench = false
doc = false
[dependencies]
core = { path = "../core", public = true }

View file

@ -9,6 +9,9 @@ edition = "2024"
[lib]
path = "lib.rs"
test = false
bench = false
doc = false
[dependencies]
std = { path = "../std" }

View file

@ -131,14 +131,13 @@ macro_rules! features {
};
}
#[test] //tidy:skip
#[deny(unexpected_cfgs)]
#[deny(unfulfilled_lint_expectations)]
fn unexpected_cfgs() {
const _: () = {
$(
check_cfg_feature!($feature, $feature_lit $(, without cfg check: $feature_cfg_check)? $(: $($target_feature_lit),*)?);
)*
}
};
/// Each variant denotes a position in a bitset for a particular feature.
///

View file

@ -135,4 +135,5 @@ pub(crate) fn imply_features(mut value: cache::Initializer) -> cache::Initialize
}
#[cfg(test)]
#[path = "riscv/tests.rs"]
mod tests;

View file

@ -6,6 +6,8 @@ version = "0.0.0"
edition = "2024"
[lib]
test = false
bench = false
# make sure this crate isn't included in public standard library docs
doc = false

View file

@ -4,6 +4,11 @@ description = "A drop-in replacement for the real windows-targets crate for use
version = "0.0.0"
edition = "2024"
[lib]
test = false
bench = false
doc = false
[features]
# Enable using raw-dylib for Windows imports.
# This will eventually be the default.

View file

@ -1,6 +1,6 @@
[package]
name = "miropt-test-tools"
version = "0.1.0"
edition = "2021"
edition = "2024"
[dependencies]

View file

@ -34,7 +34,7 @@ fn output_file_suffix(testfile: &Path, bit_width: u32, panic_strategy: PanicStra
let mut suffix = String::new();
if each_bit_width {
suffix.push_str(&format!(".{}bit", bit_width));
suffix.push_str(&format!(".{bit_width}bit"));
}
if each_panic_strategy {
match panic_strategy {
@ -51,7 +51,7 @@ pub fn files_for_miropt_test(
panic_strategy: PanicStrategy,
) -> MiroptTest {
let mut out = Vec::new();
let test_file_contents = fs::read_to_string(&testfile).unwrap();
let test_file_contents = fs::read_to_string(testfile).unwrap();
let test_dir = testfile.parent().unwrap();
let test_crate = testfile.file_stem().unwrap().to_str().unwrap().replace('-', "_");
@ -76,10 +76,10 @@ pub fn files_for_miropt_test(
if test_name.ends_with(".diff") {
let trimmed = test_name.trim_end_matches(".diff");
passes.push(trimmed.split('.').last().unwrap().to_owned());
let test_against = format!("{}.after.mir", trimmed);
from_file = format!("{}.before.mir", trimmed);
expected_file = format!("{}{}.diff", trimmed, suffix);
passes.push(trimmed.split('.').next_back().unwrap().to_owned());
let test_against = format!("{trimmed}.after.mir");
from_file = format!("{trimmed}.before.mir");
expected_file = format!("{trimmed}{suffix}.diff");
assert!(test_names.next().is_none(), "two mir pass names specified for MIR diff");
to_file = Some(test_against);
} else if let Some(first_pass) = test_names.next() {
@ -92,10 +92,9 @@ pub fn files_for_miropt_test(
}
assert!(test_names.next().is_none(), "three mir pass names specified for MIR diff");
expected_file =
format!("{}{}.{}-{}.diff", test_name, suffix, first_pass, second_pass);
let second_file = format!("{}.{}.mir", test_name, second_pass);
from_file = format!("{}.{}.mir", test_name, first_pass);
expected_file = format!("{test_name}{suffix}.{first_pass}-{second_pass}.diff");
let second_file = format!("{test_name}.{second_pass}.mir");
from_file = format!("{test_name}.{first_pass}.mir");
to_file = Some(second_file);
} else {
// Allow-list for file extensions that can be produced by MIR dumps.
@ -112,7 +111,7 @@ pub fn files_for_miropt_test(
)
}
expected_file = format!("{}{}.{}", test_name_wo_ext, suffix, test_name_ext);
expected_file = format!("{test_name_wo_ext}{suffix}.{test_name_ext}");
from_file = test_name.to_string();
assert!(test_names.next().is_none(), "two mir pass names specified for MIR dump");
to_file = None;
@ -123,7 +122,7 @@ pub fn files_for_miropt_test(
);
};
if !expected_file.starts_with(&test_crate) {
expected_file = format!("{}.{}", test_crate, expected_file);
expected_file = format!("{test_crate}.{expected_file}");
}
let expected_file = test_dir.join(expected_file);

View file

@ -128,9 +128,9 @@ fn main() {
check!(pal, &library_path);
// Checks that need to be done for both the compiler and std libraries.
check!(unit_tests, &src_path);
check!(unit_tests, &compiler_path);
check!(unit_tests, &library_path);
check!(unit_tests, &src_path, false);
check!(unit_tests, &compiler_path, false);
check!(unit_tests, &library_path, true);
if bins::check_filesystem_support(&[&root_path], &output_directory) {
check!(bins, &root_path);

View file

@ -1,44 +1,60 @@
//! Tidy check to ensure `#[test]` and `#[bench]` are not used directly inside
//! `core` or `alloc`.
//! of the standard library.
//!
//! `core` and `alloc` cannot be tested directly due to duplicating lang items.
//! All tests and benchmarks must be written externally in
//! `{coretests,alloctests}/{tests,benches}`.
//!
//! Outside of `core` and `alloc`, tests and benchmarks should be outlined into
//! separate files named `tests.rs` or `benches.rs`, or directories named
//! Outside of the standard library, tests and benchmarks should be outlined
//! into separate files named `tests.rs` or `benches.rs`, or directories named
//! `tests` or `benches` unconfigured during normal build.
use std::path::Path;
use crate::walk::{filter_dirs, walk};
pub fn check(root_path: &Path, bad: &mut bool) {
let core = root_path.join("core");
let core_copy = core.clone();
let is_core = move |path: &Path| path.starts_with(&core);
let alloc = root_path.join("alloc");
let alloc_copy = alloc.clone();
let is_alloc = move |path: &Path| path.starts_with(&alloc);
pub fn check(root_path: &Path, stdlib: bool, bad: &mut bool) {
let skip = move |path: &Path, is_dir| {
let file_name = path.file_name().unwrap_or_default();
// Skip excluded directories and non-rust files
if is_dir {
filter_dirs(path)
|| path.ends_with("src/doc")
|| (file_name == "tests" || file_name == "benches")
&& !is_core(path)
&& !is_alloc(path)
if filter_dirs(path) || path.ends_with("src/doc") {
return true;
}
} else {
let extension = path.extension().unwrap_or_default();
extension != "rs"
|| (file_name == "tests.rs" || file_name == "benches.rs")
&& !is_core(path)
&& !is_alloc(path)
// Tests which use non-public internals and, as such, need to
// have the types in the same crate as the tests themselves. See
// the comment in alloctests/lib.rs.
|| path.ends_with("library/alloc/src/collections/btree/borrow/tests.rs")
if extension != "rs" {
return true;
}
}
// Tests in a separate package are always allowed
if is_dir && file_name != "tests" && file_name.as_encoded_bytes().ends_with(b"tests") {
return true;
}
if !stdlib {
// Outside of the standard library tests may also be in separate files in the same crate
if is_dir {
if file_name == "tests" || file_name == "benches" {
return true;
}
} else {
if file_name == "tests.rs" || file_name == "benches.rs" {
return true;
}
}
}
if is_dir {
// FIXME remove those exceptions once no longer necessary
file_name == "std_detect" || file_name == "std" || file_name == "test"
} else {
// Tests which use non-public internals and, as such, need to
// have the types in the same crate as the tests themselves. See
// the comment in alloctests/lib.rs.
path.ends_with("library/alloc/src/collections/btree/borrow/tests.rs")
|| path.ends_with("library/alloc/src/collections/btree/map/tests.rs")
|| path.ends_with("library/alloc/src/collections/btree/node/tests.rs")
|| path.ends_with("library/alloc/src/collections/btree/set/tests.rs")
@ -50,22 +66,29 @@ pub fn check(root_path: &Path, bad: &mut bool) {
walk(root_path, skip, &mut |entry, contents| {
let path = entry.path();
let is_core = path.starts_with(&core_copy);
let is_alloc = path.starts_with(&alloc_copy);
let package = path
.strip_prefix(root_path)
.unwrap()
.components()
.next()
.unwrap()
.as_os_str()
.to_str()
.unwrap();
for (i, line) in contents.lines().enumerate() {
let line = line.trim();
let is_test = || line.contains("#[test]") && !line.contains("`#[test]");
let is_bench = || line.contains("#[bench]") && !line.contains("`#[bench]");
let manual_skip = line.contains("//tidy:skip");
if !line.starts_with("//") && (is_test() || is_bench()) && !manual_skip {
let explanation = if is_core {
"`core` unit tests and benchmarks must be placed into `coretests`"
} else if is_alloc {
"`alloc` unit tests and benchmarks must be placed into `alloctests`"
if !line.starts_with("//") && (is_test() || is_bench()) {
let explanation = if stdlib {
format!(
"`{package}` unit tests and benchmarks must be placed into `{package}tests`"
)
} else {
"unit tests and benchmarks must be placed into \
separate files or directories named \
`tests.rs`, `benches.rs`, `tests` or `benches`"
.to_owned()
};
let name = if is_test() { "test" } else { "bench" };
tidy_error!(

View file

@ -412,6 +412,10 @@ These tests revolve around command-line flags which change the way error/warning
Exercises `#[diagnostic::*]` namespaced attributes. See [RFC 3368 Diagnostic attribute namespace](https://github.com/rust-lang/rfcs/blob/master/text/3368-diagnostic-attribute-namespace.md).
## `tests/ui/diagnostics-infra`
This directory contains tests and infrastructure related to the diagnostics system, including support for translatable diagnostics
## `tests/ui/diagnostic-width/`: `--diagnostic-width`
Everything to do with `--diagnostic-width`.

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/11192
struct Foo {
x: isize
}

View file

@ -1,5 +1,5 @@
error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as mutable
--> $DIR/issue-11192.rs:20:10
--> $DIR/closure-borrow-conflict-11192.rs:22:10
|
LL | let mut test = |foo: &Foo| {
| ----------- mutable borrow occurs here

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/11085
//@ run-pass
#![allow(dead_code)]

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/11205
//@ run-pass
#![allow(dead_code)]

View file

@ -0,0 +1,24 @@
//! Regression test for https://github.com/rust-lang/rust/issues/106755
//@ compile-flags:-Ztranslate-lang=en_US
#![feature(negative_impls)]
#![feature(marker_trait_attr)]
#[marker]
trait MyTrait {}
struct TestType<T>(::std::marker::PhantomData<T>);
unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
impl<T: MyTrait> !Send for TestType<T> {}
//~^ ERROR found both positive and negative implementation
//~| ERROR `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
unsafe impl<T: 'static> Send for TestType<T> {} //~ ERROR conflicting implementations
impl !Send for TestType<i32> {}
//~^ ERROR `!Send` impls cannot be specialized
fn main() {}

View file

@ -0,0 +1,47 @@
error[E0751]: found both positive and negative implementation of trait `Send` for type `TestType<_>`:
--> $DIR/primary-fluent-bundle-missing.rs:15:1
|
LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
| ------------------------------------------------------ positive implementation here
LL |
LL | impl<T: MyTrait> !Send for TestType<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
error[E0119]: conflicting implementations of trait `Send` for type `TestType<_>`
--> $DIR/primary-fluent-bundle-missing.rs:19:1
|
LL | unsafe impl<T: MyTrait + 'static> Send for TestType<T> {}
| ------------------------------------------------------ first implementation here
...
LL | unsafe impl<T: 'static> Send for TestType<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `TestType<_>`
error[E0367]: `!Send` impl requires `T: MyTrait` but the struct it is implemented for does not
--> $DIR/primary-fluent-bundle-missing.rs:15:9
|
LL | impl<T: MyTrait> !Send for TestType<T> {}
| ^^^^^^^
|
note: the implementor must specify the same requirement
--> $DIR/primary-fluent-bundle-missing.rs:11:1
|
LL | struct TestType<T>(::std::marker::PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^
error[E0366]: `!Send` impls cannot be specialized
--> $DIR/primary-fluent-bundle-missing.rs:21:1
|
LL | impl !Send for TestType<i32> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `i32` is not a generic parameter
note: use the same sequence of generic lifetime, type and const parameters as the struct definition
--> $DIR/primary-fluent-bundle-missing.rs:11:1
|
LL | struct TestType<T>(::std::marker::PhantomData<T>);
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0119, E0366, E0367, E0751.
For more information about an error, try `rustc --explain E0119`.

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10734
//@ run-pass
#![allow(non_upper_case_globals)]

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10802
//@ run-pass
#![allow(dead_code)]

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10764
fn f(_: extern "Rust" fn()) {}
extern "C" fn bar() {}

View file

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/issue-10764.rs:4:15
--> $DIR/extern-rust-fn-type-error-10764.rs:6:15
|
LL | fn main() { f(bar) }
| - ^^^ expected "Rust" fn, found "C" fn
@ -9,7 +9,7 @@ LL | fn main() { f(bar) }
= note: expected fn pointer `fn()`
found fn item `extern "C" fn() {bar}`
note: function defined here
--> $DIR/issue-10764.rs:1:4
--> $DIR/extern-rust-fn-type-error-10764.rs:3:4
|
LL | fn f(_: extern "Rust" fn()) {}
| ^ ---------------------

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10877
struct Foo {
x: isize,
}

View file

@ -1,23 +1,23 @@
error[E0130]: patterns aren't allowed in foreign function declarations
--> $DIR/issue-10877.rs:5:12
--> $DIR/foreign-fn-pattern-error-10877.rs:7:12
|
LL | fn foo(1: ());
| ^ pattern not allowed in foreign function
error[E0130]: patterns aren't allowed in foreign function declarations
--> $DIR/issue-10877.rs:7:12
--> $DIR/foreign-fn-pattern-error-10877.rs:9:12
|
LL | fn bar((): isize);
| ^^ pattern not allowed in foreign function
error[E0130]: patterns aren't allowed in foreign function declarations
--> $DIR/issue-10877.rs:9:12
--> $DIR/foreign-fn-pattern-error-10877.rs:11:12
|
LL | fn baz(Foo { x }: isize);
| ^^^^^^^^^ pattern not allowed in foreign function
error[E0130]: patterns aren't allowed in foreign function declarations
--> $DIR/issue-10877.rs:11:12
--> $DIR/foreign-fn-pattern-error-10877.rs:13:12
|
LL | fn qux((x, y): ());
| ^^^^^^ pattern not allowed in foreign function

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10806
//@ edition: 2015
//@ run-pass
#![allow(unused_imports)]

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10718
//@ run-pass
fn f<F:FnOnce()>(p: F) {

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10436
//@ run-pass
fn works<T>(x: T) -> Vec<T> { vec![x] }

View file

@ -1,7 +0,0 @@
//@ run-pass
pub fn main() {
fn f() {
}
let _: Box<fn()> = Box::new(f as fn());
}

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10396
//@ check-pass
#![allow(dead_code)]
#[derive(Debug)]

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10291
fn test<'x>(x: &'x isize) {
drop::<Box<dyn for<'z> FnMut(&'z isize) -> &'z isize>>(Box::new(|z| {
x

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough
--> $DIR/issue-10291.rs:3:9
--> $DIR/closure-lifetime-bounds-10291.rs:5:9
|
LL | fn test<'x>(x: &'x isize) {
| -- lifetime `'x` defined here

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/11374
use std::io::{self, Read};
use std::vec;

View file

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/issue-11374.rs:27:15
--> $DIR/container-lifetime-error-11374.rs:29:15
|
LL | c.read_to(v);
| ------- ^ expected `&mut [u8]`, found `Vec<_>`
@ -9,7 +9,7 @@ LL | c.read_to(v);
= note: expected mutable reference `&mut [u8]`
found struct `Vec<_>`
note: method defined here
--> $DIR/issue-11374.rs:13:12
--> $DIR/container-lifetime-error-11374.rs:15:12
|
LL | pub fn read_to(&mut self, vec: &mut [u8]) {
| ^^^^^^^ --------------
@ -19,7 +19,7 @@ LL | c.read_to(&mut v);
| ++++
error[E0515]: cannot return value referencing local variable `r`
--> $DIR/issue-11374.rs:20:5
--> $DIR/container-lifetime-error-11374.rs:22:5
|
LL | Container::wrap(&mut r as &mut dyn io::Read)
| ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10228
//@ run-pass
#![allow(dead_code)]
#![allow(unused_variables)]

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10412
trait Serializable<'self, T> {
//~^ ERROR lifetimes cannot use keyword names
fn serialize(val: &'self T) -> Vec<u8>; //~ ERROR lifetimes cannot use keyword names

View file

@ -1,47 +1,47 @@
error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:1:20
--> $DIR/keyword-self-lifetime-error-10412.rs:3:20
|
LL | trait Serializable<'self, T> {
| ^^^^^
error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:3:24
--> $DIR/keyword-self-lifetime-error-10412.rs:5:24
|
LL | fn serialize(val: &'self T) -> Vec<u8>;
| ^^^^^
error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:4:37
--> $DIR/keyword-self-lifetime-error-10412.rs:6:37
|
LL | fn deserialize(repr: &[u8]) -> &'self T;
| ^^^^^
error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:7:6
--> $DIR/keyword-self-lifetime-error-10412.rs:9:6
|
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^
error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:7:36
--> $DIR/keyword-self-lifetime-error-10412.rs:9:36
|
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^
error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:11:24
--> $DIR/keyword-self-lifetime-error-10412.rs:13:24
|
LL | fn serialize(val: &'self str) -> Vec<u8> {
| ^^^^^
error: lifetimes cannot use keyword names
--> $DIR/issue-10412.rs:15:37
--> $DIR/keyword-self-lifetime-error-10412.rs:17:37
|
LL | fn deserialize(repr: &[u8]) -> &'self str {
| ^^^^^
error[E0726]: implicit elided lifetime not allowed here
--> $DIR/issue-10412.rs:7:13
--> $DIR/keyword-self-lifetime-error-10412.rs:9:13
|
LL | impl<'self> Serializable<str> for &'self str {
| ^^^^^^^^^^^^^^^^^ expected lifetime parameter

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10902
//@ check-pass
#![allow(dead_code)]

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10853
//@ check-pass
#![deny(missing_docs)]

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10638
//@ run-pass
pub fn main() {

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10683
//@ run-pass
static NAME: &'static str = "hello world";

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10545
mod a {
struct S;
impl S { }

View file

@ -1,11 +1,11 @@
error[E0603]: struct `S` is private
--> $DIR/issue-10545.rs:6:14
--> $DIR/struct-field-and-impl-expose-10545.rs:8:14
|
LL | fn foo(_: a::S) {
| ^ private struct
|
note: the struct `S` is defined here
--> $DIR/issue-10545.rs:2:5
--> $DIR/struct-field-and-impl-expose-10545.rs:4:5
|
LL | struct S;
| ^^^^^^^^^

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/11267
//@ run-pass
// Tests that unary structs can be mutably borrowed.

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10456
//@ check-pass
pub struct Foo;

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/10465
pub mod a {
pub trait A {
fn foo(&self);

View file

@ -1,5 +1,5 @@
error[E0599]: no method named `foo` found for reference `&B` in the current scope
--> $DIR/issue-10465.rs:17:15
--> $DIR/nested-mod-trait-method-lookup-leak-10465.rs:19:15
|
LL | b.foo();
| ^^^ method not found in `&B`

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/102964
use std::rc::Rc;
type Foo<'a, T> = &'a dyn Fn(&T);
type RcFoo<'a, T> = Rc<Foo<'a, T>>;

View file

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/issue-102964.rs:5:41
--> $DIR/dummy-binder-102964.rs:7:41
|
LL | fn bar_function<T>(function: Foo<T>) -> RcFoo<T> {
| ------------ ^^^^^^^^ expected `Rc<&dyn Fn(&T)>`, found `()`

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/11047
//@ run-pass
// Test that static methods can be invoked on `type` aliases

View file

@ -1,3 +1,5 @@
//! Regression test for https://github.com/rust-lang/rust/issues/11004
use std::mem;
struct A { x: i32, y: f64 }

View file

@ -1,5 +1,5 @@
error[E0609]: no field `x` on type `*mut A`
--> $DIR/issue-11004.rs:7:21
--> $DIR/raw-pointer-field-access-error.rs:9:21
|
LL | let x : i32 = n.x;
| ^ unknown field
@ -10,7 +10,7 @@ LL | let x : i32 = (*n).x;
| ++ +
error[E0609]: no field `y` on type `*mut A`
--> $DIR/issue-11004.rs:8:21
--> $DIR/raw-pointer-field-access-error.rs:10:21
|
LL | let y : f64 = n.y;
| ^ unknown field