Auto merge of #128783 - GuillaumeGomez:rollup-2kvpg7s, r=GuillaumeGomez

Rollup of 9 pull requests

Successful merges:

 - #128206 (Make create_dll_import_lib easier to implement)
 - #128424 (minor `effects` cleanups)
 - #128527 (More information for fully-qualified suggestion when there are multiple impls)
 - #128656 (Enable msvc for run-make/rust-lld)
 - #128683 (bootstrap: clear miri's ui test deps when rustc changes)
 - #128700 (Migrate `simd-ffi` `run-make` test to rmake)
 - #128753 (Don't arbitrarily choose one upper bound for hidden captured region error message)
 - #128757 (Migrate `pgo-gen-lto` `run-make` test to rmake)
 - #128758 (Specify a minimum supported version for VxWorks)

Failed merges:

 - #128679 (codegen: better centralize function declaration attribute computation)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-08-07 14:10:46 +00:00
commit 8d0066922b
34 changed files with 566 additions and 473 deletions

View file

@ -205,11 +205,11 @@ dependencies = [
[[package]]
name = "ar_archive_writer"
version = "0.3.0"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8412a2d690663356cba5a2532f3ed55d1e8090743bc6695b88403b27df67733"
checksum = "3f2bcb7cf51decfbbfc7ef476e28b0775b13e5eb1190f8b7df145cd53d4f4374"
dependencies = [
"object 0.35.0",
"object 0.36.2",
]
[[package]]
@ -2454,15 +2454,6 @@ dependencies = [
"ruzstd 0.5.0",
]
[[package]]
name = "object"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
dependencies = [
"memchr",
]
[[package]]
name = "object"
version = "0.36.2"

View file

@ -1668,7 +1668,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
}),
)),
)),
// FIXME(effects) we might not need a default.
default: Some(default_ct),
is_host_effect: true,
synthetic: true,

View file

@ -225,21 +225,26 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Find something that we can name
let upper_bound = self.approx_universal_upper_bound(vid);
let upper_bound = &self.definitions[upper_bound];
match upper_bound.external_name {
Some(reg) => reg,
None => {
// Nothing exact found, so we pick the first one that we find.
let scc = self.constraint_sccs.scc(vid);
for vid in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) {
match self.definitions[vid].external_name {
None => {}
Some(region) if region.is_static() => {}
Some(region) => return region,
}
}
region
}
if let Some(universal_region) = self.definitions[upper_bound].external_name {
return universal_region;
}
// Nothing exact found, so we pick a named upper bound, if there's only one.
// If there's >1 universal region, then we probably are dealing w/ an intersection
// region which cannot be mapped back to a universal.
// FIXME: We could probably compute the LUB if there is one.
let scc = self.constraint_sccs.scc(vid);
let upper_bounds: Vec<_> = self
.rev_scc_graph
.as_ref()
.unwrap()
.upper_bounds(scc)
.filter_map(|vid| self.definitions[vid].external_name)
.filter(|r| !r.is_static())
.collect();
match &upper_bounds[..] {
[universal_region] => *universal_region,
_ => region,
}
}
_ => region,

View file

@ -1,4 +1,4 @@
use std::path::{Path, PathBuf};
use std::path::Path;
use rustc_codegen_ssa::back::archive::{
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
@ -16,10 +16,9 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
&self,
sess: &Session,
_lib_name: &str,
_dll_imports: &[rustc_session::cstore::DllImport],
_tmpdir: &Path,
_is_direct_dependency: bool,
) -> PathBuf {
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
_output_path: &Path,
) {
sess.dcx().fatal("raw-dylib is not yet supported by rustc_codegen_cranelift");
}
}

View file

@ -1,9 +1,8 @@
use std::path::{Path, PathBuf};
use std::path::Path;
use rustc_codegen_ssa::back::archive::{
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
};
use rustc_session::cstore::DllImport;
use rustc_session::Session;
pub(crate) struct ArArchiveBuilderBuilder;
@ -17,10 +16,9 @@ impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
&self,
_sess: &Session,
_lib_name: &str,
_dll_imports: &[DllImport],
_tmpdir: &Path,
_is_direct_dependency: bool,
) -> PathBuf {
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
_output_path: &Path,
) {
unimplemented!("creating dll imports is not yet supported");
}
}

View file

@ -1,23 +1,13 @@
codegen_llvm_copy_bitcode = failed to copy bitcode to object file: {$err}
codegen_llvm_dlltool_fail_import_library =
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
{$stdout}
{$stderr}
codegen_llvm_dynamic_linking_with_lto =
cannot prefer dynamic linking when performing LTO
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
codegen_llvm_error_calling_dlltool =
Error calling dlltool '{$dlltool_path}': {$error}
codegen_llvm_error_creating_import_library =
Error creating import library for {$lib_name}: {$error}
codegen_llvm_error_writing_def_file =
Error writing .DEF file: {$error}
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
codegen_llvm_from_llvm_diag = {$message}

View file

@ -1,21 +1,19 @@
//! A helper class for dealing with static archives
use std::ffi::{c_char, c_void, CStr, CString, OsString};
use std::ffi::{c_char, c_void, CStr, CString};
use std::path::{Path, PathBuf};
use std::{env, io, mem, ptr, str};
use std::{io, mem, ptr, str};
use rustc_codegen_ssa::back::archive::{
try_extract_macho_fat_archive, ArArchiveBuilder, ArchiveBuildFailure, ArchiveBuilder,
ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind, DEFAULT_OBJECT_READER,
create_mingw_dll_import_lib, try_extract_macho_fat_archive, ArArchiveBuilder,
ArchiveBuildFailure, ArchiveBuilder, ArchiveBuilderBuilder, ObjectReader, UnknownArchiveKind,
DEFAULT_OBJECT_READER,
};
use rustc_session::cstore::DllImport;
use rustc_codegen_ssa::common;
use rustc_session::Session;
use tracing::trace;
use crate::common;
use crate::errors::{
DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary, ErrorWritingDEFFile,
};
use crate::errors::ErrorCreatingImportLibrary;
use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
@ -121,116 +119,21 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
&self,
sess: &Session,
lib_name: &str,
dll_imports: &[DllImport],
tmpdir: &Path,
is_direct_dependency: bool,
) -> PathBuf {
let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
let output_path = tmpdir.join(format!("{lib_name}{name_suffix}.lib"));
let target = &sess.target;
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(target);
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = dll_imports
.iter()
.map(|import: &DllImport| {
if sess.target.arch == "x86" {
(
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
import.ordinal(),
)
} else {
(import.name.to_string(), import.ordinal())
}
})
.collect();
if mingw_gnu_toolchain {
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
output_path: &Path,
) {
if common::is_mingw_gnu_toolchain(&sess.target) {
// The binutils linker used on -windows-gnu targets cannot read the import
// libraries generated by LLVM: in our attempts, the linker produced an .EXE
// that loaded but crashed with an AV upon calling one of the imported
// functions. Therefore, use binutils to create the import library instead,
// by writing a .DEF file to the temp dir and calling binutils's dlltool.
let def_file_path = tmpdir.join(format!("{lib_name}{name_suffix}.def"));
let def_file_content = format!(
"EXPORTS\n{}",
import_name_and_ordinal_vector
.into_iter()
.map(|(name, ordinal)| {
match ordinal {
Some(n) => format!("{name} @{n} NONAME"),
None => name,
}
})
.collect::<Vec<String>>()
.join("\n")
create_mingw_dll_import_lib(
sess,
lib_name,
import_name_and_ordinal_vector,
output_path,
);
match std::fs::write(&def_file_path, def_file_content) {
Ok(_) => {}
Err(e) => {
sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e });
}
};
// --no-leading-underscore: For the `import_name_type` feature to work, we need to be
// able to control the *exact* spelling of each of the symbols that are being imported:
// hence we don't want `dlltool` adding leading underscores automatically.
let dlltool = find_binutils_dlltool(sess);
let temp_prefix = {
let mut path = PathBuf::from(&output_path);
path.pop();
path.push(lib_name);
path
};
// dlltool target architecture args from:
// https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() {
"x86_64" => ("i386:x86-64", "--64"),
"x86" => ("i386", "--32"),
"aarch64" => ("arm64", "--64"),
"arm" => ("arm", "--32"),
_ => panic!("unsupported arch {}", sess.target.arch),
};
let mut dlltool_cmd = std::process::Command::new(&dlltool);
dlltool_cmd
.arg("-d")
.arg(def_file_path)
.arg("-D")
.arg(lib_name)
.arg("-l")
.arg(&output_path)
.arg("-m")
.arg(dlltool_target_arch)
.arg("-f")
.arg(dlltool_target_bitness)
.arg("--no-leading-underscore")
.arg("--temp-prefix")
.arg(temp_prefix);
match dlltool_cmd.output() {
Err(e) => {
sess.dcx().emit_fatal(ErrorCallingDllTool {
dlltool_path: dlltool.to_string_lossy(),
error: e,
});
}
// dlltool returns '0' on failure, so check for error output instead.
Ok(output) if !output.stderr.is_empty() => {
sess.dcx().emit_fatal(DlltoolFailImportLibrary {
dlltool_path: dlltool.to_string_lossy(),
dlltool_args: dlltool_cmd
.get_args()
.map(|arg| arg.to_string_lossy())
.collect::<Vec<_>>()
.join(" "),
stdout: String::from_utf8_lossy(&output.stdout),
stderr: String::from_utf8_lossy(&output.stderr),
})
}
_ => {}
}
} else {
// we've checked for \0 characters in the library name already
let dll_name_z = CString::new(lib_name).unwrap();
@ -242,9 +145,9 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
trace!(" output_path {}", output_path.display());
trace!(
" import names: {}",
dll_imports
import_name_and_ordinal_vector
.iter()
.map(|import| import.name.to_string())
.map(|(name, _ordinal)| name.clone())
.collect::<Vec<_>>()
.join(", "),
);
@ -281,9 +184,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
});
}
};
output_path
}
}
}
@ -457,39 +358,3 @@ impl<'a> LlvmArchiveBuilder<'a> {
fn string_to_io_error(s: String) -> io::Error {
io::Error::new(io::ErrorKind::Other, format!("bad archive: {s}"))
}
fn find_binutils_dlltool(sess: &Session) -> OsString {
assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
if let Some(dlltool_path) = &sess.opts.cg.dlltool {
return dlltool_path.clone().into_os_string();
}
let tool_name: OsString = if sess.host.options.is_like_windows {
// If we're compiling on Windows, always use "dlltool.exe".
"dlltool.exe"
} else {
// On other platforms, use the architecture-specific name.
match sess.target.arch.as_ref() {
"x86_64" => "x86_64-w64-mingw32-dlltool",
"x86" => "i686-w64-mingw32-dlltool",
"aarch64" => "aarch64-w64-mingw32-dlltool",
// For non-standard architectures (e.g., aarch32) fallback to "dlltool".
_ => "dlltool",
}
}
.into();
// NOTE: it's not clear how useful it is to explicitly search PATH.
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
let full_path = dir.join(&tool_name);
if full_path.is_file() {
return full_path.into_os_string();
}
}
// The user didn't specify the location of the dlltool binary, and we weren't able
// to find the appropriate one on the PATH. Just return the name of the tool
// and let the invocation fail with a hopefully useful error message.
tool_name
}

View file

@ -4,13 +4,14 @@
//! and methods are represented as just a fn ptr and not a full
//! closure.
use rustc_codegen_ssa::common;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use tracing::debug;
use crate::context::CodegenCx;
use crate::value::Value;
use crate::{attributes, common, llvm};
use crate::{attributes, llvm};
/// Codegens a reference to a fn/method item, monomorphizing and
/// inlining as it goes.
@ -46,7 +47,7 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
} else {
let instance_def_id = instance.def_id();
let llfn = if tcx.sess.target.arch == "x86"
&& let Some(dllimport) = common::get_dllimport(tcx, instance_def_id, sym)
&& let Some(dllimport) = crate::common::get_dllimport(tcx, instance_def_id, sym)
{
// Fix for https://github.com/rust-lang/rust/issues/104453
// On x86 Windows, LLVM uses 'L' as the prefix for any private

View file

@ -1,7 +1,5 @@
//! Code that is useful in various codegen modules.
use std::fmt::Write;
use libc::{c_char, c_uint};
use rustc_ast::Mutability;
use rustc_codegen_ssa::traits::*;
@ -10,9 +8,8 @@ use rustc_hir::def_id::DefId;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
use rustc_session::cstore::DllImport;
use rustc_target::abi::{self, AddressSpace, HasDataLayout, Pointer};
use rustc_target::spec::Target;
use tracing::debug;
use crate::consts::const_alloc_to_llvm;
@ -379,64 +376,3 @@ pub(crate) fn get_dllimport<'tcx>(
tcx.native_library(id)
.and_then(|lib| lib.dll_imports.iter().find(|di| di.name.as_str() == name))
}
pub(crate) fn is_mingw_gnu_toolchain(target: &Target) -> bool {
target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
}
pub(crate) fn i686_decorated_name(
dll_import: &DllImport,
mingw: bool,
disable_name_mangling: bool,
) -> String {
let name = dll_import.name.as_str();
let (add_prefix, add_suffix) = match dll_import.import_name_type {
Some(PeImportNameType::NoPrefix) => (false, true),
Some(PeImportNameType::Undecorated) => (false, false),
_ => (true, true),
};
// Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
let mut decorated_name = String::with_capacity(name.len() + 6);
if disable_name_mangling {
// LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be disabled.
decorated_name.push('\x01');
}
let prefix = if add_prefix && dll_import.is_fn {
match dll_import.calling_convention {
DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
DllCallingConvention::Stdcall(_) => (!mingw
|| dll_import.import_name_type == Some(PeImportNameType::Decorated))
.then_some('_'),
DllCallingConvention::Fastcall(_) => Some('@'),
}
} else if !dll_import.is_fn && !mingw {
// For static variables, prefix with '_' on MSVC.
Some('_')
} else {
None
};
if let Some(prefix) = prefix {
decorated_name.push(prefix);
}
decorated_name.push_str(name);
if add_suffix && dll_import.is_fn {
match dll_import.calling_convention {
DllCallingConvention::C => {}
DllCallingConvention::Stdcall(arg_list_size)
| DllCallingConvention::Fastcall(arg_list_size) => {
write!(&mut decorated_name, "@{arg_list_size}").unwrap();
}
DllCallingConvention::Vectorcall(arg_list_size) => {
write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
}
}
}
decorated_name
}

View file

@ -1,5 +1,6 @@
use std::ops::Range;
use rustc_codegen_ssa::common;
use rustc_codegen_ssa::traits::*;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@ -18,7 +19,7 @@ use rustc_target::abi::{
};
use tracing::{debug, instrument, trace};
use crate::common::{self, CodegenCx};
use crate::common::CodegenCx;
use crate::errors::{
InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
};
@ -195,7 +196,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
g2
}
} else if cx.tcx.sess.target.arch == "x86"
&& let Some(dllimport) = common::get_dllimport(cx.tcx, def_id, sym)
&& let Some(dllimport) = crate::common::get_dllimport(cx.tcx, def_id, sym)
{
cx.declare_global(
&common::i686_decorated_name(

View file

@ -1,4 +1,3 @@
use std::borrow::Cow;
use std::ffi::CString;
use std::path::Path;
@ -71,28 +70,6 @@ pub(crate) struct InvalidMinimumAlignmentTooLarge {
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
pub(crate) struct SanitizerMemtagRequiresMte;
#[derive(Diagnostic)]
#[diag(codegen_llvm_error_writing_def_file)]
pub(crate) struct ErrorWritingDEFFile {
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_error_calling_dlltool)]
pub(crate) struct ErrorCallingDllTool<'a> {
pub dlltool_path: Cow<'a, str>,
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_dlltool_fail_import_library)]
pub(crate) struct DlltoolFailImportLibrary<'a> {
pub dlltool_path: Cow<'a, str>,
pub dlltool_args: String,
pub stdout: Cow<'a, str>,
pub stderr: Cow<'a, str>,
}
#[derive(Diagnostic)]
#[diag(codegen_llvm_dynamic_linking_with_lto)]
#[note]

View file

@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
# tidy-alphabetical-start
ar_archive_writer = "0.3.0"
ar_archive_writer = "0.3.3"
arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
cc = "1.0.90"

View file

@ -24,8 +24,19 @@ codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$e
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
codegen_ssa_dlltool_fail_import_library =
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
{$stdout}
{$stderr}
codegen_ssa_error_calling_dlltool =
Error calling dlltool '{$dlltool_path}': {$error}
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
codegen_ssa_error_writing_def_file =
Error writing .DEF file: {$error}
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified

View file

@ -1,4 +1,6 @@
use std::env;
use std::error::Error;
use std::ffi::OsString;
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
@ -9,7 +11,6 @@ use object::read::archive::ArchiveFile;
use object::read::macho::FatArch;
use rustc_data_structures::fx::FxIndexSet;
use rustc_data_structures::memmap::Mmap;
use rustc_session::cstore::DllImport;
use rustc_session::Session;
use rustc_span::symbol::Symbol;
use tempfile::Builder as TempFileBuilder;
@ -17,6 +18,7 @@ use tempfile::Builder as TempFileBuilder;
use super::metadata::search_for_section;
// Re-exporting for rustc_codegen_llvm::back::archive
pub use crate::errors::{ArchiveBuildFailure, ExtractBundledLibsError, UnknownArchiveKind};
use crate::errors::{DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorWritingDEFFile};
pub trait ArchiveBuilderBuilder {
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a>;
@ -30,10 +32,9 @@ pub trait ArchiveBuilderBuilder {
&self,
sess: &Session,
lib_name: &str,
dll_imports: &[DllImport],
tmpdir: &Path,
is_direct_dependency: bool,
) -> PathBuf;
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
output_path: &Path,
);
fn extract_bundled_libs<'a>(
&'a self,
@ -72,6 +73,130 @@ pub trait ArchiveBuilderBuilder {
}
}
pub fn create_mingw_dll_import_lib(
sess: &Session,
lib_name: &str,
import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
output_path: &Path,
) {
let def_file_path = output_path.with_extension("def");
let def_file_content = format!(
"EXPORTS\n{}",
import_name_and_ordinal_vector
.into_iter()
.map(|(name, ordinal)| {
match ordinal {
Some(n) => format!("{name} @{n} NONAME"),
None => name,
}
})
.collect::<Vec<String>>()
.join("\n")
);
match std::fs::write(&def_file_path, def_file_content) {
Ok(_) => {}
Err(e) => {
sess.dcx().emit_fatal(ErrorWritingDEFFile { error: e });
}
};
// --no-leading-underscore: For the `import_name_type` feature to work, we need to be
// able to control the *exact* spelling of each of the symbols that are being imported:
// hence we don't want `dlltool` adding leading underscores automatically.
let dlltool = find_binutils_dlltool(sess);
let temp_prefix = {
let mut path = PathBuf::from(&output_path);
path.pop();
path.push(lib_name);
path
};
// dlltool target architecture args from:
// https://github.com/llvm/llvm-project-release-prs/blob/llvmorg-15.0.6/llvm/lib/ToolDrivers/llvm-dlltool/DlltoolDriver.cpp#L69
let (dlltool_target_arch, dlltool_target_bitness) = match sess.target.arch.as_ref() {
"x86_64" => ("i386:x86-64", "--64"),
"x86" => ("i386", "--32"),
"aarch64" => ("arm64", "--64"),
"arm" => ("arm", "--32"),
_ => panic!("unsupported arch {}", sess.target.arch),
};
let mut dlltool_cmd = std::process::Command::new(&dlltool);
dlltool_cmd
.arg("-d")
.arg(def_file_path)
.arg("-D")
.arg(lib_name)
.arg("-l")
.arg(&output_path)
.arg("-m")
.arg(dlltool_target_arch)
.arg("-f")
.arg(dlltool_target_bitness)
.arg("--no-leading-underscore")
.arg("--temp-prefix")
.arg(temp_prefix);
match dlltool_cmd.output() {
Err(e) => {
sess.dcx().emit_fatal(ErrorCallingDllTool {
dlltool_path: dlltool.to_string_lossy(),
error: e,
});
}
// dlltool returns '0' on failure, so check for error output instead.
Ok(output) if !output.stderr.is_empty() => {
sess.dcx().emit_fatal(DlltoolFailImportLibrary {
dlltool_path: dlltool.to_string_lossy(),
dlltool_args: dlltool_cmd
.get_args()
.map(|arg| arg.to_string_lossy())
.collect::<Vec<_>>()
.join(" "),
stdout: String::from_utf8_lossy(&output.stdout),
stderr: String::from_utf8_lossy(&output.stderr),
})
}
_ => {}
}
}
fn find_binutils_dlltool(sess: &Session) -> OsString {
assert!(sess.target.options.is_like_windows && !sess.target.options.is_like_msvc);
if let Some(dlltool_path) = &sess.opts.cg.dlltool {
return dlltool_path.clone().into_os_string();
}
let tool_name: OsString = if sess.host.options.is_like_windows {
// If we're compiling on Windows, always use "dlltool.exe".
"dlltool.exe"
} else {
// On other platforms, use the architecture-specific name.
match sess.target.arch.as_ref() {
"x86_64" => "x86_64-w64-mingw32-dlltool",
"x86" => "i686-w64-mingw32-dlltool",
"aarch64" => "aarch64-w64-mingw32-dlltool",
// For non-standard architectures (e.g., aarch32) fallback to "dlltool".
_ => "dlltool",
}
}
.into();
// NOTE: it's not clear how useful it is to explicitly search PATH.
for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
let full_path = dir.join(&tool_name);
if full_path.is_file() {
return full_path.into_os_string();
}
}
// The user didn't specify the location of the dlltool binary, and we weren't able
// to find the appropriate one on the PATH. Just return the name of the tool
// and let the invocation fail with a hopefully useful error message.
tool_name
}
pub trait ArchiveBuilder {
fn add_file(&mut self, path: &Path);

View file

@ -51,7 +51,8 @@ use super::linker::{self, Linker};
use super::metadata::{create_wrapper_file, MetadataPosition};
use super::rpath::{self, RPathConfig};
use crate::{
errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib,
common, errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo,
NativeLib,
};
pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
@ -390,17 +391,13 @@ fn link_rlib<'a>(
}
}
for (raw_dylib_name, raw_dylib_imports) in
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
{
let output_path = archive_builder_builder.create_dll_import_lib(
sess,
&raw_dylib_name,
&raw_dylib_imports,
tmpdir.as_ref(),
true,
);
for output_path in create_dll_import_libs(
sess,
archive_builder_builder,
codegen_results.crate_info.used_libraries.iter(),
tmpdir.as_ref(),
true,
)? {
ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
});
@ -488,6 +485,47 @@ fn collate_raw_dylibs<'a>(
.collect())
}
fn create_dll_import_libs<'a>(
sess: &Session,
archive_builder_builder: &dyn ArchiveBuilderBuilder,
used_libraries: impl IntoIterator<Item = &'a NativeLib>,
tmpdir: &Path,
is_direct_dependency: bool,
) -> Result<Vec<PathBuf>, ErrorGuaranteed> {
Ok(collate_raw_dylibs(sess, used_libraries)?
.into_iter()
.map(|(raw_dylib_name, raw_dylib_imports)| {
let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" };
let output_path = tmpdir.join(format!("{raw_dylib_name}{name_suffix}.lib"));
let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(&sess.target);
let import_name_and_ordinal_vector: Vec<(String, Option<u16>)> = raw_dylib_imports
.iter()
.map(|import: &DllImport| {
if sess.target.arch == "x86" {
(
common::i686_decorated_name(import, mingw_gnu_toolchain, false),
import.ordinal(),
)
} else {
(import.name.to_string(), import.ordinal())
}
})
.collect();
archive_builder_builder.create_dll_import_lib(
sess,
&raw_dylib_name,
import_name_and_ordinal_vector,
&output_path,
);
output_path
})
.collect())
}
/// Create a static archive.
///
/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
@ -2305,16 +2343,14 @@ fn linker_with_args(
);
// Link with the import library generated for any raw-dylib functions.
for (raw_dylib_name, raw_dylib_imports) in
collate_raw_dylibs(sess, codegen_results.crate_info.used_libraries.iter())?
{
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
sess,
&raw_dylib_name,
&raw_dylib_imports,
tmpdir,
true,
));
for output_path in create_dll_import_libs(
sess,
archive_builder_builder,
codegen_results.crate_info.used_libraries.iter(),
tmpdir,
true,
)? {
cmd.add_object(&output_path);
}
// As with add_upstream_native_libraries, we need to add the upstream raw-dylib symbols in case
// they are used within inlined functions or instantiated generic functions. We do this *after*
@ -2339,16 +2375,14 @@ fn linker_with_args(
.flatten()
.collect::<Vec<_>>();
native_libraries_from_nonstatics.sort_unstable_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
for (raw_dylib_name, raw_dylib_imports) in
collate_raw_dylibs(sess, native_libraries_from_nonstatics)?
{
cmd.add_object(&archive_builder_builder.create_dll_import_lib(
sess,
&raw_dylib_name,
&raw_dylib_imports,
tmpdir,
false,
));
for output_path in create_dll_import_libs(
sess,
archive_builder_builder,
native_libraries_from_nonstatics,
tmpdir,
false,
)? {
cmd.add_object(&output_path);
}
// Library linking above uses some global state for things like `-Bstatic`/`-Bdynamic` to make

View file

@ -4,7 +4,9 @@ use rustc_hir::LangItem;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Instance, TyCtxt};
use rustc_middle::{bug, mir, span_bug};
use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
use rustc_span::Span;
use rustc_target::spec::Target;
use crate::traits::*;
@ -176,3 +178,66 @@ pub fn asm_const_to_str<'tcx>(
_ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
}
}
pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
}
pub fn i686_decorated_name(
dll_import: &DllImport,
mingw: bool,
disable_name_mangling: bool,
) -> String {
let name = dll_import.name.as_str();
let (add_prefix, add_suffix) = match dll_import.import_name_type {
Some(PeImportNameType::NoPrefix) => (false, true),
Some(PeImportNameType::Undecorated) => (false, false),
_ => (true, true),
};
// Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
let mut decorated_name = String::with_capacity(name.len() + 6);
if disable_name_mangling {
// LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be disabled.
decorated_name.push('\x01');
}
let prefix = if add_prefix && dll_import.is_fn {
match dll_import.calling_convention {
DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
DllCallingConvention::Stdcall(_) => (!mingw
|| dll_import.import_name_type == Some(PeImportNameType::Decorated))
.then_some('_'),
DllCallingConvention::Fastcall(_) => Some('@'),
}
} else if !dll_import.is_fn && !mingw {
// For static variables, prefix with '_' on MSVC.
Some('_')
} else {
None
};
if let Some(prefix) = prefix {
decorated_name.push(prefix);
}
decorated_name.push_str(name);
if add_suffix && dll_import.is_fn {
use std::fmt::Write;
match dll_import.calling_convention {
DllCallingConvention::C => {}
DllCallingConvention::Stdcall(arg_list_size)
| DllCallingConvention::Fastcall(arg_list_size) => {
write!(&mut decorated_name, "@{arg_list_size}").unwrap();
}
DllCallingConvention::Vectorcall(arg_list_size) => {
write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
}
}
}
decorated_name
}

View file

@ -1026,6 +1026,28 @@ pub struct FailedToGetLayout<'tcx> {
pub err: LayoutError<'tcx>,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_dlltool_fail_import_library)]
pub(crate) struct DlltoolFailImportLibrary<'a> {
pub dlltool_path: Cow<'a, str>,
pub dlltool_args: String,
pub stdout: Cow<'a, str>,
pub stderr: Cow<'a, str>,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_error_writing_def_file)]
pub(crate) struct ErrorWritingDEFFile {
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_error_calling_dlltool)]
pub(crate) struct ErrorCallingDllTool<'a> {
pub dlltool_path: Cow<'a, str>,
pub error: std::io::Error,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_error_creating_remark_dir)]
pub struct ErrorCreatingRemarkDir {

View file

@ -253,32 +253,6 @@ pub fn lower_generic_args<'tcx: 'a, 'a>(
match (args_iter.peek(), params.peek()) {
(Some(&arg), Some(&param)) => {
match (arg, &param.kind, arg_count.explicit_late_bound) {
(
GenericArg::Const(hir::ConstArg {
is_desugared_from_effects: true,
..
}),
GenericParamDefKind::Const { is_host_effect: false, .. }
| GenericParamDefKind::Type { .. }
| GenericParamDefKind::Lifetime,
_,
) => {
// FIXME(effects): this should be removed
// SPECIAL CASE FOR DESUGARED EFFECT PARAMS
// This comes from the following example:
//
// ```
// #[const_trait]
// pub trait PartialEq<Rhs: ?Sized = Self> {}
// impl const PartialEq for () {}
// ```
//
// Since this is a const impl, we need to insert a host arg at the end of
// `PartialEq`'s generics, but this errors since `Rhs` isn't specified.
// To work around this, we infer all arguments until we reach the host param.
args.push(ctx.inferred_kind(&args, param, infer_args));
params.next();
}
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
| (
GenericArg::Type(_) | GenericArg::Infer(_),

View file

@ -388,39 +388,67 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
trait_impls.non_blanket_impls().values().flatten().count();
// If there is only one implementation of the trait, suggest using it.
// Otherwise, use a placeholder comment for the implementation.
let (message, self_type) = if non_blanket_impl_count == 1 {
let (message, self_types) = if non_blanket_impl_count == 1 {
(
"use the fully-qualified path to the only available \
implementation",
format!(
vec![format!(
"{}",
self.tcx.type_of(impl_def_id).instantiate_identity()
),
)],
)
} else if non_blanket_impl_count < 20 {
(
"use a fully-qualified path to one of the available \
implementations",
trait_impls
.non_blanket_impls()
.values()
.flatten()
.map(|id| {
format!(
"{}",
self.tcx.type_of(id).instantiate_identity()
)
})
.collect::<Vec<String>>(),
)
} else {
(
"use a fully-qualified path to a specific available \
implementation",
"/* self type */".to_string(),
vec!["/* self type */".to_string()],
)
};
let mut suggestions =
vec![(path.span.shrink_to_lo(), format!("<{self_type} as "))];
if let Some(generic_arg) = trait_path_segment.args {
let between_span =
trait_path_segment.ident.span.between(generic_arg.span_ext);
// get rid of :: between Trait and <type>
// must be '::' between them, otherwise the parser won't accept the code
suggestions.push((between_span, "".to_string()));
suggestions
.push((generic_arg.span_ext.shrink_to_hi(), ">".to_string()));
} else {
suggestions.push((
trait_path_segment.ident.span.shrink_to_hi(),
">".to_string(),
));
}
err.multipart_suggestion(
let suggestions: Vec<_> = self_types
.into_iter()
.map(|self_type| {
let mut suggestions = vec![(
path.span.shrink_to_lo(),
format!("<{self_type} as "),
)];
if let Some(generic_arg) = trait_path_segment.args {
let between_span = trait_path_segment
.ident
.span
.between(generic_arg.span_ext);
// get rid of :: between Trait and <type>
// must be '::' between them, otherwise the parser won't accept the code
suggestions.push((between_span, "".to_string()));
suggestions.push((
generic_arg.span_ext.shrink_to_hi(),
">".to_string(),
));
} else {
suggestions.push((
trait_path_segment.ident.span.shrink_to_hi(),
">".to_string(),
));
}
suggestions
})
.collect();
err.multipart_suggestions(
message,
suggestions,
Applicability::MaybeIncorrect,

View file

@ -520,6 +520,14 @@ impl Step for Miri {
builder.ensure(compile::Std::new(target_compiler, host));
let host_sysroot = builder.sysroot(target_compiler);
// Miri has its own "target dir" for ui test dependencies. Make sure it gets cleared
// properly when rustc changes. Similar to `Builder::cargo`, we skip this in dry runs to
// make sure the relevant compiler has been set up properly.
if !builder.config.dry_run() {
let ui_test_dep_dir = builder.stage_out(host_compiler, Mode::ToolStd).join("miri_ui");
builder.clear_if_dirty(&ui_test_dep_dir, &builder.rustc(host_compiler));
}
// Run `cargo test`.
// This is with the Miri crate, so it uses the host compiler.
let mut cargo = tool::prepare_tool_cargo(

View file

@ -20,6 +20,12 @@ Target triplets available:
## Requirements
### OS version
The minimum supported version is VxWorks 7.
## Building
Rust for each target can be cross-compiled with its specific target vsb configuration. Std support is added but not yet fully tested.
## Building the target

View file

@ -17,12 +17,10 @@ run-make/min-global-align/Makefile
run-make/native-link-modifier-bundle/Makefile
run-make/no-alloc-shim/Makefile
run-make/pdb-buildinfo-cl-cmd/Makefile
run-make/pgo-gen-lto/Makefile
run-make/pgo-indirect-call-promotion/Makefile
run-make/remap-path-prefix-dwarf/Makefile
run-make/reproducible-build/Makefile
run-make/rlib-format-packed-bundled-libs/Makefile
run-make/simd-ffi/Makefile
run-make/split-debuginfo/Makefile
run-make/staticlib-dylib-linkage/Makefile
run-make/symbol-mangling-hashed/Makefile

View file

@ -1,11 +0,0 @@
# needs-profiler-support
# ignore-cross-compile
include ../tools.mk
COMPILE_FLAGS=-Copt-level=3 -Clto=fat -Cprofile-generate="$(TMPDIR)"
all:
$(RUSTC) $(COMPILE_FLAGS) test.rs
$(call RUN,test) || exit 1
[ -e "$(TMPDIR)"/default_*.profraw ] || (echo "No .profraw file"; exit 1)

View file

@ -0,0 +1,22 @@
// A simple smoke test: when rustc compiles with profiling enabled, a profraw file
// should be generated.
// See https://github.com/rust-lang/rust/pull/48346
//@ needs-profiler-support
// Reason: this exercises LTO profiling
//@ ignore-cross-compile
// Reason: the compiled binary is executed
use run_make_support::{cwd, has_extension, has_prefix, run, rustc, shallow_find_files};
fn main() {
rustc().opt_level("3").arg("-Clto=fat").profile_generate(cwd()).input("test.rs").run();
run("test");
assert_eq!(
shallow_find_files(cwd(), |path| {
has_prefix(path, "default_") && has_extension(path, "profraw")
})
.len(),
1
);
}

View file

@ -2,15 +2,17 @@
// see https://github.com/rust-lang/compiler-team/issues/510 for more info
//@ needs-rust-lld
//@ ignore-msvc
//@ ignore-s390x lld does not yet support s390x as target
use std::process::Output;
use run_make_support::regex::Regex;
use run_make_support::rustc;
use run_make_support::{is_msvc, rustc};
fn main() {
// lld-link is used if msvc, otherwise a gnu-compatible lld is used.
let linker_version_flag = if is_msvc() { "--version" } else { "-Wl,-v" };
// Opt-in to lld and the self-contained linker, to link with rust-lld. We'll check that by
// asking the linker to display its version number with a link-arg.
let output = rustc()
@ -18,7 +20,7 @@ fn main() {
.arg("-Zlinker-features=+lld")
.arg("-Clink-self-contained=+linker")
.arg("-Zunstable-options")
.link_arg("-Wl,-v")
.link_arg(linker_version_flag)
.input("main.rs")
.run();
assert!(
@ -27,10 +29,10 @@ fn main() {
output.stderr_utf8()
);
// It should not be used when we explictly opt-out of lld.
// It should not be used when we explicitly opt-out of lld.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.link_arg("-Wl,-v")
.link_arg(linker_version_flag)
.arg("-Zlinker-features=-lld")
.input("main.rs")
.run();
@ -44,7 +46,7 @@ fn main() {
// times to rustc.
let output = rustc()
.env("RUSTC_LOG", "rustc_codegen_ssa::back::link=info")
.link_arg("-Wl,-v")
.link_arg(linker_version_flag)
.arg("-Clink-self-contained=+linker")
.arg("-Zunstable-options")
.arg("-Zlinker-features=-lld")

View file

@ -1,47 +0,0 @@
include ../tools.mk
TARGETS =
ifeq ($(filter arm,$(LLVM_COMPONENTS)),arm)
# construct a fairly exhaustive list of platforms that we
# support. These ones don't follow a pattern
TARGETS += arm-linux-androideabi arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabi
endif
ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86)
X86_ARCHS = i686 x86_64
else
X86_ARCHS =
endif
# these ones do, each OS lists the architectures it supports
LINUX=$(filter aarch64 mips,$(LLVM_COMPONENTS)) $(X86_ARCHS)
ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips)
LINUX += mipsel
endif
WINDOWS=$(X86_ARCHS)
# fails with: failed to get iphonesimulator SDK path: no such file or directory
#IOS=i386 aarch64 armv7
DARWIN=$(X86_ARCHS)
$(foreach arch,$(LINUX),$(eval TARGETS += $(arch)-unknown-linux-gnu))
$(foreach arch,$(WINDOWS),$(eval TARGETS += $(arch)-pc-windows-gnu))
#$(foreach arch,$(IOS),$(eval TARGETS += $(arch)-apple-ios))
$(foreach arch,$(DARWIN),$(eval TARGETS += $(arch)-apple-darwin))
all: $(TARGETS)
define MK_TARGETS
# compile the rust file to the given target, but only to asm and IR
# form, to avoid having to have an appropriate linker.
#
# we need some features because the integer SIMD instructions are not
# enabled by-default for i686 and ARM; these features will be invalid
# on some platforms, but LLVM just prints a warning so that's fine for
# now.
$(1): simd.rs
$$(RUSTC) --target=$(1) --emit=llvm-ir,asm simd.rs \
-C target-feature='+neon,+sse2' -C extra-filename=-$(1)
endef
$(foreach targetxxx,$(TARGETS),$(eval $(call MK_TARGETS,$(targetxxx))))

View file

@ -0,0 +1,63 @@
// Using SIMD types in a program with foreign-function interfaces used to result in an ICE
// (internal compiler error). Since this was fixed in #21233, it should be checked that
// compilation of SIMD and FFI together should be successful on all the most common
// architectures.
// Note that this test does not check linking or binary execution.
// See https://github.com/rust-lang/rust/pull/21233
use run_make_support::{llvm_components_contain, rustc};
fn main() {
let mut targets = Vec::new();
// arm-specific targets.
if llvm_components_contain("arm") {
targets.append(&mut vec![
"arm-linux-androideabi".to_owned(),
"arm-unknown-linux-gnueabihf".to_owned(),
"arm-unknown-linux-gnueabi".to_owned(),
]);
}
let mut x86_archs = Vec::new();
if llvm_components_contain("x86") {
x86_archs.append(&mut vec!["i686", "x86_64"]);
}
// Linux has all x86 targets, plus aarch64 and mips.
let mut extra_targets = x86_archs.clone();
if llvm_components_contain("aarch64") {
extra_targets.push("aarch64");
}
if llvm_components_contain("mips") {
extra_targets.append(&mut vec!["mips", "mipsel"]);
}
for target in extra_targets {
let linux = format!("{target}-unknown-linux-gnu");
targets.push(linux);
}
// Windows and Darwin (OSX) only receive x86 targets.
let extra_targets = x86_archs.clone();
for target in extra_targets {
let windows = format!("{target}-pc-windows-gnu");
let darwin = format!("{target}-apple-darwin");
targets.push(windows);
targets.push(darwin);
}
for target in targets {
// compile the rust file to the given target, but only to asm and IR
// form, to avoid having to have an appropriate linker.
//
// we need some features because the integer SIMD instructions are not
// enabled by-default for i686 and ARM; these features will be invalid
// on some platforms, but LLVM just prints a warning so that's fine for
// now.
rustc()
.target(&target)
.emit("llvm-ir,asm")
.input("simd.rs")
.arg("-Ctarget-feature=+neon,+sse")
.arg(&format!("-Cextra-filename=-{target}"))
.run();
}
}

View file

@ -7,10 +7,12 @@ LL | fn create() -> u32;
LL | let cont: u32 = Coroutine::create();
| ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
help: use a fully-qualified path to a specific available implementation
help: use a fully-qualified path to one of the available implementations
|
LL | let cont: u32 = </* self type */ as Coroutine>::create();
| +++++++++++++++++++ +
LL | let cont: u32 = <Impl as Coroutine>::create();
| ++++++++ +
LL | let cont: u32 = <AnotherImpl as Coroutine>::create();
| +++++++++++++++ +
error[E0283]: type annotations needed
--> $DIR/E0283.rs:35:24

View file

@ -63,10 +63,12 @@ LL | fn my_fn();
LL | MyTrait2::my_fn();
| ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
|
help: use a fully-qualified path to a specific available implementation
help: use a fully-qualified path to one of the available implementations
|
LL | </* self type */ as MyTrait2>::my_fn();
| +++++++++++++++++++ +
LL | <Impl1 as MyTrait2>::my_fn();
| +++++++++ +
LL | <Impl2 as MyTrait2>::my_fn();
| +++++++++ +
error: aborting due to 5 previous errors

View file

@ -0,0 +1,29 @@
#![feature(precise_capturing)]
use std::future::Future;
use std::pin::Pin;
trait MyTrait {
fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32>;
}
trait ErasedMyTrait {
fn foo<'life0, 'life1, 'dynosaur>(&'life0 self, x: &'life1 i32)
-> Pin<Box<dyn Future<Output = i32> + 'dynosaur>>
where
'life0: 'dynosaur,
'life1: 'dynosaur;
}
struct DynMyTrait<T: ErasedMyTrait> {
ptr: T,
}
impl<T: ErasedMyTrait> MyTrait for DynMyTrait<T> {
fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
self.ptr.foo(x)
//~^ ERROR hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
}
}
fn main() {}

View file

@ -0,0 +1,13 @@
error[E0700]: hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
--> $DIR/cannot-capture-intersection.rs:24:9
|
LL | fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
| ------------------------- opaque type defined here
LL | self.ptr.foo(x)
| ^^^^^^^^^^^^^^^
|
= note: hidden type `Pin<Box<dyn Future<Output = i32>>>` captures lifetime `'_`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0700`.

View file

@ -2,17 +2,12 @@ error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does n
--> $DIR/ordinary-bounds-unrelated.rs:28:33
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
| -- ------------------ opaque type defined here
| |
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
| ------------------ opaque type defined here
...
LL | if condition() { a } else { b }
| ^
|
help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
| ++++
= note: hidden type `Ordinary<'_>` captures lifetime `'_`
error: aborting due to 1 previous error

View file

@ -2,17 +2,12 @@ error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does n
--> $DIR/ordinary-bounds-unsuited.rs:31:33
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
| -- ------------------ opaque type defined here
| |
| hidden type `Ordinary<'b>` captures the lifetime `'b` as defined here
| ------------------ opaque type defined here
...
LL | if condition() { a } else { b }
| ^
|
help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
| ++++
= note: hidden type `Ordinary<'_>` captures lifetime `'_`
error: aborting due to 1 previous error

View file

@ -2,18 +2,13 @@ error[E0700]: hidden type for `impl Iterator<Item = i32>` captures lifetime that
--> $DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:7:5
|
LL | fn bar(src: &crate::Foo) -> impl Iterator<Item = i32> {
| ---------- ------------------------- opaque type defined here
| |
| hidden type `FilterMap<std::slice::Iter<'static, i32>, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures the anonymous lifetime defined here
| ------------------------- opaque type defined here
LL | / [0].into_iter()
LL | |
LL | | .filter_map(|_| foo(src))
| |_________________________________^
|
help: to declare that `impl Iterator<Item = i32>` captures `'_`, you can introduce a named lifetime parameter `'a`
|
LL | fn bar<'a>(src: &'a crate::Foo<'a>) -> impl Iterator<Item = i32> + 'a {
| ++++ ++ ++++ ++++
= note: hidden type `FilterMap<std::slice::Iter<'static, i32>, {closure@$DIR/explicit-lifetime-suggestion-in-proper-span-issue-121267.rs:9:21: 9:24}>` captures lifetime `'_`
error: aborting due to 1 previous error