mirror of
https://github.com/rust-lang/rust
synced 2024-07-21 10:26:41 +00:00
Auto merge of #122389 - workingjubilee:rollup-vbdniap, r=workingjubilee
Rollup of 12 pull requests Successful merges: - #121754 ([bootstrap] Move the `split-debuginfo` setting to the per-target section) - #121953 (Add tests for the generated assembly of mask related simd instructions.) - #122081 (validate `builder::PATH_REMAP`) - #122245 (Detect truncated DepGraph files) - #122354 (bootstrap: Don't eagerly format verbose messages) - #122355 (rustdoc: fix up old test) - #122363 (tests: Add ui/attributes/unix_sigpipe/unix_sigpipe-str-list.rs) - #122366 (Fix stack overflow with recursive associated types) - #122377 (Fix discriminant_kind copy paste from the pointee trait case) - #122378 (Properly rebuild rustbooks) - #122380 (Fix typo in lib.rs of proc_macro) - #122381 (llvm-wrapper: adapt for LLVM API changes) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
6b1e5d9db3
|
@ -1112,11 +1112,16 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
|
|||
LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
|
||||
uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
|
||||
LLVMBasicBlockRef InsertAtEnd) {
|
||||
return wrap(Builder->insertDeclare(
|
||||
auto Result = Builder->insertDeclare(
|
||||
unwrap(V), unwrap<DILocalVariable>(VarInfo),
|
||||
Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
|
||||
DebugLoc(cast<MDNode>(unwrap(DL))),
|
||||
unwrap(InsertAtEnd)));
|
||||
unwrap(InsertAtEnd));
|
||||
#if LLVM_VERSION_GE(19, 0)
|
||||
return wrap(Result.get<llvm::Instruction *>());
|
||||
#else
|
||||
return wrap(Result);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
|
||||
|
|
|
@ -179,13 +179,15 @@ impl SerializedDepGraph {
|
|||
pub fn decode<D: Deps>(d: &mut MemDecoder<'_>) -> SerializedDepGraph {
|
||||
// The last 16 bytes are the node count and edge count.
|
||||
debug!("position: {:?}", d.position());
|
||||
let (node_count, edge_count) =
|
||||
d.with_position(d.len() - 2 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| {
|
||||
let (node_count, edge_count, graph_size) =
|
||||
d.with_position(d.len() - 3 * IntEncodedWithFixedSize::ENCODED_SIZE, |d| {
|
||||
debug!("position: {:?}", d.position());
|
||||
let node_count = IntEncodedWithFixedSize::decode(d).0 as usize;
|
||||
let edge_count = IntEncodedWithFixedSize::decode(d).0 as usize;
|
||||
(node_count, edge_count)
|
||||
let graph_size = IntEncodedWithFixedSize::decode(d).0 as usize;
|
||||
(node_count, edge_count, graph_size)
|
||||
});
|
||||
assert_eq!(d.len(), graph_size);
|
||||
debug!("position: {:?}", d.position());
|
||||
|
||||
debug!(?node_count, ?edge_count);
|
||||
|
@ -491,6 +493,8 @@ fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
|
|||
debug!("position: {:?}", encoder.position());
|
||||
IntEncodedWithFixedSize(node_count).encode(&mut encoder);
|
||||
IntEncodedWithFixedSize(edge_count).encode(&mut encoder);
|
||||
let graph_size = encoder.position() + IntEncodedWithFixedSize::ENCODED_SIZE;
|
||||
IntEncodedWithFixedSize(graph_size as u64).encode(&mut encoder);
|
||||
debug!("position: {:?}", encoder.position());
|
||||
// Drop the encoder so that nothing is written after the counts.
|
||||
let result = encoder.finish();
|
||||
|
|
|
@ -1061,8 +1061,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
|||
// Integers and floats always have `u8` as their discriminant.
|
||||
| ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
|
||||
|
||||
// type parameters, opaques, and unnormalized projections have pointer
|
||||
// metadata if they're known (e.g. by the param_env) to be sized
|
||||
// type parameters, opaques, and unnormalized projections don't have
|
||||
// a known discriminant and may need to be normalized further or rely
|
||||
// on param env for discriminant projections
|
||||
ty::Param(_)
|
||||
| ty::Alias(..)
|
||||
| ty::Bound(..)
|
||||
|
|
|
@ -240,6 +240,10 @@ fn visit_ty(&mut self, t: Ty<'tcx>) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if !self.seen.insert(assoc.def_id.expect_local()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let impl_args = alias_ty.args.rebase_onto(
|
||||
self.tcx,
|
||||
impl_trait_ref.def_id,
|
||||
|
|
|
@ -543,23 +543,15 @@
|
|||
# FIXME(#61117): Some tests fail when this option is enabled.
|
||||
#debuginfo-level-tests = 0
|
||||
|
||||
# Should rustc be build with split debuginfo? Default is platform dependent.
|
||||
# Valid values are the same as those accepted by `-C split-debuginfo`
|
||||
# (`off`/`unpacked`/`packed`).
|
||||
# Should rustc and the standard library be built with split debuginfo? Default
|
||||
# is platform dependent.
|
||||
#
|
||||
# On Linux, split debuginfo is disabled by default.
|
||||
# This field is deprecated, use `target.<triple>.split-debuginfo` instead.
|
||||
#
|
||||
# On Apple platforms, unpacked split debuginfo is used by default. Unpacked
|
||||
# debuginfo does not run `dsymutil`, which packages debuginfo from disparate
|
||||
# object files into a single `.dSYM` file. `dsymutil` adds time to builds for
|
||||
# no clear benefit, and also makes it more difficult for debuggers to find
|
||||
# debug info. The compiler currently defaults to running `dsymutil` to preserve
|
||||
# its historical default, but when compiling the compiler itself, we skip it by
|
||||
# default since we know it's safe to do so in that case.
|
||||
# The value specified here is only used when targeting the `build.build` triple,
|
||||
# and is overridden by `target.<triple>.split-debuginfo` if specified.
|
||||
#
|
||||
# On Windows platforms, packed debuginfo is the only supported option,
|
||||
# producing a `.pdb` file.
|
||||
#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked }
|
||||
#split-debuginfo = see target.<triple>.split-debuginfo
|
||||
|
||||
# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
|
||||
#backtrace = true
|
||||
|
@ -773,6 +765,26 @@
|
|||
# Setting this will override the `use-lld` option for Rust code when targeting MSVC.
|
||||
#linker = "cc" (path)
|
||||
|
||||
# Should rustc and the standard library be built with split debuginfo? Default
|
||||
# is platform dependent.
|
||||
#
|
||||
# Valid values are the same as those accepted by `-C split-debuginfo`
|
||||
# (`off`/`unpacked`/`packed`).
|
||||
#
|
||||
# On Linux, split debuginfo is disabled by default.
|
||||
#
|
||||
# On Apple platforms, unpacked split debuginfo is used by default. Unpacked
|
||||
# debuginfo does not run `dsymutil`, which packages debuginfo from disparate
|
||||
# object files into a single `.dSYM` file. `dsymutil` adds time to builds for
|
||||
# no clear benefit, and also makes it more difficult for debuggers to find
|
||||
# debug info. The compiler currently defaults to running `dsymutil` to preserve
|
||||
# its historical default, but when compiling the compiler itself, we skip it by
|
||||
# default since we know it's safe to do so in that case.
|
||||
#
|
||||
# On Windows platforms, packed debuginfo is the only supported option,
|
||||
# producing a `.pdb` file.
|
||||
#split-debuginfo = if linux { off } else if windows { packed } else if apple { unpacked }
|
||||
|
||||
# Path to the `llvm-config` binary of the installation of a custom LLVM to link
|
||||
# against. Note that if this is specified we don't compile LLVM at all for this
|
||||
# target.
|
||||
|
|
|
@ -73,7 +73,7 @@ pub fn is_available() -> bool {
|
|||
|
||||
/// The main type provided by this crate, representing an abstract stream of
|
||||
/// tokens, or, more specifically, a sequence of token trees.
|
||||
/// The type provide interfaces for iterating over those token trees and, conversely,
|
||||
/// The type provides interfaces for iterating over those token trees and, conversely,
|
||||
/// collecting a number of token trees into one stream.
|
||||
///
|
||||
/// This is both the input and output of `#[proc_macro]`, `#[proc_macro_attribute]`
|
||||
|
|
|
@ -1536,7 +1536,8 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
|
|||
};
|
||||
let sysroot = sysroot_dir(compiler.stage);
|
||||
|
||||
builder.verbose(&format!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
|
||||
builder
|
||||
.verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
|
||||
let _ = fs::remove_dir_all(&sysroot);
|
||||
t!(fs::create_dir_all(&sysroot));
|
||||
|
||||
|
@ -1606,7 +1607,7 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
|
|||
return true;
|
||||
}
|
||||
if !filtered_files.iter().all(|f| f != path.file_name().unwrap()) {
|
||||
builder.verbose_than(1, &format!("ignoring {}", path.display()));
|
||||
builder.verbose_than(1, || println!("ignoring {}", path.display()));
|
||||
false
|
||||
} else {
|
||||
true
|
||||
|
@ -2085,7 +2086,7 @@ pub fn stream_cargo(
|
|||
cargo.arg(arg);
|
||||
}
|
||||
|
||||
builder.verbose(&format!("running: {cargo:?}"));
|
||||
builder.verbose(|| println!("running: {cargo:?}"));
|
||||
|
||||
if builder.config.dry_run() {
|
||||
return true;
|
||||
|
|
|
@ -2107,7 +2107,7 @@ fn maybe_install_llvm(
|
|||
{
|
||||
let mut cmd = Command::new(llvm_config);
|
||||
cmd.arg("--libfiles");
|
||||
builder.verbose(&format!("running {cmd:?}"));
|
||||
builder.verbose(|| println!("running {cmd:?}"));
|
||||
let files = if builder.config.dry_run() { "".into() } else { output(&mut cmd) };
|
||||
let build_llvm_out = &builder.llvm_out(builder.config.build);
|
||||
let target_llvm_out = &builder.llvm_out(target);
|
||||
|
|
|
@ -145,7 +145,8 @@ fn run(self, builder: &Builder<'_>) {
|
|||
let rustbook = builder.tool_exe(Tool::Rustbook);
|
||||
let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
|
||||
|
||||
if !builder.config.dry_run() && !(up_to_date(&src, &index) || up_to_date(&rustbook, &index))
|
||||
if !builder.config.dry_run()
|
||||
&& (!up_to_date(&src, &index) || !up_to_date(&rustbook, &index))
|
||||
{
|
||||
builder.info(&format!("Rustbook ({target}) - {name}"));
|
||||
let _ = fs::remove_dir_all(&out);
|
||||
|
|
|
@ -551,7 +551,7 @@ pub fn build_miri_sysroot(
|
|||
if builder.config.dry_run() {
|
||||
String::new()
|
||||
} else {
|
||||
builder.verbose(&format!("running: {cargo:?}"));
|
||||
builder.verbose(|| println!("running: {cargo:?}"));
|
||||
let out =
|
||||
cargo.output().expect("We already ran `cargo miri setup` before and that worked");
|
||||
assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code");
|
||||
|
@ -559,7 +559,7 @@ pub fn build_miri_sysroot(
|
|||
let stdout = String::from_utf8(out.stdout)
|
||||
.expect("`cargo miri setup` stdout is not valid UTF-8");
|
||||
let sysroot = stdout.trim_end();
|
||||
builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
|
||||
builder.verbose(|| println!("`cargo miri setup --print-sysroot` said: {sysroot:?}"));
|
||||
sysroot.to_owned()
|
||||
}
|
||||
}
|
||||
|
@ -2326,7 +2326,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
|
|||
}
|
||||
}
|
||||
|
||||
builder.verbose(&format!("doc tests for: {}", markdown.display()));
|
||||
builder.verbose(|| println!("doc tests for: {}", markdown.display()));
|
||||
let mut cmd = builder.rustdoc_cmd(compiler);
|
||||
builder.add_rust_test_threads(&mut cmd);
|
||||
// allow for unstable options such as new editions
|
||||
|
|
|
@ -291,7 +291,7 @@ pub fn assert_single_path(&self) -> &TaskPath {
|
|||
const PATH_REMAP: &[(&str, &[&str])] = &[
|
||||
// config.toml uses `rust-analyzer-proc-macro-srv`, but the
|
||||
// actual path is `proc-macro-srv-cli`
|
||||
("rust-analyzer-proc-macro-srv", &["proc-macro-srv-cli"]),
|
||||
("rust-analyzer-proc-macro-srv", &["src/tools/rust-analyzer/crates/proc-macro-srv-cli"]),
|
||||
// Make `x test tests` function the same as `x t tests/*`
|
||||
(
|
||||
"tests",
|
||||
|
@ -382,10 +382,12 @@ fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
|
|||
}
|
||||
|
||||
if !builder.config.skip.is_empty() && !matches!(builder.config.dry_run, DryRun::SelfCheck) {
|
||||
builder.verbose(&format!(
|
||||
"{:?} not skipped for {:?} -- not in {:?}",
|
||||
pathset, self.name, builder.config.skip
|
||||
));
|
||||
builder.verbose(|| {
|
||||
println!(
|
||||
"{:?} not skipped for {:?} -- not in {:?}",
|
||||
pathset, self.name, builder.config.skip
|
||||
)
|
||||
});
|
||||
}
|
||||
false
|
||||
}
|
||||
|
@ -1093,10 +1095,9 @@ fn run(self, builder: &Builder<'_>) -> PathBuf {
|
|||
// Avoid deleting the rustlib/ directory we just copied
|
||||
// (in `impl Step for Sysroot`).
|
||||
if !builder.download_rustc() {
|
||||
builder.verbose(&format!(
|
||||
"Removing sysroot {} to avoid caching bugs",
|
||||
sysroot.display()
|
||||
));
|
||||
builder.verbose(|| {
|
||||
println!("Removing sysroot {} to avoid caching bugs", sysroot.display())
|
||||
});
|
||||
let _ = fs::remove_dir_all(&sysroot);
|
||||
t!(fs::create_dir_all(&sysroot));
|
||||
}
|
||||
|
@ -1436,7 +1437,7 @@ fn cargo(
|
|||
|
||||
let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
|
||||
if !matches!(self.config.dry_run, DryRun::SelfCheck) {
|
||||
self.verbose_than(0, &format!("using sysroot {sysroot_str}"));
|
||||
self.verbose_than(0, || println!("using sysroot {sysroot_str}"));
|
||||
}
|
||||
|
||||
let mut rustflags = Rustflags::new(target);
|
||||
|
@ -1731,15 +1732,16 @@ fn cargo(
|
|||
},
|
||||
);
|
||||
|
||||
let split_debuginfo = self.config.split_debuginfo(target);
|
||||
let split_debuginfo_is_stable = target.contains("linux")
|
||||
|| target.contains("apple")
|
||||
|| (target.is_msvc() && self.config.rust_split_debuginfo == SplitDebuginfo::Packed)
|
||||
|| (target.is_windows() && self.config.rust_split_debuginfo == SplitDebuginfo::Off);
|
||||
|| (target.is_msvc() && split_debuginfo == SplitDebuginfo::Packed)
|
||||
|| (target.is_windows() && split_debuginfo == SplitDebuginfo::Off);
|
||||
|
||||
if !split_debuginfo_is_stable {
|
||||
rustflags.arg("-Zunstable-options");
|
||||
}
|
||||
match self.config.rust_split_debuginfo {
|
||||
match split_debuginfo {
|
||||
SplitDebuginfo::Packed => rustflags.arg("-Csplit-debuginfo=packed"),
|
||||
SplitDebuginfo::Unpacked => rustflags.arg("-Csplit-debuginfo=unpacked"),
|
||||
SplitDebuginfo::Off => rustflags.arg("-Csplit-debuginfo=off"),
|
||||
|
@ -2102,11 +2104,11 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
|
|||
panic!("{}", out);
|
||||
}
|
||||
if let Some(out) = self.cache.get(&step) {
|
||||
self.verbose_than(1, &format!("{}c {:?}", " ".repeat(stack.len()), step));
|
||||
self.verbose_than(1, || println!("{}c {:?}", " ".repeat(stack.len()), step));
|
||||
|
||||
return out;
|
||||
}
|
||||
self.verbose_than(1, &format!("{}> {:?}", " ".repeat(stack.len()), step));
|
||||
self.verbose_than(1, || println!("{}> {:?}", " ".repeat(stack.len()), step));
|
||||
stack.push(Box::new(step.clone()));
|
||||
}
|
||||
|
||||
|
@ -2144,7 +2146,7 @@ pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
|
|||
let cur_step = stack.pop().expect("step stack empty");
|
||||
assert_eq!(cur_step.downcast_ref(), Some(&step));
|
||||
}
|
||||
self.verbose_than(1, &format!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
|
||||
self.verbose_than(1, || println!("{}< {:?}", " ".repeat(self.stack.borrow().len()), step));
|
||||
self.cache.put(step, out.clone());
|
||||
out
|
||||
}
|
||||
|
|
|
@ -115,6 +115,19 @@ fn test_intersection() {
|
|||
assert_eq!(command_paths, vec![Path::new("library/stdarch")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_path_remap() {
|
||||
let build = Build::new(configure("test", &["A"], &["A"]));
|
||||
|
||||
PATH_REMAP
|
||||
.iter()
|
||||
.flat_map(|(_, paths)| paths.iter())
|
||||
.map(|path| build.src.join(path))
|
||||
.for_each(|path| {
|
||||
assert!(path.exists(), "{} should exist.", path.display());
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_exclude() {
|
||||
let mut config = configure("test", &["A"], &["A"]);
|
||||
|
|
|
@ -256,7 +256,7 @@ pub struct Config {
|
|||
pub rust_debuginfo_level_std: DebuginfoLevel,
|
||||
pub rust_debuginfo_level_tools: DebuginfoLevel,
|
||||
pub rust_debuginfo_level_tests: DebuginfoLevel,
|
||||
pub rust_split_debuginfo: SplitDebuginfo,
|
||||
pub rust_split_debuginfo_for_build_triple: Option<SplitDebuginfo>, // FIXME: Deprecated field. Remove in Q3'24.
|
||||
pub rust_rpath: bool,
|
||||
pub rust_strip: bool,
|
||||
pub rust_frame_pointers: bool,
|
||||
|
@ -574,6 +574,7 @@ pub struct Target {
|
|||
pub ranlib: Option<PathBuf>,
|
||||
pub default_linker: Option<PathBuf>,
|
||||
pub linker: Option<PathBuf>,
|
||||
pub split_debuginfo: Option<SplitDebuginfo>,
|
||||
pub sanitizers: Option<bool>,
|
||||
pub profiler: Option<StringOrBool>,
|
||||
pub rpath: Option<bool>,
|
||||
|
@ -1133,6 +1134,7 @@ struct TomlTarget {
|
|||
ranlib: Option<String> = "ranlib",
|
||||
default_linker: Option<PathBuf> = "default-linker",
|
||||
linker: Option<String> = "linker",
|
||||
split_debuginfo: Option<String> = "split-debuginfo",
|
||||
llvm_config: Option<String> = "llvm-config",
|
||||
llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches",
|
||||
llvm_filecheck: Option<String> = "llvm-filecheck",
|
||||
|
@ -1627,11 +1629,18 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
|
|||
debuginfo_level_tools = debuginfo_level_tools_toml;
|
||||
debuginfo_level_tests = debuginfo_level_tests_toml;
|
||||
|
||||
config.rust_split_debuginfo = split_debuginfo
|
||||
config.rust_split_debuginfo_for_build_triple = split_debuginfo
|
||||
.as_deref()
|
||||
.map(SplitDebuginfo::from_str)
|
||||
.map(|v| v.expect("invalid value for rust.split_debuginfo"))
|
||||
.unwrap_or(SplitDebuginfo::default_for_platform(config.build));
|
||||
.map(|v| v.expect("invalid value for rust.split-debuginfo"));
|
||||
|
||||
if config.rust_split_debuginfo_for_build_triple.is_some() {
|
||||
println!(
|
||||
"WARNING: specifying `rust.split-debuginfo` is deprecated, use `target.{}.split-debuginfo` instead",
|
||||
config.build
|
||||
);
|
||||
}
|
||||
|
||||
optimize = optimize_toml;
|
||||
omit_git_hash = omit_git_hash_toml;
|
||||
config.rust_new_symbol_mangling = new_symbol_mangling;
|
||||
|
@ -1853,10 +1862,11 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
|
|||
if let Some(ref s) = cfg.llvm_filecheck {
|
||||
target.llvm_filecheck = Some(config.src.join(s));
|
||||
}
|
||||
target.llvm_libunwind = cfg
|
||||
.llvm_libunwind
|
||||
.as_ref()
|
||||
.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
|
||||
target.llvm_libunwind = cfg.llvm_libunwind.as_ref().map(|v| {
|
||||
v.parse().unwrap_or_else(|_| {
|
||||
panic!("failed to parse target.{triple}.llvm-libunwind")
|
||||
})
|
||||
});
|
||||
if let Some(s) = cfg.no_std {
|
||||
target.no_std = s;
|
||||
}
|
||||
|
@ -1893,6 +1903,12 @@ fn get_table(option: &str) -> Result<TomlConfig, toml::de::Error> {
|
|||
}).collect());
|
||||
}
|
||||
|
||||
target.split_debuginfo = cfg.split_debuginfo.as_ref().map(|v| {
|
||||
v.parse().unwrap_or_else(|_| {
|
||||
panic!("invalid value for target.{triple}.split-debuginfo")
|
||||
})
|
||||
});
|
||||
|
||||
config.target_config.insert(TargetSelection::from_user(&triple), target);
|
||||
}
|
||||
}
|
||||
|
@ -2043,7 +2059,7 @@ pub(crate) fn try_run(&self, cmd: &mut Command) -> Result<(), ()> {
|
|||
if self.dry_run() {
|
||||
return Ok(());
|
||||
}
|
||||
self.verbose(&format!("running: {cmd:?}"));
|
||||
self.verbose(|| println!("running: {cmd:?}"));
|
||||
build_helper::util::try_run(cmd, self.is_verbose())
|
||||
}
|
||||
|
||||
|
@ -2230,9 +2246,10 @@ pub(crate) fn initial_rustfmt(&self) -> Option<PathBuf> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn verbose(&self, msg: &str) {
|
||||
/// Runs a function if verbosity is greater than 0
|
||||
pub fn verbose(&self, f: impl Fn()) {
|
||||
if self.verbose > 0 {
|
||||
println!("{msg}");
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2291,6 +2308,16 @@ pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn split_debuginfo(&self, target: TargetSelection) -> SplitDebuginfo {
|
||||
self.target_config
|
||||
.get(&target)
|
||||
.and_then(|t| t.split_debuginfo)
|
||||
.or_else(|| {
|
||||
if self.build == target { self.rust_split_debuginfo_for_build_triple } else { None }
|
||||
})
|
||||
.unwrap_or_else(|| SplitDebuginfo::default_for_platform(target))
|
||||
}
|
||||
|
||||
pub fn submodules(&self, rust_info: &GitInfo) -> bool {
|
||||
self.submodules.unwrap_or(rust_info.is_managed_git_subrepository())
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ pub(crate) fn check_run(&self, cmd: &mut Command) -> bool {
|
|||
if self.dry_run() {
|
||||
return true;
|
||||
}
|
||||
self.verbose(&format!("running: {cmd:?}"));
|
||||
self.verbose(|| println!("running: {cmd:?}"));
|
||||
check_run(cmd, self.is_verbose())
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ fn fix_bin_or_dylib(&self, fname: &Path) {
|
|||
}
|
||||
|
||||
fn download_file(&self, url: &str, dest_path: &Path, help_on_error: &str) {
|
||||
self.verbose(&format!("download {url}"));
|
||||
self.verbose(|| println!("download {url}"));
|
||||
// Use a temporary file in case we crash while downloading, to avoid a corrupt download in cache/.
|
||||
let tempfile = self.tempdir().join(dest_path.file_name().unwrap());
|
||||
// While bootstrap itself only supports http and https downloads, downstream forks might
|
||||
|
@ -300,7 +300,9 @@ fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
|
|||
}
|
||||
short_path = t!(short_path.strip_prefix(pattern));
|
||||
let dst_path = dst.join(short_path);
|
||||
self.verbose(&format!("extracting {} to {}", original_path.display(), dst.display()));
|
||||
self.verbose(|| {
|
||||
println!("extracting {} to {}", original_path.display(), dst.display())
|
||||
});
|
||||
if !t!(member.unpack_in(dst)) {
|
||||
panic!("path traversal attack ??");
|
||||
}
|
||||
|
@ -323,7 +325,7 @@ fn unpack(&self, tarball: &Path, dst: &Path, pattern: &str) {
|
|||
pub(crate) fn verify(&self, path: &Path, expected: &str) -> bool {
|
||||
use sha2::Digest;
|
||||
|
||||
self.verbose(&format!("verifying {}", path.display()));
|
||||
self.verbose(|| println!("verifying {}", path.display()));
|
||||
|
||||
if self.dry_run() {
|
||||
return false;
|
||||
|
@ -379,7 +381,7 @@ enum DownloadSource {
|
|||
/// Functions that are only ever called once, but named for clarify and to avoid thousand-line functions.
|
||||
impl Config {
|
||||
pub(crate) fn download_clippy(&self) -> PathBuf {
|
||||
self.verbose("downloading stage0 clippy artifacts");
|
||||
self.verbose(|| println!("downloading stage0 clippy artifacts"));
|
||||
|
||||
let date = &self.stage0_metadata.compiler.date;
|
||||
let version = &self.stage0_metadata.compiler.version;
|
||||
|
@ -469,7 +471,7 @@ fn ci_component_contents(&self, stamp_file: &str) -> Vec<String> {
|
|||
}
|
||||
|
||||
pub(crate) fn download_ci_rustc(&self, commit: &str) {
|
||||
self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})"));
|
||||
self.verbose(|| println!("using downloaded stage2 artifacts from CI (commit {commit})"));
|
||||
|
||||
let version = self.artifact_version_part(commit);
|
||||
// download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
|
||||
|
@ -486,7 +488,7 @@ pub(crate) fn download_ci_rustc(&self, commit: &str) {
|
|||
}
|
||||
|
||||
pub(crate) fn download_beta_toolchain(&self) {
|
||||
self.verbose("downloading stage0 beta artifacts");
|
||||
self.verbose(|| println!("downloading stage0 beta artifacts"));
|
||||
|
||||
let date = &self.stage0_metadata.compiler.date;
|
||||
let version = &self.stage0_metadata.compiler.version;
|
||||
|
@ -625,10 +627,12 @@ fn download_component(
|
|||
self.unpack(&tarball, &bin_root, prefix);
|
||||
return;
|
||||
} else {
|
||||
self.verbose(&format!(
|
||||
"ignoring cached file {} due to failed verification",
|
||||
tarball.display()
|
||||
));
|
||||
self.verbose(|| {
|
||||
println!(
|
||||
"ignoring cached file {} due to failed verification",
|
||||
tarball.display()
|
||||
)
|
||||
});
|
||||
self.remove(&tarball);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -288,7 +288,7 @@ impl Build {
|
|||
}
|
||||
|
||||
forward! {
|
||||
verbose(msg: &str),
|
||||
verbose(f: impl Fn()),
|
||||
is_verbose() -> bool,
|
||||
create(path: &Path, s: &str),
|
||||
remove(f: &Path),
|
||||
|
@ -440,11 +440,11 @@ pub fn new(mut config: Config) -> Build {
|
|||
.unwrap()
|
||||
.trim();
|
||||
if local_release.split('.').take(2).eq(version.split('.').take(2)) {
|
||||
build.verbose(&format!("auto-detected local-rebuild {local_release}"));
|
||||
build.verbose(|| println!("auto-detected local-rebuild {local_release}"));
|
||||
build.local_rebuild = true;
|
||||
}
|
||||
|
||||
build.verbose("finding compilers");
|
||||
build.verbose(|| println!("finding compilers"));
|
||||
utils::cc_detect::find(&build);
|
||||
// When running `setup`, the profile is about to change, so any requirements we have now may
|
||||
// be different on the next invocation. Don't check for them until the next time x.py is
|
||||
|
@ -452,7 +452,7 @@ pub fn new(mut config: Config) -> Build {
|
|||
//
|
||||
// Similarly, for `setup` we don't actually need submodules or cargo metadata.
|
||||
if !matches!(build.config.cmd, Subcommand::Setup { .. }) {
|
||||
build.verbose("running sanity check");
|
||||
build.verbose(|| println!("running sanity check"));
|
||||
crate::core::sanity::check(&mut build);
|
||||
|
||||
// Make sure we update these before gathering metadata so we don't get an error about missing
|
||||
|
@ -464,7 +464,7 @@ pub fn new(mut config: Config) -> Build {
|
|||
// Now, update all existing submodules.
|
||||
build.update_existing_submodules();
|
||||
|
||||
build.verbose("learning about cargo");
|
||||
build.verbose(|| println!("learning about cargo"));
|
||||
crate::core::metadata::build(&mut build);
|
||||
}
|
||||
|
||||
|
@ -693,7 +693,7 @@ fn clear_if_dirty(&self, dir: &Path, input: &Path) -> bool {
|
|||
let stamp = dir.join(".stamp");
|
||||
let mut cleared = false;
|
||||
if mtime(&stamp) < mtime(input) {
|
||||
self.verbose(&format!("Dirty - {}", dir.display()));
|
||||
self.verbose(|| println!("Dirty - {}", dir.display()));
|
||||
let _ = fs::remove_dir_all(dir);
|
||||
cleared = true;
|
||||
} else if stamp.exists() {
|
||||
|
@ -986,7 +986,7 @@ pub(crate) fn run_cmd<'a, C: Into<BootstrapCommand<'a>>>(&self, cmd: C) -> bool
|
|||
}
|
||||
|
||||
let command = cmd.into();
|
||||
self.verbose(&format!("running: {command:?}"));
|
||||
self.verbose(|| println!("running: {command:?}"));
|
||||
|
||||
let (output, print_error) = match command.output_mode {
|
||||
mode @ (OutputMode::PrintAll | OutputMode::PrintOutput) => (
|
||||
|
@ -1044,14 +1044,15 @@ pub(crate) fn run_cmd<'a, C: Into<BootstrapCommand<'a>>>(&self, cmd: C) -> bool
|
|||
}
|
||||
}
|
||||
|
||||
/// Check if verbosity is greater than the `level`
|
||||
pub fn is_verbose_than(&self, level: usize) -> bool {
|
||||
self.verbosity > level
|
||||
}
|
||||
|
||||
/// Prints a message if this build is configured in more verbose mode than `level`.
|
||||
fn verbose_than(&self, level: usize, msg: &str) {
|
||||
/// Runs a function if verbosity is greater than `level`.
|
||||
fn verbose_than(&self, level: usize, f: impl Fn()) {
|
||||
if self.is_verbose_than(level) {
|
||||
println!("{msg}");
|
||||
f()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1654,7 +1655,7 @@ fn copy_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) {
|
|||
if self.config.dry_run() {
|
||||
return;
|
||||
}
|
||||
self.verbose_than(1, &format!("Copy {src:?} to {dst:?}"));
|
||||
self.verbose_than(1, || println!("Copy {src:?} to {dst:?}"));
|
||||
if src == dst {
|
||||
return;
|
||||
}
|
||||
|
@ -1745,7 +1746,7 @@ fn install(&self, src: &Path, dstdir: &Path, perms: u32) {
|
|||
return;
|
||||
}
|
||||
let dst = dstdir.join(src.file_name().unwrap());
|
||||
self.verbose_than(1, &format!("Install {src:?} to {dst:?}"));
|
||||
self.verbose_than(1, || println!("Install {src:?} to {dst:?}"));
|
||||
t!(fs::create_dir_all(dstdir));
|
||||
if !src.exists() {
|
||||
panic!("ERROR: File \"{}\" not found!", src.display());
|
||||
|
|
|
@ -145,15 +145,15 @@ pub fn find_target(build: &Build, target: TargetSelection) {
|
|||
build.cxx.borrow_mut().insert(target, compiler);
|
||||
}
|
||||
|
||||
build.verbose(&format!("CC_{} = {:?}", &target.triple, build.cc(target)));
|
||||
build.verbose(&format!("CFLAGS_{} = {:?}", &target.triple, cflags));
|
||||
build.verbose(|| println!("CC_{} = {:?}", &target.triple, build.cc(target)));
|
||||
build.verbose(|| println!("CFLAGS_{} = {:?}", &target.triple, cflags));
|
||||
if let Ok(cxx) = build.cxx(target) {
|
||||
let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx);
|
||||
build.verbose(&format!("CXX_{} = {:?}", &target.triple, cxx));
|
||||
build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags));
|
||||
build.verbose(|| println!("CXX_{} = {:?}", &target.triple, cxx));
|
||||
build.verbose(|| println!("CXXFLAGS_{} = {:?}", &target.triple, cxxflags));
|
||||
}
|
||||
if let Some(ar) = ar {
|
||||
build.verbose(&format!("AR_{} = {:?}", &target.triple, ar));
|
||||
build.verbose(|| println!("AR_{} = {:?}", &target.triple, ar));
|
||||
build.ar.borrow_mut().insert(target, ar);
|
||||
}
|
||||
|
||||
|
|
|
@ -151,4 +151,9 @@ pub fn find_recent_config_change_ids(current_id: usize) -> Vec<ChangeInfo> {
|
|||
severity: ChangeSeverity::Info,
|
||||
summary: "New option `rust.llvm-bitcode-linker` that will build the llvm-bitcode-linker.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 121754,
|
||||
severity: ChangeSeverity::Warning,
|
||||
summary: "`rust.split-debuginfo` has been moved to `target.<triple>.split-debuginfo` and its default value is determined for each target individually.",
|
||||
},
|
||||
];
|
||||
|
|
|
@ -44,7 +44,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bo
|
|||
fn run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool {
|
||||
cmd.stdout(Stdio::piped());
|
||||
|
||||
builder.verbose(&format!("running: {cmd:?}"));
|
||||
builder.verbose(|| println!("running: {cmd:?}"));
|
||||
|
||||
let mut process = cmd.spawn().unwrap();
|
||||
|
||||
|
|
|
@ -328,7 +328,9 @@ fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> GeneratedTar
|
|||
|
||||
// For `x install` tarball files aren't needed, so we can speed up the process by not producing them.
|
||||
let compression_profile = if self.builder.kind == Kind::Install {
|
||||
self.builder.verbose("Forcing dist.compression-profile = 'no-op' for `x install`.");
|
||||
self.builder.verbose(|| {
|
||||
println!("Forcing dist.compression-profile = 'no-op' for `x install`.")
|
||||
});
|
||||
// "no-op" indicates that the rust-installer won't produce compressed tarball sources.
|
||||
"no-op"
|
||||
} else {
|
||||
|
|
|
@ -694,7 +694,6 @@ pub fn line_directive<'line>(
|
|||
"check-stdout",
|
||||
"check-test-line-numbers-match",
|
||||
"compile-flags",
|
||||
"count",
|
||||
"dont-check-compiler-stderr",
|
||||
"dont-check-compiler-stdout",
|
||||
"dont-check-failure-status",
|
||||
|
|
149
tests/assembly/simd-bitmask.rs
Normal file
149
tests/assembly/simd-bitmask.rs
Normal file
|
@ -0,0 +1,149 @@
|
|||
//@ revisions: x86 x86-avx2 x86-avx512 aarch64
|
||||
//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86] needs-llvm-components: x86
|
||||
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
|
||||
//@ [x86-avx2] needs-llvm-components: x86
|
||||
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
|
||||
//@ [x86-avx512] needs-llvm-components: x86
|
||||
//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
|
||||
//@ [aarch64] needs-llvm-components: aarch64
|
||||
//@ [aarch64] min-llvm-version: 18.0
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type=lib -O
|
||||
|
||||
#![feature(no_core, lang_items, repr_simd, intrinsics)]
|
||||
#![no_core]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m8x16([i8; 16]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m8x64([i8; 64]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m32x4([i32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x2([i64; 2]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x4([i64; 4]);
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn simd_bitmask<V, B>(mask: V) -> B;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: bitmask_m8x16
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn bitmask_m8x16(mask: m8x16) -> u16 {
|
||||
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
|
||||
// Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit
|
||||
// of each byte into the right position.
|
||||
//
|
||||
// x86-NOT: psllw
|
||||
// x86: movmskb eax, xmm0
|
||||
//
|
||||
// x86-avx2-NOT: vpsllw
|
||||
// x86-avx2: vpmovmskb eax, xmm0
|
||||
//
|
||||
// x86-avx512-NOT: vpsllw xmm0
|
||||
// x86-avx512: vpmovmskb eax, xmm0
|
||||
//
|
||||
// aarch64: adrp
|
||||
// aarch64-NEXT: cmlt
|
||||
// aarch64-NEXT: ldr
|
||||
// aarch64-NEXT: and
|
||||
// aarch64-NEXT: ext
|
||||
// aarch64-NEXT: zip1
|
||||
// aarch64-NEXT: addv
|
||||
// aarch64-NEXT: fmov
|
||||
simd_bitmask(mask)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: bitmask_m8x64
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn bitmask_m8x64(mask: m8x64) -> u64 {
|
||||
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
|
||||
// Note that x86 has no byte shift, llvm uses a word shift to move the least significant bit
|
||||
// of each byte into the right position.
|
||||
//
|
||||
// The parameter is a 512 bit vector which in the C abi is only valid for avx512 targets.
|
||||
//
|
||||
// x86-avx512-NOT: vpsllw
|
||||
// x86-avx512: vpmovb2m k0, zmm0
|
||||
// x86-avx512: kmovq rax, k0
|
||||
simd_bitmask(mask)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: bitmask_m32x4
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn bitmask_m32x4(mask: m32x4) -> u8 {
|
||||
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
|
||||
//
|
||||
// x86-NOT: psllq
|
||||
// x86: movmskps eax, xmm0
|
||||
//
|
||||
// x86-avx2-NOT: vpsllq
|
||||
// x86-avx2: vmovmskps eax, xmm0
|
||||
//
|
||||
// x86-avx512-NOT: vpsllq
|
||||
// x86-avx512: vmovmskps eax, xmm0
|
||||
//
|
||||
// aarch64: adrp
|
||||
// aarch64-NEXT: cmlt
|
||||
// aarch64-NEXT: ldr
|
||||
// aarch64-NEXT: and
|
||||
// aarch64-NEXT: addv
|
||||
// aarch64-NEXT: fmov
|
||||
// aarch64-NEXT: and
|
||||
simd_bitmask(mask)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: bitmask_m64x2
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn bitmask_m64x2(mask: m64x2) -> u8 {
|
||||
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
|
||||
//
|
||||
// x86-NOT: psllq
|
||||
// x86: movmskpd eax, xmm0
|
||||
//
|
||||
// x86-avx2-NOT: vpsllq
|
||||
// x86-avx2: vmovmskpd eax, xmm0
|
||||
//
|
||||
// x86-avx512-NOT: vpsllq
|
||||
// x86-avx512: vmovmskpd eax, xmm0
|
||||
//
|
||||
// aarch64: adrp
|
||||
// aarch64-NEXT: cmlt
|
||||
// aarch64-NEXT: ldr
|
||||
// aarch64-NEXT: and
|
||||
// aarch64-NEXT: addp
|
||||
// aarch64-NEXT: fmov
|
||||
// aarch64-NEXT: and
|
||||
simd_bitmask(mask)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: bitmask_m64x4
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn bitmask_m64x4(mask: m64x4) -> u8 {
|
||||
// The simd_bitmask intrinsic already uses the most significant bit, so no shift is necessary.
|
||||
//
|
||||
// The parameter is a 256 bit vector which in the C abi is only valid for avx/avx512 targets.
|
||||
//
|
||||
// x86-avx2-NOT: vpsllq
|
||||
// x86-avx2: vmovmskpd eax, ymm0
|
||||
//
|
||||
// x86-avx512-NOT: vpsllq
|
||||
// x86-avx512: vmovmskpd eax, ymm0
|
||||
simd_bitmask(mask)
|
||||
}
|
44
tests/assembly/simd-intrinsic-gather.rs
Normal file
44
tests/assembly/simd-intrinsic-gather.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
//@ revisions: x86-avx512
|
||||
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
|
||||
//@ [x86-avx512] needs-llvm-components: x86
|
||||
//@ [x86-avx512] min-llvm-version: 18.0
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type=lib -O
|
||||
|
||||
#![feature(no_core, lang_items, repr_simd, intrinsics)]
|
||||
#![no_core]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f64x4([f64; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x4([i64; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct pf64x4([*const f64; 4]);
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn simd_gather<V, M, P>(values: V, mask: M, pointer: P) -> V;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: gather_f64x4
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn gather_f64x4(mask: m64x4, ptrs: pf64x4) -> f64x4 {
|
||||
// FIXME: This should also get checked to generate a gather instruction for avx2.
|
||||
// Currently llvm scalarizes this code, see https://github.com/llvm/llvm-project/issues/59789
|
||||
//
|
||||
// x86-avx512: vpsllq ymm0, ymm0, 63
|
||||
// x86-avx512-NEXT: vpmovq2m k1, ymm0
|
||||
// x86-avx512-NEXT: vpxor xmm0, xmm0, xmm0
|
||||
// x86-avx512-NEXT: vgatherqpd ymm0 {k1}, ymmword ptr [1*ymm1]
|
||||
simd_gather(f64x4([0_f64, 0_f64, 0_f64, 0_f64]), ptrs, mask)
|
||||
}
|
88
tests/assembly/simd-intrinsic-mask-load.rs
Normal file
88
tests/assembly/simd-intrinsic-mask-load.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
//@ revisions: x86-avx2 x86-avx512
|
||||
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
|
||||
//@ [x86-avx2] needs-llvm-components: x86
|
||||
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
|
||||
//@ [x86-avx512] needs-llvm-components: x86
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type=lib -O
|
||||
|
||||
#![feature(no_core, lang_items, repr_simd, intrinsics)]
|
||||
#![no_core]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct i8x16([i8; 16]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m8x16([i8; 16]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f32x8([f32; 8]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m32x8([i32; 8]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f64x4([f64; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x4([i64; 4]);
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: load_i8x16
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn load_i8x16(mask: m8x16, pointer: *const i8) -> i8x16 {
|
||||
// Since avx2 supports no masked loads for bytes, the code tests each individual bit
|
||||
// and jumps to code that inserts individual bytes.
|
||||
// x86-avx2: vpsllw xmm0, xmm0, 7
|
||||
// x86-avx2-NEXT: vpmovmskb eax, xmm0
|
||||
// x86-avx2-NEXT: vpxor xmm0, xmm0
|
||||
// x86-avx2-NEXT: test al, 1
|
||||
// x86-avx2-NEXT: jne
|
||||
// x86-avx2-NEXT: test al, 2
|
||||
// x86-avx2-NEXT: jne
|
||||
// x86-avx2-DAG: movzx [[REG:[a-z]+]], byte ptr [rdi]
|
||||
// x86-avx2-NEXT: vmovd xmm0, [[REG]]
|
||||
// x86-avx2-DAG: vpinsrb xmm0, xmm0, byte ptr [rdi + 1], 1
|
||||
//
|
||||
// x86-avx512: vpsllw xmm0, xmm0, 7
|
||||
// x86-avx512-NEXT: vpmovb2m k1, xmm0
|
||||
// x86-avx512-NEXT: vmovdqu8 xmm0 {k1} {z}, xmmword ptr [rdi]
|
||||
simd_masked_load(mask, pointer, i8x16([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]))
|
||||
}
|
||||
|
||||
// CHECK-LABEL: load_f32x8
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn load_f32x8(mask: m32x8, pointer: *const f32) -> f32x8 {
|
||||
// x86-avx2: vpslld ymm0, ymm0, 31
|
||||
// x86-avx2-NEXT: vmaskmovps ymm0, ymm0, ymmword ptr [rdi]
|
||||
//
|
||||
// x86-avx512: vpslld ymm0, ymm0, 31
|
||||
// x86-avx512-NEXT: vpmovd2m k1, ymm0
|
||||
// x86-avx512-NEXT: vmovups ymm0 {k1} {z}, ymmword ptr [rdi]
|
||||
simd_masked_load(mask, pointer, f32x8([0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32, 0_f32]))
|
||||
}
|
||||
|
||||
// CHECK-LABEL: load_f64x4
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn load_f64x4(mask: m64x4, pointer: *const f64) -> f64x4 {
|
||||
// x86-avx2: vpsllq ymm0, ymm0, 63
|
||||
// x86-avx2-NEXT: vmaskmovpd ymm0, ymm0, ymmword ptr [rdi]
|
||||
//
|
||||
// x86-avx512: vpsllq ymm0, ymm0, 63
|
||||
// x86-avx512-NEXT: vpmovq2m k1, ymm0
|
||||
// x86-avx512-NEXT: vmovupd ymm0 {k1} {z}, ymmword ptr [rdi]
|
||||
simd_masked_load(mask, pointer, f64x4([0_f64, 0_f64, 0_f64, 0_f64]))
|
||||
}
|
60
tests/assembly/simd-intrinsic-mask-reduce.rs
Normal file
60
tests/assembly/simd-intrinsic-mask-reduce.rs
Normal file
|
@ -0,0 +1,60 @@
|
|||
// verify that simd mask reductions do not introduce additional bit shift operations
|
||||
//@ revisions: x86 aarch64
|
||||
//@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86] needs-llvm-components: x86
|
||||
//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
|
||||
//@ [aarch64] needs-llvm-components: aarch64
|
||||
//@ [aarch64] min-llvm-version: 18.0
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type=lib -O
|
||||
|
||||
#![feature(no_core, lang_items, repr_simd, intrinsics)]
|
||||
#![no_core]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct mask8x16([i8; 16]);
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn simd_reduce_all<T>(x: T) -> bool;
|
||||
fn simd_reduce_any<T>(x: T) -> bool;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: mask_reduce_all:
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mask_reduce_all(m: mask8x16) -> bool {
|
||||
// x86: psllw xmm0, 7
|
||||
// x86-NEXT: pmovmskb eax, xmm0
|
||||
// x86-NEXT: {{cmp ax, -1|xor eax, 65535}}
|
||||
// x86-NEXT: sete al
|
||||
//
|
||||
// aarch64: shl v0.16b, v0.16b, #7
|
||||
// aarch64-NEXT: cmlt v0.16b, v0.16b, #0
|
||||
// aarch64-NEXT: uminv b0, v0.16b
|
||||
// aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0
|
||||
// aarch64-NEXT: and w0, [[REG]], #0x1
|
||||
simd_reduce_all(m)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: mask_reduce_any:
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mask_reduce_any(m: mask8x16) -> bool {
|
||||
// x86: psllw xmm0, 7
|
||||
// x86-NEXT: pmovmskb
|
||||
// x86-NEXT: test eax, eax
|
||||
// x86-NEXT: setne al
|
||||
//
|
||||
// aarch64: shl v0.16b, v0.16b, #7
|
||||
// aarch64-NEXT: cmlt v0.16b, v0.16b, #0
|
||||
// aarch64-NEXT: umaxv b0, v0.16b
|
||||
// aarch64-NEXT: fmov [[REG:[a-z0-9]+]], s0
|
||||
// aarch64-NEXT: and w0, [[REG]], #0x1
|
||||
simd_reduce_any(m)
|
||||
}
|
86
tests/assembly/simd-intrinsic-mask-store.rs
Normal file
86
tests/assembly/simd-intrinsic-mask-store.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
//@ revisions: x86-avx2 x86-avx512
|
||||
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
|
||||
//@ [x86-avx2] needs-llvm-components: x86
|
||||
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
|
||||
//@ [x86-avx512] needs-llvm-components: x86
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type=lib -O
|
||||
|
||||
#![feature(no_core, lang_items, repr_simd, intrinsics)]
|
||||
#![no_core]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct i8x16([i8; 16]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m8x16([i8; 16]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f32x8([f32; 8]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m32x8([i32; 8]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f64x4([f64; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x4([i64; 4]);
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: store_i8x16
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn store_i8x16(mask: m8x16, pointer: *mut i8, value: i8x16) {
|
||||
// Since avx2 supports no masked stores for bytes, the code tests each individual bit
|
||||
// and jumps to code that extracts individual bytes to memory.
|
||||
// x86-avx2: vpsllw xmm0, xmm0, 7
|
||||
// x86-avx2-NEXT: vpmovmskb eax, xmm0
|
||||
// x86-avx2-NEXT: test al, 1
|
||||
// x86-avx2-NEXT: jne
|
||||
// x86-avx2-NEXT: test al, 2
|
||||
// x86-avx2-NEXT: jne
|
||||
// x86-avx2-DAG: vpextrb byte ptr [rdi + 1], xmm1, 1
|
||||
// x86-avx2-DAG: vpextrb byte ptr [rdi], xmm1, 0
|
||||
//
|
||||
// x86-avx512: vpsllw xmm0, xmm0, 7
|
||||
// x86-avx512-NEXT: vpmovb2m k1, xmm0
|
||||
// x86-avx512-NEXT: vmovdqu8 xmmword ptr [rdi] {k1}, xmm1
|
||||
simd_masked_store(mask, pointer, value)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: store_f32x8
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn store_f32x8(mask: m32x8, pointer: *mut f32, value: f32x8) {
|
||||
// x86-avx2: vpslld ymm0, ymm0, 31
|
||||
// x86-avx2-NEXT: vmaskmovps ymmword ptr [rdi], ymm0, ymm1
|
||||
//
|
||||
// x86-avx512: vpslld ymm0, ymm0, 31
|
||||
// x86-avx512-NEXT: vpmovd2m k1, ymm0
|
||||
// x86-avx512-NEXT: vmovups ymmword ptr [rdi] {k1}, ymm1
|
||||
simd_masked_store(mask, pointer, value)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: store_f64x4
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn store_f64x4(mask: m64x4, pointer: *mut f64, value: f64x4) {
|
||||
// x86-avx2: vpsllq ymm0, ymm0, 63
|
||||
// x86-avx2-NEXT: vmaskmovpd ymmword ptr [rdi], ymm0, ymm1
|
||||
//
|
||||
// x86-avx512: vpsllq ymm0, ymm0, 63
|
||||
// x86-avx512-NEXT: vpmovq2m k1, ymm0
|
||||
// x86-avx512-NEXT: vmovupd ymmword ptr [rdi] {k1}, ymm1
|
||||
simd_masked_store(mask, pointer, value)
|
||||
}
|
40
tests/assembly/simd-intrinsic-scatter.rs
Normal file
40
tests/assembly/simd-intrinsic-scatter.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
//@ revisions: x86-avx512
|
||||
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
|
||||
//@ [x86-avx512] needs-llvm-components: x86
|
||||
//@ [x86-avx512] min-llvm-version: 18.0
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type=lib -O
|
||||
|
||||
#![feature(no_core, lang_items, repr_simd, intrinsics)]
|
||||
#![no_core]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f64x4([f64; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x4([i64; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct pf64x4([*mut f64; 4]);
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn simd_scatter<V, P, M>(values: V, pointer: P, mask: M);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: scatter_f64x4
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn scatter_f64x4(values: f64x4, ptrs: pf64x4, mask: m64x4) {
|
||||
// x86-avx512: vpsllq ymm2, ymm2, 63
|
||||
// x86-avx512-NEXT: vpmovq2m k1, ymm2
|
||||
// x86-avx512-NEXT: vscatterqpd ymmword ptr [1*ymm1] {k1}, ymm0
|
||||
simd_scatter(values, ptrs, mask)
|
||||
}
|
130
tests/assembly/simd-intrinsic-select.rs
Normal file
130
tests/assembly/simd-intrinsic-select.rs
Normal file
|
@ -0,0 +1,130 @@
|
|||
//@ revisions: x86-avx2 x86-avx512 aarch64
|
||||
//@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx2] compile-flags: -C target-feature=+avx2
|
||||
//@ [x86-avx2] needs-llvm-components: x86
|
||||
//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
|
||||
//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
|
||||
//@ [x86-avx512] needs-llvm-components: x86
|
||||
//@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
|
||||
//@ [aarch64] needs-llvm-components: aarch64
|
||||
//@ [aarch64] min-llvm-version: 18.0
|
||||
//@ assembly-output: emit-asm
|
||||
//@ compile-flags: --crate-type=lib -O
|
||||
|
||||
#![feature(no_core, lang_items, repr_simd, intrinsics)]
|
||||
#![no_core]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// Because we don't have core yet.
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
trait Copy {}
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct i8x16([i8; 16]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m8x16([i8; 16]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f32x4([f32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m32x4([i32; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f64x2([f64; 2]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x2([i64; 2]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f64x4([f64; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x4([i64; 4]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct f64x8([f64; 8]);
|
||||
|
||||
#[repr(simd)]
|
||||
pub struct m64x8([i64; 8]);
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
fn simd_select<M, V>(mask: M, a: V, b: V) -> V;
|
||||
}
|
||||
|
||||
// CHECK-LABEL: select_i8x16
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16 {
|
||||
// x86-avx2: vpsllw xmm0, xmm0, 7
|
||||
// x86-avx2-NEXT: vpblendvb xmm0, xmm2, xmm1, xmm0
|
||||
//
|
||||
// x86-avx512: vpsllw xmm0, xmm0, 7
|
||||
// x86-avx512-NEXT: vpmovb2m k1, xmm0
|
||||
// x86-avx512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1
|
||||
//
|
||||
// aarch64: shl v0.16b, v0.16b, #7
|
||||
// aarch64-NEXT: cmlt v0.16b, v0.16b, #0
|
||||
// aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
|
||||
simd_select(mask, a, b)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: select_f32x4
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4 {
|
||||
// x86-avx2: vpslld xmm0, xmm0, 31
|
||||
// x86-avx2-NEXT: vblendvps xmm0, xmm2, xmm1, xmm0
|
||||
//
|
||||
// x86-avx512: vpslld xmm0, xmm0, 31
|
||||
// x86-avx512-NEXT: vpmovd2m k1, xmm0
|
||||
// x86-avx512-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1
|
||||
//
|
||||
// aarch64: shl v0.4s, v0.4s, #31
|
||||
// aarch64-NEXT: cmlt v0.4s, v0.4s, #0
|
||||
// aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
|
||||
simd_select(mask, a, b)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: select_f64x2
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 {
|
||||
// x86-avx2: vpsllq xmm0, xmm0, 63
|
||||
// x86-avx2-NEXT: vblendvpd xmm0, xmm2, xmm1, xmm0
|
||||
//
|
||||
// x86-avx512: vpsllq xmm0, xmm0, 63
|
||||
// x86-avx512-NEXT: vpmovq2m k1, xmm0
|
||||
// x86-avx512-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1
|
||||
//
|
||||
// aarch64: shl v0.2d, v0.2d, #63
|
||||
// aarch64-NEXT: cmlt v0.2d, v0.2d, #0
|
||||
// aarch64-NEXT: bsl v0.16b, v1.16b, v2.16b
|
||||
simd_select(mask, a, b)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: select_f64x4
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 {
|
||||
// The parameter is a 256 bit vector which in the C abi is only valid for avx targets.
|
||||
//
|
||||
// x86-avx2: vpsllq ymm0, ymm0, 63
|
||||
// x86-avx2-NEXT: vblendvpd ymm0, ymm2, ymm1, ymm0
|
||||
//
|
||||
// x86-avx512: vpsllq ymm0, ymm0, 63
|
||||
// x86-avx512-NEXT: vpmovq2m k1, ymm0
|
||||
// x86-avx512-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1
|
||||
simd_select(mask, a, b)
|
||||
}
|
||||
|
||||
// CHECK-LABEL: select_f64x8
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 {
|
||||
// The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets.
|
||||
//
|
||||
// x86-avx512: vpsllq zmm0, zmm0, 63
|
||||
// x86-avx512-NEXT: vpmovq2m k1, zmm0
|
||||
// x86-avx512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1
|
||||
simd_select(mask, a, b)
|
||||
}
|
|
@ -1,26 +1,37 @@
|
|||
#![crate_name = "foo"]
|
||||
|
||||
use std::ops::Add;
|
||||
use std::fmt::Display;
|
||||
use std::ops::Add;
|
||||
|
||||
//@count foo/fn.function_with_a_really_long_name.html //pre/br 2
|
||||
pub fn function_with_a_really_long_name(parameter_one: i32,
|
||||
parameter_two: i32)
|
||||
-> Option<i32> {
|
||||
// @matches foo/fn.function_with_a_really_long_name.html '//*[@class="rust item-decl"]//code' "\
|
||||
// function_with_a_really_long_name\(\n\
|
||||
// \ parameter_one: i32,\n\
|
||||
// \ parameter_two: i32\n\
|
||||
// \) -> Option<i32>$"
|
||||
pub fn function_with_a_really_long_name(parameter_one: i32, parameter_two: i32) -> Option<i32> {
|
||||
Some(parameter_one + parameter_two)
|
||||
}
|
||||
|
||||
//@count foo/fn.short_name.html //pre/br 0
|
||||
pub fn short_name(param: i32) -> i32 { param + 1 }
|
||||
// @matches foo/fn.short_name.html '//*[@class="rust item-decl"]//code' \
|
||||
// "short_name\(param: i32\) -> i32$"
|
||||
pub fn short_name(param: i32) -> i32 {
|
||||
param + 1
|
||||
}
|
||||
|
||||
//@count foo/fn.where_clause.html //pre/br 4
|
||||
pub fn where_clause<T, U>(param_one: T,
|
||||
param_two: U)
|
||||
where T: Add<U> + Display + Copy,
|
||||
U: Add<T> + Display + Copy,
|
||||
T::Output: Display + Add<U::Output> + Copy,
|
||||
<T::Output as Add<U::Output>>::Output: Display,
|
||||
U::Output: Display + Copy
|
||||
// @matches foo/fn.where_clause.html '//*[@class="rust item-decl"]//code' "\
|
||||
// where_clause<T, U>\(param_one: T, param_two: U\)where\n\
|
||||
// \ T: Add<U> \+ Display \+ Copy,\n\
|
||||
// \ U: Add<T> \+ Display \+ Copy,\n\
|
||||
// \ T::Output: Display \+ Add<U::Output> \+ Copy,\n\
|
||||
// \ <T::Output as Add<U::Output>>::Output: Display,\n\
|
||||
// \ U::Output: Display \+ Copy,$"
|
||||
pub fn where_clause<T, U>(param_one: T, param_two: U)
|
||||
where
|
||||
T: Add<U> + Display + Copy,
|
||||
U: Add<T> + Display + Copy,
|
||||
T::Output: Display + Add<U::Output> + Copy,
|
||||
<T::Output as Add<U::Output>>::Output: Display,
|
||||
U::Output: Display + Copy,
|
||||
{
|
||||
let x = param_one + param_two;
|
||||
println!("{} + {} = {}", param_one, param_two, x);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: malformed `unix_sigpipe` attribute input
|
||||
--> $DIR/unix_sigpipe-list.rs:3:1
|
||||
--> $DIR/unix_sigpipe-ident-list.rs:3:1
|
||||
|
|
||||
LL | #[unix_sigpipe(sig_dfl)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`
|
|
@ -0,0 +1,4 @@
|
|||
#![feature(unix_sigpipe)]
|
||||
|
||||
#[unix_sigpipe("sig_dfl")] //~ error: malformed `unix_sigpipe` attribute input
|
||||
fn main() {}
|
|
@ -0,0 +1,8 @@
|
|||
error: malformed `unix_sigpipe` attribute input
|
||||
--> $DIR/unix_sigpipe-str-list.rs:3:1
|
||||
|
|
||||
LL | #[unix_sigpipe("sig_dfl")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
14
tests/ui/impl-trait/associated-type-cycle.rs
Normal file
14
tests/ui/impl-trait/associated-type-cycle.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
trait Foo {
|
||||
type Bar;
|
||||
fn foo(self) -> Self::Bar;
|
||||
}
|
||||
|
||||
impl Foo for Box<dyn Foo> {
|
||||
//~^ ERROR: the value of the associated type `Bar` in `Foo` must be specified
|
||||
type Bar = <Self as Foo>::Bar;
|
||||
fn foo(self) -> <Self as Foo>::Bar {
|
||||
(*self).foo()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
12
tests/ui/impl-trait/associated-type-cycle.stderr
Normal file
12
tests/ui/impl-trait/associated-type-cycle.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0191]: the value of the associated type `Bar` in `Foo` must be specified
|
||||
--> $DIR/associated-type-cycle.rs:6:22
|
||||
|
|
||||
LL | type Bar;
|
||||
| -------- `Bar` defined here
|
||||
...
|
||||
LL | impl Foo for Box<dyn Foo> {
|
||||
| ^^^ help: specify the associated type: `Foo<Bar = Type>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0191`.
|
Loading…
Reference in a new issue