1
Fork 0

Auto merge of #125463 - GuillaumeGomez:rollup-287wx4y, r=GuillaumeGomez

Rollup of 6 pull requests

Successful merges:

 - #125263 (rust-lld: fallback to rustc's sysroot if there's no path to the linker in the target sysroot)
 - #125345 (rustc_codegen_llvm: add support for writing summary bitcode)
 - #125362 (Actually use TAIT instead of emulating it)
 - #125412 (Don't suggest adding the unexpected cfgs to the build-script it-self)
 - #125445 (Migrate `run-make/rustdoc-with-short-out-dir-option` to `rmake.rs`)
 - #125452 (Cleanup check-cfg handling in core and std)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-05-24 03:04:06 +00:00
commit 7601adcc76
32 changed files with 335 additions and 187 deletions

View file

@ -200,7 +200,7 @@ fn produce_final_output_artifacts(
// to get rid of it. // to get rid of it.
for output_type in crate_output.outputs.keys() { for output_type in crate_output.outputs.keys() {
match *output_type { match *output_type {
OutputType::Bitcode => { OutputType::Bitcode | OutputType::ThinLinkBitcode => {
// Cranelift doesn't have bitcode // Cranelift doesn't have bitcode
// user_wants_bitcode = true; // user_wants_bitcode = true;
// // Copy to .bc, but always keep the .0.bc. There is a later // // Copy to .bc, but always keep the .0.bc. There is a later

View file

@ -335,6 +335,10 @@ impl ThinBufferMethods for ThinBuffer {
fn data(&self) -> &[u8] { fn data(&self) -> &[u8] {
unimplemented!(); unimplemented!();
} }
fn thin_link_data(&self) -> &[u8] {
unimplemented!();
}
} }
pub struct GccContext { pub struct GccContext {
@ -414,7 +418,7 @@ impl WriteBackendMethods for GccCodegenBackend {
back::write::codegen(cgcx, dcx, module, config) back::write::codegen(cgcx, dcx, module, config)
} }
fn prepare_thin(_module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) { fn prepare_thin(_module: ModuleCodegen<Self::Module>, _emit_summary: bool) -> (String, Self::ThinBuffer) {
unimplemented!(); unimplemented!();
} }

View file

@ -230,9 +230,12 @@ pub(crate) fn run_thin(
thin_lto(cgcx, &dcx, modules, upstream_modules, cached_modules, &symbols_below_threshold) thin_lto(cgcx, &dcx, modules, upstream_modules, cached_modules, &symbols_below_threshold)
} }
pub(crate) fn prepare_thin(module: ModuleCodegen<ModuleLlvm>) -> (String, ThinBuffer) { pub(crate) fn prepare_thin(
module: ModuleCodegen<ModuleLlvm>,
emit_summary: bool,
) -> (String, ThinBuffer) {
let name = module.name; let name = module.name;
let buffer = ThinBuffer::new(module.module_llvm.llmod(), true); let buffer = ThinBuffer::new(module.module_llvm.llmod(), true, emit_summary);
(name, buffer) (name, buffer)
} }
@ -672,9 +675,9 @@ unsafe impl Send for ThinBuffer {}
unsafe impl Sync for ThinBuffer {} unsafe impl Sync for ThinBuffer {}
impl ThinBuffer { impl ThinBuffer {
pub fn new(m: &llvm::Module, is_thin: bool) -> ThinBuffer { pub fn new(m: &llvm::Module, is_thin: bool, emit_summary: bool) -> ThinBuffer {
unsafe { unsafe {
let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin); let buffer = llvm::LLVMRustThinLTOBufferCreate(m, is_thin, emit_summary);
ThinBuffer(buffer) ThinBuffer(buffer)
} }
} }
@ -688,6 +691,14 @@ impl ThinBufferMethods for ThinBuffer {
slice::from_raw_parts(ptr, len) slice::from_raw_parts(ptr, len)
} }
} }
fn thin_link_data(&self) -> &[u8] {
unsafe {
let ptr = llvm::LLVMRustThinLTOBufferThinLinkDataPtr(self.0) as *const _;
let len = llvm::LLVMRustThinLTOBufferThinLinkDataLen(self.0);
slice::from_raw_parts(ptr, len)
}
}
} }
impl Drop for ThinBuffer { impl Drop for ThinBuffer {

View file

@ -709,13 +709,15 @@ pub(crate) unsafe fn codegen(
// asm from LLVM and use `gcc` to create the object file. // asm from LLVM and use `gcc` to create the object file.
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
let bc_summary_out =
cgcx.output_filenames.temp_path(OutputType::ThinLinkBitcode, module_name);
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
if config.bitcode_needed() { if config.bitcode_needed() {
let _timer = cgcx let _timer = cgcx
.prof .prof
.generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name); .generic_activity_with_arg("LLVM_module_codegen_make_bitcode", &*module.name);
let thin = ThinBuffer::new(llmod, config.emit_thin_lto); let thin = ThinBuffer::new(llmod, config.emit_thin_lto, config.emit_thin_lto_summary);
let data = thin.data(); let data = thin.data();
if let Some(bitcode_filename) = bc_out.file_name() { if let Some(bitcode_filename) = bc_out.file_name() {
@ -726,6 +728,25 @@ pub(crate) unsafe fn codegen(
); );
} }
if config.emit_thin_lto_summary
&& let Some(thin_link_bitcode_filename) = bc_summary_out.file_name()
{
let summary_data = thin.thin_link_data();
cgcx.prof.artifact_size(
"llvm_bitcode_summary",
thin_link_bitcode_filename.to_string_lossy(),
summary_data.len() as u64,
);
let _timer = cgcx.prof.generic_activity_with_arg(
"LLVM_module_codegen_emit_bitcode_summary",
&*module.name,
);
if let Err(err) = fs::write(&bc_summary_out, summary_data) {
dcx.emit_err(WriteBytecode { path: &bc_summary_out, err });
}
}
if config.emit_bc || config.emit_obj == EmitObj::Bitcode { if config.emit_bc || config.emit_obj == EmitObj::Bitcode {
let _timer = cgcx let _timer = cgcx
.prof .prof

View file

@ -237,8 +237,11 @@ impl WriteBackendMethods for LlvmCodegenBackend {
) -> Result<CompiledModule, FatalError> { ) -> Result<CompiledModule, FatalError> {
back::write::codegen(cgcx, dcx, module, config) back::write::codegen(cgcx, dcx, module, config)
} }
fn prepare_thin(module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) { fn prepare_thin(
back::lto::prepare_thin(module) module: ModuleCodegen<Self::Module>,
emit_summary: bool,
) -> (String, Self::ThinBuffer) {
back::lto::prepare_thin(module, emit_summary)
} }
fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) { fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
(module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod())) (module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod()))

View file

@ -2350,10 +2350,16 @@ extern "C" {
#[allow(improper_ctypes)] #[allow(improper_ctypes)]
pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString); pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString);
pub fn LLVMRustThinLTOBufferCreate(M: &Module, is_thin: bool) -> &'static mut ThinLTOBuffer; pub fn LLVMRustThinLTOBufferCreate(
M: &Module,
is_thin: bool,
emit_summary: bool,
) -> &'static mut ThinLTOBuffer;
pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer); pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer);
pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char; pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char;
pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t; pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t;
pub fn LLVMRustThinLTOBufferThinLinkDataPtr(M: &ThinLTOBuffer) -> *const c_char;
pub fn LLVMRustThinLTOBufferThinLinkDataLen(M: &ThinLTOBuffer) -> size_t;
pub fn LLVMRustCreateThinLTOData( pub fn LLVMRustCreateThinLTOData(
Modules: *const ThinLTOModule, Modules: *const ThinLTOModule,
NumModules: c_uint, NumModules: c_uint,

View file

@ -212,6 +212,8 @@ codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, fo
codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected codegen_ssa_select_cpp_build_tool_workload = in the Visual Studio installer, ensure the "C++ build tools" workload is selected
codegen_ssa_self_contained_linker_missing = the self-contained linker was requested, but it wasn't found in the target's sysroot, or in rustc's sysroot
codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time
codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link

View file

@ -3141,13 +3141,21 @@ fn add_lld_args(
let self_contained_linker = self_contained_cli || self_contained_target; let self_contained_linker = self_contained_cli || self_contained_target;
if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() { if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() {
let mut linker_path_exists = false;
for path in sess.get_tools_search_paths(false) { for path in sess.get_tools_search_paths(false) {
let linker_path = path.join("gcc-ld");
linker_path_exists |= linker_path.exists();
cmd.arg({ cmd.arg({
let mut arg = OsString::from("-B"); let mut arg = OsString::from("-B");
arg.push(path.join("gcc-ld")); arg.push(linker_path);
arg arg
}); });
} }
if !linker_path_exists {
// As a sanity check, we emit an error if none of these paths exist: we want
// self-contained linking and have no linker.
sess.dcx().emit_fatal(errors::SelfContainedLinkerMissing);
}
} }
// 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of // 2. Implement the "linker flavor" part of this feature by asking `cc` to use some kind of

View file

@ -108,6 +108,7 @@ pub struct ModuleConfig {
pub emit_asm: bool, pub emit_asm: bool,
pub emit_obj: EmitObj, pub emit_obj: EmitObj,
pub emit_thin_lto: bool, pub emit_thin_lto: bool,
pub emit_thin_lto_summary: bool,
pub bc_cmdline: String, pub bc_cmdline: String,
// Miscellaneous flags. These are mostly copied from command-line // Miscellaneous flags. These are mostly copied from command-line
@ -232,6 +233,10 @@ impl ModuleConfig {
), ),
emit_obj, emit_obj,
emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto, emit_thin_lto: sess.opts.unstable_opts.emit_thin_lto,
emit_thin_lto_summary: if_regular!(
sess.opts.output_types.contains_key(&OutputType::ThinLinkBitcode),
false
),
bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(), bc_cmdline: sess.target.bitcode_llvm_cmdline.to_string(),
verify_llvm_ir: sess.verify_llvm_ir(), verify_llvm_ir: sess.verify_llvm_ir(),
@ -283,6 +288,7 @@ impl ModuleConfig {
pub fn bitcode_needed(&self) -> bool { pub fn bitcode_needed(&self) -> bool {
self.emit_bc self.emit_bc
|| self.emit_thin_lto_summary
|| self.emit_obj == EmitObj::Bitcode || self.emit_obj == EmitObj::Bitcode
|| self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) || self.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full)
} }
@ -630,6 +636,9 @@ fn produce_final_output_artifacts(
// them for making an rlib. // them for making an rlib.
copy_if_one_unit(OutputType::Bitcode, true); copy_if_one_unit(OutputType::Bitcode, true);
} }
OutputType::ThinLinkBitcode => {
copy_if_one_unit(OutputType::ThinLinkBitcode, false);
}
OutputType::LlvmAssembly => { OutputType::LlvmAssembly => {
copy_if_one_unit(OutputType::LlvmAssembly, false); copy_if_one_unit(OutputType::LlvmAssembly, false);
} }
@ -883,7 +892,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
match lto_type { match lto_type {
ComputedLtoType::No => finish_intra_module_work(cgcx, module, module_config), ComputedLtoType::No => finish_intra_module_work(cgcx, module, module_config),
ComputedLtoType::Thin => { ComputedLtoType::Thin => {
let (name, thin_buffer) = B::prepare_thin(module); let (name, thin_buffer) = B::prepare_thin(module, false);
if let Some(path) = bitcode { if let Some(path) = bitcode {
fs::write(&path, thin_buffer.data()).unwrap_or_else(|e| { fs::write(&path, thin_buffer.data()).unwrap_or_else(|e| {
panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e); panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);

View file

@ -413,6 +413,10 @@ pub struct UnableToExeLinker {
#[diag(codegen_ssa_msvc_missing_linker)] #[diag(codegen_ssa_msvc_missing_linker)]
pub struct MsvcMissingLinker; pub struct MsvcMissingLinker;
#[derive(Diagnostic)]
#[diag(codegen_ssa_self_contained_linker_missing)]
pub struct SelfContainedLinkerMissing;
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(codegen_ssa_check_installed_visual_studio)] #[diag(codegen_ssa_check_installed_visual_studio)]
pub struct CheckInstalledVisualStudio; pub struct CheckInstalledVisualStudio;

View file

@ -56,12 +56,16 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
module: ModuleCodegen<Self::Module>, module: ModuleCodegen<Self::Module>,
config: &ModuleConfig, config: &ModuleConfig,
) -> Result<CompiledModule, FatalError>; ) -> Result<CompiledModule, FatalError>;
fn prepare_thin(module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer); fn prepare_thin(
module: ModuleCodegen<Self::Module>,
want_summary: bool,
) -> (String, Self::ThinBuffer);
fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer); fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer);
} }
pub trait ThinBufferMethods: Send + Sync { pub trait ThinBufferMethods: Send + Sync {
fn data(&self) -> &[u8]; fn data(&self) -> &[u8];
fn thin_link_data(&self) -> &[u8];
} }
pub trait ModuleBufferMethods: Send + Sync { pub trait ModuleBufferMethods: Send + Sync {

View file

@ -42,6 +42,22 @@ fn to_check_cfg_arg(name: Symbol, value: Option<Symbol>, quotes: EscapeQuotes) -
} }
} }
fn cargo_help_sub(
sess: &Session,
inst: &impl Fn(EscapeQuotes) -> String,
) -> lints::UnexpectedCfgCargoHelp {
// We don't want to suggest the `build.rs` way to expected cfgs if we are already in a
// `build.rs`. We therefor do a best effort check (looking if the `--crate-name` is
// `build_script_build`) to try to figure out if we are building a Cargo build script
let unescaped = &inst(EscapeQuotes::No);
if matches!(&sess.opts.crate_name, Some(crate_name) if crate_name == "build_script_build") {
lints::UnexpectedCfgCargoHelp::lint_cfg(unescaped)
} else {
lints::UnexpectedCfgCargoHelp::lint_cfg_and_build_rs(unescaped, &inst(EscapeQuotes::Yes))
}
}
pub(super) fn unexpected_cfg_name( pub(super) fn unexpected_cfg_name(
sess: &Session, sess: &Session,
(name, name_span): (Symbol, Span), (name, name_span): (Symbol, Span),
@ -162,14 +178,7 @@ pub(super) fn unexpected_cfg_name(
let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes); let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes);
let invocation_help = if is_from_cargo { let invocation_help = if is_from_cargo {
let sub = if !is_feature_cfg { let sub = if !is_feature_cfg { Some(cargo_help_sub(sess, &inst)) } else { None };
Some(lints::UnexpectedCfgCargoHelp::new(
&inst(EscapeQuotes::No),
&inst(EscapeQuotes::Yes),
))
} else {
None
};
lints::unexpected_cfg_name::InvocationHelp::Cargo { sub } lints::unexpected_cfg_name::InvocationHelp::Cargo { sub }
} else { } else {
lints::unexpected_cfg_name::InvocationHelp::Rustc(lints::UnexpectedCfgRustcHelp::new( lints::unexpected_cfg_name::InvocationHelp::Rustc(lints::UnexpectedCfgRustcHelp::new(
@ -267,10 +276,7 @@ pub(super) fn unexpected_cfg_value(
Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures) Some(lints::unexpected_cfg_value::CargoHelp::DefineFeatures)
} }
} else if !is_cfg_a_well_know_name { } else if !is_cfg_a_well_know_name {
Some(lints::unexpected_cfg_value::CargoHelp::Other(lints::UnexpectedCfgCargoHelp::new( Some(lints::unexpected_cfg_value::CargoHelp::Other(cargo_help_sub(sess, &inst)))
&inst(EscapeQuotes::No),
&inst(EscapeQuotes::Yes),
)))
} else { } else {
None None
}; };

View file

@ -1962,21 +1962,33 @@ pub struct UnitBindingsDiag {
pub struct BuiltinNamedAsmLabel; pub struct BuiltinNamedAsmLabel;
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
#[help(lint_unexpected_cfg_add_cargo_feature)] pub enum UnexpectedCfgCargoHelp {
#[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)] #[help(lint_unexpected_cfg_add_cargo_feature)]
#[help(lint_unexpected_cfg_add_build_rs_println)] #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
pub struct UnexpectedCfgCargoHelp { LintCfg { cargo_toml_lint_cfg: String },
pub build_rs_println: String, #[help(lint_unexpected_cfg_add_cargo_feature)]
pub cargo_toml_lint_cfg: String, #[help(lint_unexpected_cfg_add_cargo_toml_lint_cfg)]
#[help(lint_unexpected_cfg_add_build_rs_println)]
LintCfgAndBuildRs { cargo_toml_lint_cfg: String, build_rs_println: String },
} }
impl UnexpectedCfgCargoHelp { impl UnexpectedCfgCargoHelp {
pub fn new(unescaped: &str, escaped: &str) -> Self { fn cargo_toml_lint_cfg(unescaped: &str) -> String {
Self { format!(
cargo_toml_lint_cfg: format!( "\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}"
"\n [lints.rust]\n unexpected_cfgs = {{ level = \"warn\", check-cfg = ['{unescaped}'] }}", )
), }
build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");",),
pub fn lint_cfg(unescaped: &str) -> Self {
UnexpectedCfgCargoHelp::LintCfg {
cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
}
}
pub fn lint_cfg_and_build_rs(unescaped: &str, escaped: &str) -> Self {
UnexpectedCfgCargoHelp::LintCfgAndBuildRs {
cargo_toml_lint_cfg: Self::cargo_toml_lint_cfg(unescaped),
build_rs_println: format!("println!(\"cargo::rustc-check-cfg={escaped}\");"),
} }
} }
} }

View file

@ -1488,13 +1488,15 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M,
// a ThinLTO summary attached. // a ThinLTO summary attached.
struct LLVMRustThinLTOBuffer { struct LLVMRustThinLTOBuffer {
std::string data; std::string data;
std::string thin_link_data;
}; };
extern "C" LLVMRustThinLTOBuffer* extern "C" LLVMRustThinLTOBuffer*
LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) { LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin, bool emit_summary) {
auto Ret = std::make_unique<LLVMRustThinLTOBuffer>(); auto Ret = std::make_unique<LLVMRustThinLTOBuffer>();
{ {
auto OS = raw_string_ostream(Ret->data); auto OS = raw_string_ostream(Ret->data);
auto ThinLinkOS = raw_string_ostream(Ret->thin_link_data);
{ {
if (is_thin) { if (is_thin) {
PassBuilder PB; PassBuilder PB;
@ -1508,7 +1510,10 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
PB.registerLoopAnalyses(LAM); PB.registerLoopAnalyses(LAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
ModulePassManager MPM; ModulePassManager MPM;
MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr)); // We only pass ThinLinkOS to be filled in if we want the summary,
// because otherwise LLVM does extra work and may double-emit some
// errors or warnings.
MPM.addPass(ThinLTOBitcodeWriterPass(OS, emit_summary ? &ThinLinkOS : nullptr));
MPM.run(*unwrap(M), MAM); MPM.run(*unwrap(M), MAM);
} else { } else {
WriteBitcodeToFile(*unwrap(M), OS); WriteBitcodeToFile(*unwrap(M), OS);
@ -1533,6 +1538,16 @@ LLVMRustThinLTOBufferLen(const LLVMRustThinLTOBuffer *Buffer) {
return Buffer->data.length(); return Buffer->data.length();
} }
extern "C" const void*
LLVMRustThinLTOBufferThinLinkDataPtr(const LLVMRustThinLTOBuffer *Buffer) {
return Buffer->thin_link_data.data();
}
extern "C" size_t
LLVMRustThinLTOBufferThinLinkDataLen(const LLVMRustThinLTOBuffer *Buffer) {
return Buffer->thin_link_data.length();
}
// This is what we used to parse upstream bitcode for actual ThinLTO // This is what we used to parse upstream bitcode for actual ThinLTO
// processing. We'll call this once per module optimized through ThinLTO, and // processing. We'll call this once per module optimized through ThinLTO, and
// it'll be called concurrently on many threads. // it'll be called concurrently on many threads.

View file

@ -465,6 +465,7 @@ impl FromStr for SplitDwarfKind {
#[derive(Encodable, Decodable)] #[derive(Encodable, Decodable)]
pub enum OutputType { pub enum OutputType {
Bitcode, Bitcode,
ThinLinkBitcode,
Assembly, Assembly,
LlvmAssembly, LlvmAssembly,
Mir, Mir,
@ -492,6 +493,7 @@ impl OutputType {
match *self { match *self {
OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true, OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true,
OutputType::Bitcode OutputType::Bitcode
| OutputType::ThinLinkBitcode
| OutputType::Assembly | OutputType::Assembly
| OutputType::LlvmAssembly | OutputType::LlvmAssembly
| OutputType::Mir | OutputType::Mir
@ -502,6 +504,7 @@ impl OutputType {
pub fn shorthand(&self) -> &'static str { pub fn shorthand(&self) -> &'static str {
match *self { match *self {
OutputType::Bitcode => "llvm-bc", OutputType::Bitcode => "llvm-bc",
OutputType::ThinLinkBitcode => "thin-link-bitcode",
OutputType::Assembly => "asm", OutputType::Assembly => "asm",
OutputType::LlvmAssembly => "llvm-ir", OutputType::LlvmAssembly => "llvm-ir",
OutputType::Mir => "mir", OutputType::Mir => "mir",
@ -518,6 +521,7 @@ impl OutputType {
"llvm-ir" => OutputType::LlvmAssembly, "llvm-ir" => OutputType::LlvmAssembly,
"mir" => OutputType::Mir, "mir" => OutputType::Mir,
"llvm-bc" => OutputType::Bitcode, "llvm-bc" => OutputType::Bitcode,
"thin-link-bitcode" => OutputType::ThinLinkBitcode,
"obj" => OutputType::Object, "obj" => OutputType::Object,
"metadata" => OutputType::Metadata, "metadata" => OutputType::Metadata,
"link" => OutputType::Exe, "link" => OutputType::Exe,
@ -528,8 +532,9 @@ impl OutputType {
fn shorthands_display() -> String { fn shorthands_display() -> String {
format!( format!(
"`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`", "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
OutputType::Bitcode.shorthand(), OutputType::Bitcode.shorthand(),
OutputType::ThinLinkBitcode.shorthand(),
OutputType::Assembly.shorthand(), OutputType::Assembly.shorthand(),
OutputType::LlvmAssembly.shorthand(), OutputType::LlvmAssembly.shorthand(),
OutputType::Mir.shorthand(), OutputType::Mir.shorthand(),
@ -543,6 +548,7 @@ impl OutputType {
pub fn extension(&self) -> &'static str { pub fn extension(&self) -> &'static str {
match *self { match *self {
OutputType::Bitcode => "bc", OutputType::Bitcode => "bc",
OutputType::ThinLinkBitcode => "indexing.o",
OutputType::Assembly => "s", OutputType::Assembly => "s",
OutputType::LlvmAssembly => "ll", OutputType::LlvmAssembly => "ll",
OutputType::Mir => "mir", OutputType::Mir => "mir",
@ -559,9 +565,11 @@ impl OutputType {
| OutputType::LlvmAssembly | OutputType::LlvmAssembly
| OutputType::Mir | OutputType::Mir
| OutputType::DepInfo => true, | OutputType::DepInfo => true,
OutputType::Bitcode | OutputType::Object | OutputType::Metadata | OutputType::Exe => { OutputType::Bitcode
false | OutputType::ThinLinkBitcode
} | OutputType::Object
| OutputType::Metadata
| OutputType::Exe => false,
} }
} }
} }
@ -644,6 +652,7 @@ impl OutputTypes {
pub fn should_codegen(&self) -> bool { pub fn should_codegen(&self) -> bool {
self.0.keys().any(|k| match *k { self.0.keys().any(|k| match *k {
OutputType::Bitcode OutputType::Bitcode
| OutputType::ThinLinkBitcode
| OutputType::Assembly | OutputType::Assembly
| OutputType::LlvmAssembly | OutputType::LlvmAssembly
| OutputType::Mir | OutputType::Mir
@ -657,6 +666,7 @@ impl OutputTypes {
pub fn should_link(&self) -> bool { pub fn should_link(&self) -> bool {
self.0.keys().any(|k| match *k { self.0.keys().any(|k| match *k {
OutputType::Bitcode OutputType::Bitcode
| OutputType::ThinLinkBitcode
| OutputType::Assembly | OutputType::Assembly
| OutputType::LlvmAssembly | OutputType::LlvmAssembly
| OutputType::Mir | OutputType::Mir
@ -1769,6 +1779,12 @@ fn parse_output_types(
display = OutputType::shorthands_display(), display = OutputType::shorthands_display(),
)) ))
}); });
if output_type == OutputType::ThinLinkBitcode && !unstable_opts.unstable_options {
early_dcx.early_fatal(format!(
"{} requested but -Zunstable-options not specified",
OutputType::ThinLinkBitcode.shorthand()
));
}
output_types.insert(output_type, path); output_types.insert(output_type, path);
} }
} }

View file

@ -51,6 +51,14 @@ pub fn make_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")]) PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("lib")])
} }
/// Returns a path to the target's `bin` folder within its `rustlib` path in the sysroot. This is
/// where binaries are usually installed, e.g. the self-contained linkers, lld-wrappers, LLVM tools,
/// etc.
pub fn make_target_bin_path(sysroot: &Path, target_triple: &str) -> PathBuf {
let rustlib_path = rustc_target::target_rustlib_path(sysroot, target_triple);
PathBuf::from_iter([sysroot, Path::new(&rustlib_path), Path::new("bin")])
}
#[cfg(unix)] #[cfg(unix)]
fn current_dll_path() -> Result<PathBuf, String> { fn current_dll_path() -> Result<PathBuf, String> {
use std::ffi::{CStr, OsStr}; use std::ffi::{CStr, OsStr};

View file

@ -449,15 +449,24 @@ impl Session {
) )
} }
/// Returns a list of directories where target-specific tool binaries are located. /// Returns a list of directories where target-specific tool binaries are located. Some fallback
/// directories are also returned, for example if `--sysroot` is used but tools are missing
/// (#125246): we also add the bin directories to the sysroot where rustc is located.
pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> { pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
let rustlib_path = rustc_target::target_rustlib_path(&self.sysroot, config::host_triple()); let bin_path = filesearch::make_target_bin_path(&self.sysroot, config::host_triple());
let p = PathBuf::from_iter([ let fallback_sysroot_paths = filesearch::sysroot_candidates()
Path::new(&self.sysroot), .into_iter()
Path::new(&rustlib_path), .map(|sysroot| filesearch::make_target_bin_path(&sysroot, config::host_triple()));
Path::new("bin"), let search_paths = std::iter::once(bin_path).chain(fallback_sysroot_paths);
]);
if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p] } if self_contained {
// The self-contained tools are expected to be e.g. in `bin/self-contained` in the
// sysroot's `rustlib` path, so we add such a subfolder to the bin path, and the
// fallback paths.
search_paths.flat_map(|path| [path.clone(), path.join("self-contained")]).collect()
} else {
search_paths.collect()
}
} }
pub fn init_incr_comp_session(&self, session_dir: PathBuf, lock_file: flock::Lock) { pub fn init_incr_comp_session(&self, session_dir: PathBuf, lock_file: flock::Lock) {

View file

@ -46,6 +46,8 @@ check-cfg = [
'cfg(bootstrap)', 'cfg(bootstrap)',
'cfg(no_fp_fmt_parse)', 'cfg(no_fp_fmt_parse)',
'cfg(stdarch_intel_sde)', 'cfg(stdarch_intel_sde)',
# This matches `EXTRA_CHECK_CFGS` in `src/bootstrap/src/lib.rs`. # core use #[path] imports to portable-simd `core_simd` crate
# and to stdarch `core_arch` crate which messes-up with Cargo list
# of declared features, we therefor expect any feature cfg
'cfg(feature, values(any()))', 'cfg(feature, values(any()))',
] ]

View file

@ -80,47 +80,6 @@ macro_rules! forward_ref_op_assign {
} }
} }
/// Create a zero-size type similar to a closure type, but named.
macro_rules! impl_fn_for_zst {
($(
$( #[$attr: meta] )*
struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
|$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
$body: block;
)+) => {
$(
$( #[$attr] )*
struct $Name;
impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
#[inline]
extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
$body
}
}
impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
#[inline]
extern "rust-call" fn call_mut(
&mut self,
($( $arg, )*): ($( $ArgTy, )*)
) -> $ReturnTy {
Fn::call(&*self, ($( $arg, )*))
}
}
impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
type Output = $ReturnTy;
#[inline]
extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
Fn::call(&self, ($( $arg, )*))
}
}
)+
}
}
/// A macro for defining `#[cfg]` if-else statements. /// A macro for defining `#[cfg]` if-else statements.
/// ///
/// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade /// `cfg_if` is similar to the `if/elif` C preprocessor macro by allowing definition of a cascade

View file

@ -255,6 +255,7 @@
#![feature(trait_alias)] #![feature(trait_alias)]
#![feature(transparent_unions)] #![feature(transparent_unions)]
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(type_alias_impl_trait)]
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(unsized_fn_params)] #![feature(unsized_fn_params)]
#![feature(with_negative_coherence)] #![feature(with_negative_coherence)]

View file

@ -108,7 +108,7 @@ impl [u8] {
without modifying the original"] without modifying the original"]
#[stable(feature = "inherent_ascii_escape", since = "1.60.0")] #[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
pub fn escape_ascii(&self) -> EscapeAscii<'_> { pub fn escape_ascii(&self) -> EscapeAscii<'_> {
EscapeAscii { inner: self.iter().flat_map(EscapeByte) } EscapeAscii { inner: self.iter().flat_map(|byte| byte.escape_ascii()) }
} }
/// Returns a byte slice with leading ASCII whitespace bytes removed. /// Returns a byte slice with leading ASCII whitespace bytes removed.
@ -190,12 +190,7 @@ impl [u8] {
} }
} }
impl_fn_for_zst! { type EscapeByte = impl (Fn(&u8) -> ascii::EscapeDefault) + Copy;
#[derive(Clone)]
struct EscapeByte impl Fn = |byte: &u8| -> ascii::EscapeDefault {
ascii::escape_default(*byte)
};
}
/// An iterator over the escaped version of a byte slice. /// An iterator over the escaped version of a byte slice.
/// ///

View file

@ -1274,8 +1274,10 @@ pub struct SplitWhitespace<'a> {
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SplitAsciiWhitespace<'a> { pub struct SplitAsciiWhitespace<'a> {
pub(super) inner: pub(super) inner: Map<
Map<Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty>, UnsafeBytesToStr>, Filter<SliceSplit<'a, u8, IsAsciiWhitespace>, BytesIsNotEmpty<'a>>,
UnsafeBytesToStr<'a>,
>,
} }
/// An iterator over the substrings of a string, /// An iterator over the substrings of a string,

View file

@ -983,7 +983,7 @@ impl str {
#[cfg_attr(not(test), rustc_diagnostic_item = "str_split_whitespace")] #[cfg_attr(not(test), rustc_diagnostic_item = "str_split_whitespace")]
#[inline] #[inline]
pub fn split_whitespace(&self) -> SplitWhitespace<'_> { pub fn split_whitespace(&self) -> SplitWhitespace<'_> {
SplitWhitespace { inner: self.split(IsWhitespace).filter(IsNotEmpty) } SplitWhitespace { inner: self.split(char::is_whitespace).filter(|s| !s.is_empty()) }
} }
/// Splits a string slice by ASCII whitespace. /// Splits a string slice by ASCII whitespace.
@ -1032,8 +1032,13 @@ impl str {
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")] #[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
#[inline] #[inline]
pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> { pub fn split_ascii_whitespace(&self) -> SplitAsciiWhitespace<'_> {
let inner = let inner = self
self.as_bytes().split(IsAsciiWhitespace).filter(BytesIsNotEmpty).map(UnsafeBytesToStr); .as_bytes()
.split(u8::is_ascii_whitespace)
.filter(|s| !s.is_empty())
// SAFETY: the byte slice came from a string and was only split
// along character boundaries, so the resulting slices are strings.
.map(|bytes| unsafe { from_utf8_unchecked(bytes) });
SplitAsciiWhitespace { inner } SplitAsciiWhitespace { inner }
} }
@ -1085,7 +1090,11 @@ impl str {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]
pub fn lines(&self) -> Lines<'_> { pub fn lines(&self) -> Lines<'_> {
Lines(self.split_inclusive('\n').map(LinesMap)) Lines(self.split_inclusive('\n').map(|line| {
let Some(line) = line.strip_suffix('\n') else { return line };
let Some(line) = line.strip_suffix('\r') else { return line };
line
}))
} }
/// An iterator over the lines of a string. /// An iterator over the lines of a string.
@ -2636,14 +2645,19 @@ impl str {
#[stable(feature = "str_escape", since = "1.34.0")] #[stable(feature = "str_escape", since = "1.34.0")]
pub fn escape_debug(&self) -> EscapeDebug<'_> { pub fn escape_debug(&self) -> EscapeDebug<'_> {
let mut chars = self.chars(); let mut chars = self.chars();
EscapeDebug { let first = chars
inner: chars .next()
.next() .map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL))
.map(|first| first.escape_debug_ext(EscapeDebugExtArgs::ESCAPE_ALL)) .into_iter()
.into_iter() .flatten();
.flatten() let inner = first.chain(chars.flat_map(|c| {
.chain(chars.flat_map(CharEscapeDebugContinue)), c.escape_debug_ext(EscapeDebugExtArgs {
} escape_grapheme_extended: false,
escape_single_quote: true,
escape_double_quote: true,
})
}));
EscapeDebug { inner }
} }
/// Return an iterator that escapes each char in `self` with [`char::escape_default`]. /// Return an iterator that escapes each char in `self` with [`char::escape_default`].
@ -2681,7 +2695,7 @@ impl str {
without modifying the original"] without modifying the original"]
#[stable(feature = "str_escape", since = "1.34.0")] #[stable(feature = "str_escape", since = "1.34.0")]
pub fn escape_default(&self) -> EscapeDefault<'_> { pub fn escape_default(&self) -> EscapeDefault<'_> {
EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) } EscapeDefault { inner: self.chars().flat_map(char::escape_default) }
} }
/// Return an iterator that escapes each char in `self` with [`char::escape_unicode`]. /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
@ -2719,7 +2733,7 @@ impl str {
without modifying the original"] without modifying the original"]
#[stable(feature = "str_escape", since = "1.34.0")] #[stable(feature = "str_escape", since = "1.34.0")]
pub fn escape_unicode(&self) -> EscapeUnicode<'_> { pub fn escape_unicode(&self) -> EscapeUnicode<'_> {
EscapeUnicode { inner: self.chars().flat_map(CharEscapeUnicode) } EscapeUnicode { inner: self.chars().flat_map(char::escape_unicode) }
} }
} }
@ -2750,59 +2764,15 @@ impl Default for &mut str {
} }
} }
impl_fn_for_zst! { type LinesMap = impl (Fn(&str) -> &str) + Copy;
/// A nameable, cloneable fn type type CharEscapeDebugContinue = impl (FnMut(char) -> char::EscapeDebug) + Copy;
#[derive(Clone)] type CharEscapeUnicode = impl (Fn(char) -> char::EscapeUnicode) + Copy;
struct LinesMap impl<'a> Fn = |line: &'a str| -> &'a str { type CharEscapeDefault = impl (Fn(char) -> char::EscapeDefault) + Copy;
let Some(line) = line.strip_suffix('\n') else { return line }; type IsWhitespace = impl (Fn(char) -> bool) + Copy;
let Some(line) = line.strip_suffix('\r') else { return line }; type IsAsciiWhitespace = impl (Fn(&u8) -> bool) + Copy;
line type IsNotEmpty = impl (Fn(&&str) -> bool) + Copy;
}; type BytesIsNotEmpty<'a> = impl (FnMut(&&'a [u8]) -> bool) + Copy;
type UnsafeBytesToStr<'a> = impl (FnMut(&'a [u8]) -> &'a str) + Copy;
#[derive(Clone)]
struct CharEscapeDebugContinue impl Fn = |c: char| -> char::EscapeDebug {
c.escape_debug_ext(EscapeDebugExtArgs {
escape_grapheme_extended: false,
escape_single_quote: true,
escape_double_quote: true
})
};
#[derive(Clone)]
struct CharEscapeUnicode impl Fn = |c: char| -> char::EscapeUnicode {
c.escape_unicode()
};
#[derive(Clone)]
struct CharEscapeDefault impl Fn = |c: char| -> char::EscapeDefault {
c.escape_default()
};
#[derive(Clone)]
struct IsWhitespace impl Fn = |c: char| -> bool {
c.is_whitespace()
};
#[derive(Clone)]
struct IsAsciiWhitespace impl Fn = |byte: &u8| -> bool {
byte.is_ascii_whitespace()
};
#[derive(Clone)]
struct IsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b str| -> bool {
!s.is_empty()
};
#[derive(Clone)]
struct BytesIsNotEmpty impl<'a, 'b> Fn = |s: &'a &'b [u8]| -> bool {
!s.is_empty()
};
#[derive(Clone)]
struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str {
// SAFETY: not safe
unsafe { from_utf8_unchecked(bytes) }
};
}
// This is required to make `impl From<&str> for Box<dyn Error>` and `impl<E> From<E> for Box<dyn Error>` not overlap. // This is required to make `impl From<&str> for Box<dyn Error>` and `impl<E> From<E> for Box<dyn Error>` not overlap.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]

View file

@ -100,10 +100,14 @@ test = true
[lints.rust.unexpected_cfgs] [lints.rust.unexpected_cfgs]
level = "warn" level = "warn"
# x.py uses beta cargo, so `check-cfg` entries do not yet take effect
# for rust-lang/rust. But for users of `-Zbuild-std` it does.
# The unused warning is waiting for rust-lang/cargo#13925 to reach beta.
check-cfg = [ check-cfg = [
'cfg(bootstrap)', 'cfg(bootstrap)',
'cfg(backtrace_in_libstd)',
'cfg(netbsd10)',
'cfg(target_arch, values("xtensa"))', 'cfg(target_arch, values("xtensa"))',
'cfg(feature, values("std", "as_crate"))', # std use #[path] imports to portable-simd `std_float` crate
# and to the `backtrace` crate which messes-up with Cargo list
# of declared features, we therefor expect any feature cfg
'cfg(feature, values(any()))',
] ]

View file

@ -7,9 +7,13 @@ fn main() {
let target_vendor = let target_vendor =
env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set"); env::var("CARGO_CFG_TARGET_VENDOR").expect("CARGO_CFG_TARGET_VENDOR was not set");
let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set"); let target_env = env::var("CARGO_CFG_TARGET_ENV").expect("CARGO_CFG_TARGET_ENV was not set");
println!("cargo:rustc-check-cfg=cfg(netbsd10)");
if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() { if target_os == "netbsd" && env::var("RUSTC_STD_NETBSD10").is_ok() {
println!("cargo:rustc-cfg=netbsd10"); println!("cargo:rustc-cfg=netbsd10");
} }
println!("cargo:rustc-check-cfg=cfg(restricted_std)");
if target_os == "linux" if target_os == "linux"
|| target_os == "android" || target_os == "android"
|| target_os == "netbsd" || target_os == "netbsd"
@ -59,8 +63,11 @@ fn main() {
// - arch=avr // - arch=avr
// - JSON targets // - JSON targets
// - Any new targets that have not been explicitly added above. // - Any new targets that have not been explicitly added above.
println!("cargo:rustc-cfg=feature=\"restricted-std\""); println!("cargo:rustc-cfg=restricted_std");
} }
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
println!("cargo:rustc-check-cfg=cfg(backtrace_in_libstd)");
println!("cargo:rustc-cfg=backtrace_in_libstd"); println!("cargo:rustc-cfg=backtrace_in_libstd");
println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
} }

View file

@ -213,9 +213,9 @@
//! [array]: prim@array //! [array]: prim@array
//! [slice]: prim@slice //! [slice]: prim@slice
#![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))] #![cfg_attr(not(restricted_std), stable(feature = "rust1", since = "1.0.0"))]
#![cfg_attr( #![cfg_attr(
feature = "restricted-std", restricted_std,
unstable( unstable(
feature = "restricted_std", feature = "restricted_std",
issue = "none", issue = "none",

View file

@ -92,8 +92,6 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
(Some(Mode::Std), "no_global_oom_handling", None), (Some(Mode::Std), "no_global_oom_handling", None),
(Some(Mode::Std), "no_rc", None), (Some(Mode::Std), "no_rc", None),
(Some(Mode::Std), "no_sync", None), (Some(Mode::Std), "no_sync", None),
(Some(Mode::Std), "netbsd10", None),
(Some(Mode::Std), "backtrace_in_libstd", None),
/* Extra values not defined in the built-in targets yet, but used in std */ /* Extra values not defined in the built-in targets yet, but used in std */
(Some(Mode::Std), "target_env", Some(&["libnx", "p2"])), (Some(Mode::Std), "target_env", Some(&["libnx", "p2"])),
(Some(Mode::Std), "target_os", Some(&["visionos"])), (Some(Mode::Std), "target_os", Some(&["visionos"])),

View file

@ -229,7 +229,6 @@ run-make/rustc-macro-dep-files/Makefile
run-make/rustdoc-io-error/Makefile run-make/rustdoc-io-error/Makefile
run-make/rustdoc-verify-output-files/Makefile run-make/rustdoc-verify-output-files/Makefile
run-make/rustdoc-with-output-option/Makefile run-make/rustdoc-with-output-option/Makefile
run-make/rustdoc-with-short-out-dir-option/Makefile
run-make/sanitizer-cdylib-link/Makefile run-make/sanitizer-cdylib-link/Makefile
run-make/sanitizer-dylib-link/Makefile run-make/sanitizer-dylib-link/Makefile
run-make/sanitizer-staticlib-link/Makefile run-make/sanitizer-staticlib-link/Makefile

View file

@ -1,8 +0,0 @@
include ../tools.mk
OUTPUT_DIR := "$(TMPDIR)/rustdoc"
all:
$(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib -o $(OUTPUT_DIR)
$(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs

View file

@ -0,0 +1,16 @@
use run_make_support::{htmldocck, rustdoc, tmp_dir};
fn main() {
let out_dir = tmp_dir().join("rustdoc");
rustdoc()
.input("src/lib.rs")
.crate_name("foobar")
.crate_type("lib")
// This is intentionally using `-o` option flag and not the `output()` method.
.arg("-o")
.arg(&out_dir)
.run();
assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success());
}

View file

@ -0,0 +1,22 @@
// This test checks that when we are building a build script provided
// by Cargo we only suggest expecting the unexpected cfgs in the Cargo.toml.
//
//@ check-pass
//@ no-auto-check-cfg
//@ rustc-env:CARGO_CRATE_NAME=build_script_build
//@ compile-flags:--crate-name=build_script_build
//@ compile-flags:--check-cfg=cfg(has_bar)
#[cfg(has_foo)]
//~^ WARNING unexpected `cfg` condition name
fn foo() {}
#[cfg(has_foo = "yes")]
//~^ WARNING unexpected `cfg` condition name
fn foo() {}
#[cfg(has_bar = "yes")]
//~^ WARNING unexpected `cfg` condition value
fn has_bar() {}
fn main() {}

View file

@ -0,0 +1,43 @@
warning: unexpected `cfg` condition name: `has_foo`
--> $DIR/cargo-build-script.rs:10:7
|
LL | #[cfg(has_foo)]
| ^^^^^^^
|
= help: expected names are: `clippy`, `debug_assertions`, `doc`, `doctest`, `has_bar`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `ub_checks`, `unix`, and `windows`
= help: consider using a Cargo feature instead
= help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_foo)'] }
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition name: `has_foo`
--> $DIR/cargo-build-script.rs:14:7
|
LL | #[cfg(has_foo = "yes")]
| ^^^^^^^^^^^^^^^
|
= help: consider using a Cargo feature instead
= help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_foo, values("yes"))'] }
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
warning: unexpected `cfg` condition value: `yes`
--> $DIR/cargo-build-script.rs:18:7
|
LL | #[cfg(has_bar = "yes")]
| ^^^^^^^--------
| |
| help: remove the value
|
= note: no expected value for `has_bar`
= help: consider using a Cargo feature instead
= help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint:
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_bar, values("yes"))'] }
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg/cargo-specifics.html> for more information about checking conditional configuration
warning: 3 warnings emitted