Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2024-10-30 05:12:55 +00:00
commit 7d12e50f73
1778 changed files with 31621 additions and 19057 deletions

View file

@ -1092,9 +1092,6 @@ class RustBuild(object):
if not os.path.exists(cargo_dir):
eprint('ERROR: vendoring required, but .cargo/config does not exist.')
raise Exception("{} not found".format(cargo_dir))
else:
if os.path.exists(cargo_dir):
shutil.rmtree(cargo_dir)
def parse_args(args):
"""Parse the command line arguments that the python script needs."""

View file

@ -72,6 +72,7 @@ v("llvm-libunwind", "rust.llvm-libunwind", "use LLVM libunwind")
o("optimize-llvm", "llvm.optimize", "build optimized LLVM")
o("llvm-assertions", "llvm.assertions", "build LLVM with assertions")
o("llvm-enzyme", "llvm.enzyme", "build LLVM with enzyme")
o("llvm-offload", "llvm.offload", "build LLVM with gpu offload support")
o("llvm-plugins", "llvm.plugins", "build LLVM with plugin interface")
o("debug-assertions", "rust.debug-assertions", "build with debugging assertions")
o("debug-assertions-std", "rust.debug-assertions-std", "build the standard library with debugging assertions")

View file

@ -15,7 +15,6 @@ use std::path::{Path, PathBuf};
use std::process::Stdio;
use std::{env, fs, str};
use build_helper::git::get_closest_merge_commit;
use serde_derive::Deserialize;
use crate::core::build_steps::tool::SourceType;
@ -27,7 +26,7 @@ use crate::core::builder::{
use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
use crate::utils::exec::command;
use crate::utils::helpers::{
self, exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
};
use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode};
@ -125,23 +124,9 @@ impl Step for Std {
// Force compilation of the standard library from source if the `library` is modified. This allows
// library team to compile the standard library without needing to compile the compiler with
// the `rust.download-rustc=true` option.
let force_recompile =
if builder.rust_info().is_managed_git_subrepository() && builder.download_rustc() {
let closest_merge_commit =
get_closest_merge_commit(Some(&builder.src), &builder.config.git_config(), &[])
.unwrap();
// Check if `library` has changes (returns false otherwise)
!t!(helpers::git(Some(&builder.src))
.args(["diff-index", "--quiet", &closest_merge_commit])
.arg("--")
.arg(builder.src.join("library"))
.as_command_mut()
.status())
.success()
} else {
false
};
let force_recompile = builder.rust_info().is_managed_git_subrepository()
&& builder.download_rustc()
&& builder.config.last_modified_commit(&["library"], "download-rustc", true).is_none();
run.builder.ensure(Std {
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),

View file

@ -170,7 +170,14 @@ impl<P: Step> Step for RustbookSrc<P> {
builder.add_rustc_lib_path(compiler, &mut rustbook_cmd);
}
rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).run(builder);
rustbook_cmd
.arg("build")
.arg(&src)
.arg("-d")
.arg(&out)
.arg("--rust-root")
.arg(&builder.src)
.run(builder);
for lang in &self.languages {
let out = out.join(lang);

View file

@ -472,6 +472,21 @@ impl Step for Llvm {
cfg.define("LLVM_ENABLE_PROJECTS", enabled_llvm_projects.join(";"));
}
let mut enabled_llvm_runtimes = Vec::new();
if builder.config.llvm_offload {
enabled_llvm_runtimes.push("offload");
//FIXME(ZuseZ4): LLVM intends to drop the offload dependency on openmp.
//Remove this line once they achieved it.
enabled_llvm_runtimes.push("openmp");
}
if !enabled_llvm_runtimes.is_empty() {
enabled_llvm_runtimes.sort();
enabled_llvm_runtimes.dedup();
cfg.define("LLVM_ENABLE_RUNTIMES", enabled_llvm_runtimes.join(";"));
}
if let Some(num_linkers) = builder.config.llvm_link_jobs {
if num_linkers > 0 {
cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string());

View file

@ -1734,13 +1734,15 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
} else {
// We need to properly build cargo using the suitable stage compiler.
// HACK: currently tool stages are off-by-one compared to compiler stages, i.e. if
// you give `tool::Cargo` a stage 1 rustc, it will cause stage 2 rustc to be built
// and produce a cargo built with stage 2 rustc. To fix this, we need to chop off
// the compiler stage by 1 to align with expected `./x test run-make --stage N`
// behavior, i.e. we need to pass `N - 1` compiler stage to cargo. See also Miri
// which does a similar hack.
let compiler = builder.compiler(builder.top_stage - 1, compiler.host);
let compiler = builder.download_rustc().then_some(compiler).unwrap_or_else(||
// HACK: currently tool stages are off-by-one compared to compiler stages, i.e. if
// you give `tool::Cargo` a stage 1 rustc, it will cause stage 2 rustc to be built
// and produce a cargo built with stage 2 rustc. To fix this, we need to chop off
// the compiler stage by 1 to align with expected `./x test run-make --stage N`
// behavior, i.e. we need to pass `N - 1` compiler stage to cargo. See also Miri
// which does a similar hack.
builder.compiler(builder.top_stage - 1, compiler.host));
builder.ensure(tool::Cargo { compiler, target: compiler.host })
};
@ -1834,6 +1836,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
if builder.config.cmd.only_modified() {
cmd.arg("--only-modified");
}
if let Some(compiletest_diff_tool) = &builder.config.compiletest_diff_tool {
cmd.arg("--compiletest-diff-tool").arg(compiletest_diff_tool);
}
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
@ -3549,9 +3554,7 @@ impl Step for TestFloatParse {
let path = self.path.to_str().unwrap();
let crate_name = self.path.components().last().unwrap().as_os_str().to_str().unwrap();
if !builder.download_rustc() {
builder.ensure(compile::Std::new(compiler, self.host));
}
builder.ensure(tool::TestFloatParse { host: self.host });
// Run any unit tests in the crate
let cargo_test = tool::prepare_tool_cargo(

View file

@ -1,8 +1,6 @@
use std::path::PathBuf;
use std::{env, fs};
use build_helper::git::get_closest_merge_commit;
use crate::core::build_steps::compile;
use crate::core::build_steps::toolstate::ToolState;
use crate::core::builder;
@ -10,7 +8,7 @@ use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun,
use crate::core::config::TargetSelection;
use crate::utils::channel::GitInfo;
use crate::utils::exec::{BootstrapCommand, command};
use crate::utils::helpers::{add_dylib_path, exe, git, t};
use crate::utils::helpers::{add_dylib_path, exe, t};
use crate::{Compiler, Kind, Mode, gha};
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
@ -596,28 +594,11 @@ impl Step for Rustdoc {
&& target_compiler.stage > 0
&& builder.rust_info().is_managed_git_subrepository()
{
let commit = get_closest_merge_commit(
Some(&builder.config.src),
&builder.config.git_config(),
&[],
)
.unwrap();
let files_to_track = &["src/librustdoc", "src/tools/rustdoc"];
let librustdoc_src = builder.config.src.join("src/librustdoc");
let rustdoc_src = builder.config.src.join("src/tools/rustdoc");
// FIXME: The change detection logic here is quite similar to `Config::download_ci_rustc_commit`.
// It would be better to unify them.
let has_changes = !git(Some(&builder.config.src))
.allow_failure()
.run_always()
.args(["diff-index", "--quiet", &commit])
.arg("--")
.arg(librustdoc_src)
.arg(rustdoc_src)
.run(builder);
if !has_changes {
// Check if unchanged
if builder.config.last_modified_commit(files_to_track, "download-rustc", true).is_some()
{
let precompiled_rustdoc = builder
.config
.ci_rustc_dir()
@ -1097,6 +1078,38 @@ tool_extended!((self, builder),
Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"];
);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct TestFloatParse {
pub host: TargetSelection,
}
impl Step for TestFloatParse {
type Output = ();
const ONLY_HOSTS: bool = true;
const DEFAULT: bool = false;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/etc/test-float-parse")
}
fn run(self, builder: &Builder<'_>) {
let bootstrap_host = builder.config.build;
let compiler = builder.compiler(builder.top_stage, bootstrap_host);
builder.ensure(ToolBuild {
compiler,
target: bootstrap_host,
tool: "test-float-parse",
mode: Mode::ToolStd,
path: "src/etc/test-float-parse",
source_type: SourceType::InTree,
extra_features: Vec::new(),
allow_features: "",
cargo_args: Vec::new(),
});
}
}
impl Builder<'_> {
/// Gets a `BootstrapCommand` which is ready to run `tool` in `stage` built for
/// `host`.

View file

@ -224,6 +224,7 @@ pub struct Config {
pub llvm_assertions: bool,
pub llvm_tests: bool,
pub llvm_enzyme: bool,
pub llvm_offload: bool,
pub llvm_plugins: bool,
pub llvm_optimize: bool,
pub llvm_thin_lto: bool,
@ -368,6 +369,9 @@ pub struct Config {
/// The paths to work with. For example: with `./x check foo bar` we get
/// `paths=["foo", "bar"]`.
pub paths: Vec<PathBuf>,
/// Command for visual diff display, e.g. `diff-tool --color=always`.
pub compiletest_diff_tool: Option<String>,
}
#[derive(Clone, Debug, Default)]
@ -892,6 +896,7 @@ define_config! {
android_ndk: Option<PathBuf> = "android-ndk",
optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
jobs: Option<u32> = "jobs",
compiletest_diff_tool: Option<String> = "compiletest-diff-tool",
}
}
@ -934,6 +939,7 @@ define_config! {
use_libcxx: Option<bool> = "use-libcxx",
use_linker: Option<String> = "use-linker",
allow_old_toolchain: Option<bool> = "allow-old-toolchain",
offload: Option<bool> = "offload",
polly: Option<bool> = "polly",
clang: Option<bool> = "clang",
enable_warnings: Option<bool> = "enable-warnings",
@ -1512,6 +1518,7 @@ impl Config {
android_ndk,
optimized_compiler_builtins,
jobs,
compiletest_diff_tool,
} = toml.build.unwrap_or_default();
config.jobs = Some(threads_from_config(flags.jobs.unwrap_or(jobs.unwrap_or(0))));
@ -1642,6 +1649,7 @@ impl Config {
// we'll infer default values for them later
let mut llvm_tests = None;
let mut llvm_enzyme = None;
let mut llvm_offload = None;
let mut llvm_plugins = None;
let mut debug = None;
let mut debug_assertions = None;
@ -1879,6 +1887,7 @@ impl Config {
use_libcxx,
use_linker,
allow_old_toolchain,
offload,
polly,
clang,
enable_warnings,
@ -1895,6 +1904,7 @@ impl Config {
set(&mut config.ninja_in_file, ninja);
llvm_tests = tests;
llvm_enzyme = enzyme;
llvm_offload = offload;
llvm_plugins = plugins;
set(&mut config.llvm_optimize, optimize_toml);
set(&mut config.llvm_thin_lto, thin_lto);
@ -1916,6 +1926,7 @@ impl Config {
set(&mut config.llvm_use_libcxx, use_libcxx);
config.llvm_use_linker.clone_from(&use_linker);
config.llvm_allow_old_toolchain = allow_old_toolchain.unwrap_or(false);
config.llvm_offload = offload.unwrap_or(false);
config.llvm_polly = polly.unwrap_or(false);
config.llvm_clang = clang.unwrap_or(false);
config.llvm_enable_warnings = enable_warnings.unwrap_or(false);
@ -2092,6 +2103,7 @@ impl Config {
config.llvm_tests = llvm_tests.unwrap_or(false);
config.llvm_enzyme = llvm_enzyme.unwrap_or(false);
config.llvm_offload = llvm_offload.unwrap_or(false);
config.llvm_plugins = llvm_plugins.unwrap_or(false);
config.rust_optimize = optimize.unwrap_or(RustOptimize::Bool(true));
@ -2158,6 +2170,7 @@ impl Config {
config.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(DebuginfoLevel::None);
config.optimized_compiler_builtins =
optimized_compiler_builtins.unwrap_or(config.channel != "dev");
config.compiletest_diff_tool = compiletest_diff_tool;
let download_rustc = config.download_rustc_commit.is_some();
// See https://github.com/rust-lang/compiler-team/issues/326
@ -2754,25 +2767,25 @@ impl Config {
}
};
let files_to_track = &[
self.src.join("compiler"),
self.src.join("library"),
self.src.join("src/version"),
self.src.join("src/stage0"),
self.src.join("src/ci/channel"),
];
let files_to_track =
&["compiler", "library", "src/version", "src/stage0", "src/ci/channel"];
// Look for a version to compare to based on the current commit.
// Only commits merged by bors will have CI artifacts.
let commit =
get_closest_merge_commit(Some(&self.src), &self.git_config(), files_to_track).unwrap();
if commit.is_empty() {
println!("ERROR: could not find commit hash for downloading rustc");
println!("HELP: maybe your repository history is too shallow?");
println!("HELP: consider disabling `download-rustc`");
println!("HELP: or fetch enough history to include one upstream commit");
crate::exit!(1);
}
let commit = match self.last_modified_commit(files_to_track, "download-rustc", if_unchanged)
{
Some(commit) => commit,
None => {
if if_unchanged {
return None;
}
println!("ERROR: could not find commit hash for downloading rustc");
println!("HELP: maybe your repository history is too shallow?");
println!("HELP: consider disabling `download-rustc`");
println!("HELP: or fetch enough history to include one upstream commit");
crate::exit!(1);
}
};
if CiEnv::is_ci() && {
let head_sha =
@ -2787,31 +2800,7 @@ impl Config {
return None;
}
// Warn if there were changes to the compiler or standard library since the ancestor commit.
let has_changes = !t!(helpers::git(Some(&self.src))
.args(["diff-index", "--quiet", &commit])
.arg("--")
.args(files_to_track)
.as_command_mut()
.status())
.success();
if has_changes {
if if_unchanged {
if self.is_verbose() {
println!(
"WARNING: saw changes to compiler/ or library/ since {commit}; \
ignoring `download-rustc`"
);
}
return None;
}
println!(
"WARNING: `download-rustc` is enabled, but there are changes to \
compiler/ or library/"
);
}
Some(commit.to_string())
Some(commit)
}
fn parse_download_ci_llvm(
@ -2882,14 +2871,7 @@ impl Config {
// Warn if there were changes to the compiler or standard library since the ancestor commit.
let mut git = helpers::git(Some(&self.src));
git.args(["diff-index", "--quiet", &commit, "--"]);
// Handle running from a directory other than the top level
let top_level = &self.src;
for path in modified_paths {
git.arg(top_level.join(path));
}
git.args(["diff-index", "--quiet", &commit, "--"]).args(modified_paths);
let has_changes = !t!(git.as_command_mut().status()).success();
if has_changes {
@ -2981,6 +2963,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
use_libcxx,
use_linker,
allow_old_toolchain,
offload,
polly,
clang,
enable_warnings,
@ -3003,6 +2986,7 @@ pub(crate) fn check_incompatible_options_for_ci_llvm(
err!(current_llvm_config.use_libcxx, use_libcxx);
err!(current_llvm_config.use_linker, use_linker);
err!(current_llvm_config.allow_old_toolchain, allow_old_toolchain);
err!(current_llvm_config.offload, offload);
err!(current_llvm_config.polly, polly);
err!(current_llvm_config.clang, clang);
err!(current_llvm_config.build_config, build_config);

View file

@ -541,27 +541,32 @@ impl Build {
}
let output = helpers::git(Some(&self.src))
.args(["config", "--file"])
.arg(self.config.src.join(".gitmodules"))
.arg(".gitmodules")
.args(["--get-regexp", "path"])
.run_capture(self)
.stdout();
for line in output.lines() {
std::thread::scope(|s| {
// Look for `submodule.$name.path = $path`
// Sample output: `submodule.src/rust-installer.path src/tools/rust-installer`
let submodule = line.split_once(' ').unwrap().1;
self.update_existing_submodule(submodule);
}
for line in output.lines() {
let submodule = line.split_once(' ').unwrap().1;
let config = self.config.clone();
s.spawn(move || {
Self::update_existing_submodule(&config, submodule);
});
}
});
}
/// Updates the given submodule only if it's initialized already; nothing happens otherwise.
pub fn update_existing_submodule(&self, submodule: &str) {
pub fn update_existing_submodule(config: &Config, submodule: &str) {
// Avoid running git when there isn't a git checkout.
if !self.config.submodules() {
if !config.submodules() {
return;
}
if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() {
self.config.update_submodule(submodule);
config.update_submodule(submodule);
}
}

View file

@ -280,4 +280,14 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Info,
summary: "Allow setting `--jobs` in config.toml with `build.jobs`.",
},
ChangeInfo {
change_id: 131181,
severity: ChangeSeverity::Info,
summary: "New option `build.compiletest-diff-tool` that adds support for a custom differ for compiletest",
},
ChangeInfo {
change_id: 131513,
severity: ChangeSeverity::Info,
summary: "New option `llvm.offload` to control whether the llvm offload runtime for GPU support is built. Implicitly enables the openmp runtime as dependency.",
},
];

View file

@ -10,7 +10,7 @@ use std::path::Path;
use super::helpers;
use crate::Build;
use crate::utils::helpers::{output, t};
use crate::utils::helpers::{start_process, t};
#[derive(Clone, Default)]
pub enum GitInfo {
@ -56,7 +56,7 @@ impl GitInfo {
}
// Ok, let's scrape some info
let ver_date = output(
let ver_date = start_process(
helpers::git(Some(dir))
.arg("log")
.arg("-1")
@ -65,14 +65,14 @@ impl GitInfo {
.as_command_mut(),
);
let ver_hash =
output(helpers::git(Some(dir)).arg("rev-parse").arg("HEAD").as_command_mut());
let short_ver_hash = output(
start_process(helpers::git(Some(dir)).arg("rev-parse").arg("HEAD").as_command_mut());
let short_ver_hash = start_process(
helpers::git(Some(dir)).arg("rev-parse").arg("--short=9").arg("HEAD").as_command_mut(),
);
GitInfo::Present(Some(Info {
commit_date: ver_date.trim().to_string(),
sha: ver_hash.trim().to_string(),
short_sha: short_ver_hash.trim().to_string(),
commit_date: ver_date().trim().to_string(),
sha: ver_hash().trim().to_string(),
short_sha: short_ver_hash().trim().to_string(),
}))
}

View file

@ -288,6 +288,33 @@ pub fn output(cmd: &mut Command) -> String {
String::from_utf8(output.stdout).unwrap()
}
/// Spawn a process and return a closure that will wait for the process
/// to finish and then return its output. This allows the spawned process
/// to do work without immediately blocking bootstrap.
#[track_caller]
pub fn start_process(cmd: &mut Command) -> impl FnOnce() -> String {
let child = match cmd.stderr(Stdio::inherit()).stdout(Stdio::piped()).spawn() {
Ok(child) => child,
Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")),
};
let command = format!("{:?}", cmd);
move || {
let output = child.wait_with_output().unwrap();
if !output.status.success() {
panic!(
"command did not execute successfully: {}\n\
expected success, got: {}",
command, output.status
);
}
String::from_utf8(output.stdout).unwrap()
}
}
/// Returns the last-modified time for `path`, or zero if it doesn't exist.
pub fn mtime(path: &Path) -> SystemTime {
fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH)

View file

@ -0,0 +1,58 @@
FROM ubuntu:22.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ \
make \
ninja-build \
file \
curl \
ca-certificates \
python3 \
python3-dev \
libxml2-dev \
libncurses-dev \
libedit-dev \
swig \
doxygen \
git \
cmake \
sudo \
gdb \
libssl-dev \
pkg-config \
xz-utils \
lld \
clang \
&& rm -rf /var/lib/apt/lists/*
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV RUSTBUILD_FORCE_CLANG_BASED_TESTS 1
ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
# llvm.use-linker conflicts with downloading CI LLVM
ENV NO_DOWNLOAD_CI_LLVM 1
ENV RUST_CONFIGURE_ARGS \
--build=aarch64-unknown-linux-gnu \
--enable-debug \
--enable-lld \
--set llvm.use-linker=lld \
--set target.aarch64-unknown-linux-gnu.linker=clang \
--set target.aarch64-unknown-linux-gnu.cc=clang \
--set target.aarch64-unknown-linux-gnu.cxx=clang++
# This job appears to be checking two separate things:
# - That we can build the compiler with `--enable-debug`
# (without necessarily testing the result).
# - That the tests with `//@ needs-force-clang-based-tests` pass, since they
# don't run by default unless RUSTBUILD_FORCE_CLANG_BASED_TESTS is set.
# - FIXME(https://github.com/rust-lang/rust/pull/126155#issuecomment-2156314273):
# Currently we only run the subset of tests with "clang" in their name.
# - See also FIXME(#132034)
ENV SCRIPT \
python3 ../x.py --stage 2 build && \
python3 ../x.py --stage 2 test tests/run-make --test-args clang

View file

@ -56,9 +56,9 @@ ENV \
CFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
CXX_x86_64_fortanix_unknown_sgx=clang++-11 \
CXXFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
AR_i686_unknown_freebsd=i686-unknown-freebsd13-ar \
CC_i686_unknown_freebsd=i686-unknown-freebsd13-clang \
CXX_i686_unknown_freebsd=i686-unknown-freebsd13-clang++ \
AR_i686_unknown_freebsd=i686-unknown-freebsd12-ar \
CC_i686_unknown_freebsd=i686-unknown-freebsd12-clang \
CXX_i686_unknown_freebsd=i686-unknown-freebsd12-clang++ \
CC_aarch64_unknown_uefi=clang-11 \
CXX_aarch64_unknown_uefi=clang++-11 \
CC_i686_unknown_uefi=clang-11 \
@ -118,6 +118,7 @@ ENV TARGETS=$TARGETS,wasm32-wasi
ENV TARGETS=$TARGETS,wasm32-wasip1
ENV TARGETS=$TARGETS,wasm32-wasip1-threads
ENV TARGETS=$TARGETS,wasm32-wasip2
ENV TARGETS=$TARGETS,wasm32v1-none
ENV TARGETS=$TARGETS,sparcv9-sun-solaris
ENV TARGETS=$TARGETS,x86_64-pc-solaris
ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32

View file

@ -29,9 +29,9 @@ COPY scripts/cmake.sh /scripts/
RUN /scripts/cmake.sh
ENV \
AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-ar \
CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-clang \
CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-clang++
AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-ar \
CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-clang \
CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-clang++
ENV HOSTS=x86_64-unknown-freebsd

View file

@ -51,7 +51,8 @@ ENV SCRIPT \
/scripts/check-default-config-profiles.sh && \
python3 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \
python3 ../x.py clippy bootstrap -Dwarnings && \
python3 ../x.py clippy compiler library -Aclippy::all -Dclippy::correctness && \
python3 ../x.py clippy library -Aclippy::all -Dclippy::correctness && \
python3 ../x.py clippy compiler -Aclippy::all -Dclippy::correctness -Dclippy::clone_on_ref_ptr && \
python3 ../x.py build --stage 0 src/tools/build-manifest && \
python3 ../x.py test --stage 0 src/tools/compiletest && \
python3 ../x.py test --stage 0 core alloc std test proc_macro && \

View file

@ -49,9 +49,7 @@ ENV RUST_CONFIGURE_ARGS \
# (without necessarily testing the result).
# - That the tests with `//@ needs-force-clang-based-tests` pass, since they
# don't run by default unless RUSTBUILD_FORCE_CLANG_BASED_TESTS is set.
# - FIXME(https://github.com/rust-lang/rust/pull/126155#issuecomment-2156314273):
# Currently we only run the subset of tests with "clang" in their name.
ENV SCRIPT \
python3 ../x.py --stage 2 build && \
python3 ../x.py --stage 2 test tests/run-make --test-args clang
python3 ../x.py --stage 2 test tests/run-make

View file

@ -5,8 +5,8 @@ set -eux
arch=$1
binutils_version=2.40
freebsd_version=13.2
triple=$arch-unknown-freebsd13
freebsd_version=12.3
triple=$arch-unknown-freebsd12
sysroot=/usr/local/$triple
hide_output() {
@ -59,7 +59,7 @@ done
# Originally downloaded from:
# URL=https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
URL=https://ci-mirrors.rust-lang.org/rustc/2024-02-18-freebsd-${freebsd_version}-${freebsd_arch}-base.txz
URL=https://ci-mirrors.rust-lang.org/rustc/2022-05-06-freebsd-${freebsd_version}-${freebsd_arch}-base.txz
curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
# Clang can do cross-builds out of the box, if we give it the right
@ -68,7 +68,7 @@ curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
# there might be other problems.)
#
# The --target option is last because the cross-build of LLVM uses
# --target without an OS version ("-freebsd" vs. "-freebsd13"). This
# --target without an OS version ("-freebsd" vs. "-freebsd12"). This
# makes Clang default to libstdc++ (which no longer exists), and also
# controls other features, like GNU-style symbol table hashing and
# anything predicated on the version number in the __FreeBSD__

View file

@ -287,7 +287,7 @@ class TestEnvironment:
@property
def package_server_log_path(self) -> Path:
return self.tmp_dir().joinpath("package_server_log")
return self.tmp_dir().joinpath(f"repo_{self.TEST_REPO_NAME}.log")
@property
def emulator_log_path(self) -> Path:
@ -401,6 +401,7 @@ class TestEnvironment:
# Set configs
configs = {
"log.enabled": "true",
"log.dir": self.tmp_dir(),
"test.is_isolated": "true",
"test.experimental_structured_output": "true",
}
@ -575,43 +576,19 @@ class TestEnvironment:
stderr_handler=self.subprocess_logger.debug,
)
# Add repository
check_call_with_logging(
[
ffx_path,
"repository",
"add-from-pm",
"--repository",
self.TEST_REPO_NAME,
self.repo_dir(),
],
env=ffx_env,
stdout_handler=self.subprocess_logger.debug,
stderr_handler=self.subprocess_logger.debug,
)
# Start repository server
# Note that we must first enable the repository server daemon.
check_call_with_logging(
[
ffx_path,
"config",
"set",
"repository.server.enabled",
"true",
],
env=ffx_env,
stdout_handler=self.subprocess_logger.debug,
stderr_handler=self.subprocess_logger.debug,
)
check_call_with_logging(
[
ffx_path,
"repository",
"server",
"start",
"--background",
"--address",
"[::]:0",
"--repo-path",
self.repo_dir(),
"--repository",
self.TEST_REPO_NAME
],
env=ffx_env,
stdout_handler=self.subprocess_logger.debug,
@ -1009,6 +986,21 @@ class TestEnvironment:
stderr_handler=self.subprocess_logger.debug,
)
# Stop the package server
self.env_logger.info("Stopping package server...")
check_call_with_logging(
[
self.tool_path("ffx"),
"repository",
"server",
"stop",
self.TEST_REPO_NAME
],
env=self.ffx_cmd_env(),
stdout_handler=self.subprocess_logger.debug,
stderr_handler=self.subprocess_logger.debug,
)
# Stop ffx isolation
self.env_logger.info("Stopping ffx isolation...")
self.stop_ffx_isolation()

View file

@ -2,7 +2,7 @@
set -euo pipefail
LINUX_VERSION=v6.12-rc2
LINUX_VERSION=28e848386b92645f93b9f2fdba5882c3ca7fb3e2
# Build rustc, rustdoc, cargo, clippy-driver and rustfmt
../x.py build --stage 2 library rustdoc clippy rustfmt

View file

@ -123,6 +123,9 @@ auto:
- image: aarch64-gnu
<<: *job-aarch64-linux
- image: aarch64-gnu-debug
<<: *job-aarch64-linux
- image: arm-android
<<: *job-linux-4c
@ -253,7 +256,9 @@ auto:
<<: *job-linux-4c
- image: x86_64-gnu-debug
<<: *job-linux-4c
# This seems to be needed because a full stage 2 build + run-make tests
# overwhelms the storage capacity of the standard 4c runner.
<<: *job-linux-4c-largedisk
- image: x86_64-gnu-distcheck
<<: *job-linux-8c

View file

@ -47,11 +47,6 @@ source "$ci_dir/shared.sh"
export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse
# suppress change-tracker warnings on CI
if [ "$CI" != "" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set change-id=99999999"
fi
# If runner uses an incompatible option and `FORCE_CI_RUSTC` is not defined,
# switch to in-tree rustc.
if [ "$FORCE_CI_RUSTC" == "" ]; then

@ -1 +1 @@
Subproject commit c7ebae25cb4801a31b6f05353f6d85bfa6feedd1
Subproject commit 1f07c242f8162a711a5ac5a4ea8fa7ec884ee7a9

@ -1 +1 @@
Subproject commit f40a8b420ec4b4505d9489965e261f1d5c28ba23
Subproject commit ddbf1b4e2858fedb71b7c42eb15c4576517dc125

@ -1 +1 @@
Subproject commit c64e52a3d306eac0129f3ad6c6d8806ab99ae2e9
Subproject commit 23ce619966541bf2c80d45fdfeecf3393e360a13

@ -1 +1 @@
Subproject commit 07bc9ca9eb1cd6d9fbbf758c2753b748804a134f
Subproject commit 59d94ea75a0b157e148af14c73c2dd60efb7b60a

View file

@ -66,9 +66,10 @@
- [powerpc-unknown-openbsd](platform-support/powerpc-unknown-openbsd.md)
- [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
- [powerpc64-ibm-aix](platform-support/aix.md)
- [riscv32e*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md)
- [riscv32i*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
- [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md)
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
- [riscv32*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
- [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
- [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md)
- [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
@ -86,6 +87,7 @@
- [wasm32-wasip2](platform-support/wasm32-wasip2.md)
- [wasm32-unknown-emscripten](platform-support/wasm32-unknown-emscripten.md)
- [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
- [wasm32v1-none](platform-support/wasm32v1-none.md)
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
- [\*-win7-windows-msvc](platform-support/win7-windows-msvc.md)
- [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)

View file

@ -100,7 +100,7 @@ target | notes
[`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29)
[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3)
`s390x-unknown-linux-gnu` | S390x Linux (kernel 3.2, glibc 2.17)
`x86_64-unknown-freebsd` | 64-bit FreeBSD (version 13.2)
`x86_64-unknown-freebsd` | 64-bit FreeBSD
`x86_64-unknown-illumos` | illumos
`x86_64-unknown-linux-musl` | 64-bit Linux with musl 1.2.3
[`x86_64-unknown-netbsd`](platform-support/netbsd.md) | NetBSD/amd64
@ -166,7 +166,7 @@ target | std | notes
`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, musl 1.2.3 [^x86_32-floats-x87]
[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android [^x86_32-floats-return-ABI]
[`i686-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | 32-bit x86 MinGW (Windows 10+), LLVM ABI [^x86_32-floats-return-ABI]
`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD (version 13.2) [^x86_32-floats-return-ABI]
`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI]
`i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 [^x86_32-floats-return-ABI]
[`i686-unknown-uefi`](platform-support/unknown-uefi.md) | ? | 32-bit UEFI
[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64D ABI)
@ -195,6 +195,7 @@ target | std | notes
`wasm32-wasi` | ✓ | WebAssembly with WASI (undergoing a [rename to `wasm32-wasip1`][wasi-rename])
[`wasm32-wasip1`](platform-support/wasm32-wasip1.md) | ✓ | WebAssembly with WASI
[`wasm32-wasip1-threads`](platform-support/wasm32-wasip1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
[`wasm32v1-none`](platform-support/wasm32v1-none.md) | * | WebAssembly limited to 1.0 features and no imports
[`x86_64-apple-ios`](platform-support/apple-ios.md) | ✓ | 64-bit x86 iOS
[`x86_64-apple-ios-macabi`](platform-support/apple-ios-macabi.md) | ✓ | Mac Catalyst on x86_64
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
@ -257,7 +258,7 @@ target | std | host | notes
[`aarch64-unknown-teeos`](platform-support/aarch64-unknown-teeos.md) | ? | | ARM64 TEEOS |
[`aarch64-unknown-nto-qnx700`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.0 RTOS |
[`aarch64-unknown-nto-qnx710`](platform-support/nto-qnx.md) | ✓ | | ARM64 QNX Neutrino 7.1 RTOS |
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD (version 13.2)
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
[`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit
`aarch64-unknown-illumos` | ✓ | ✓ | ARM64 illumos
`aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
@ -276,14 +277,14 @@ target | std | host | notes
`armv4t-unknown-linux-gnueabi` | ? | | Armv4T Linux
[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Bare Armv5TE
`armv5te-unknown-linux-uclibceabi` | ? | | Armv5TE Linux with uClibc
`armv6-unknown-freebsd` | ✓ | ✓ | Armv6 FreeBSD (version 13.2)
`armv6-unknown-freebsd` | ✓ | ✓ | Armv6 FreeBSD
[`armv6-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv6 NetBSD w/hard-float
[`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | Armv6k Nintendo 3DS, Horizon (Requires devkitARM toolchain)
[`armv7-rtems-eabihf`](platform-support/armv7-rtems-eabihf.md) | ? | | RTEMS OS for ARM BSPs
[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ✓ | | Armv7-A Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain)
[`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | Armv7-A Linux with uClibc, softfloat
[`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | Armv7-A Linux with uClibc, hardfloat
`armv7-unknown-freebsd` | ✓ | ✓ | Armv7-A FreeBSD (version 13.2)
`armv7-unknown-freebsd` | ✓ | ✓ | Armv7-A FreeBSD
[`armv7-unknown-netbsd-eabihf`](platform-support/netbsd.md) | ✓ | ✓ | Armv7-A NetBSD w/hard-float
[`armv7-unknown-trusty`](platform-support/trusty.md) | ? | |
[`armv7-wrs-vxworks-eabihf`](platform-support/vxworks.md) | ✓ | | Armv7-A for VxWorks
@ -342,9 +343,9 @@ target | std | host | notes
[`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | |
[`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | |
[`powerpc-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2, version 13.2)
`powerpc64le-unknown-freebsd` | | | PPC64LE FreeBSD (version 13.2)
`powerpc-unknown-freebsd` | | | PowerPC FreeBSD (version 13.2)
`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
`powerpc64le-unknown-freebsd` | | | PPC64LE FreeBSD
`powerpc-unknown-freebsd` | | | PowerPC FreeBSD
`powerpc64-unknown-linux-musl` | ? | | 64-bit PowerPC Linux with musl 1.2.3
[`powerpc64-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
`powerpc64le-unknown-linux-musl` | ? | | 64-bit PowerPC Linux with musl 1.2.3, Little Endian
@ -360,7 +361,7 @@ target | std | host | notes
[`riscv32imafc-esp-espidf`](platform-support/esp-idf.md) | ✓ | | RISC-V ESP-IDF
[`riscv32-wrs-vxworks`](platform-support/vxworks.md) | ✓ | |
[`riscv64gc-unknown-hermit`](platform-support/hermit.md) | ✓ | | RISC-V Hermit
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD (version 13.2)
`riscv64gc-unknown-freebsd` | | | RISC-V FreeBSD
`riscv64gc-unknown-fuchsia` | | | RISC-V Fuchsia
[`riscv64gc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | RISC-V NetBSD
[`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
@ -413,8 +414,8 @@ target | std | host | notes
[`riscv32imafc-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 32bit with NuttX
[`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 64bit with NuttX
[`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | * | | RISC-V 64bit with NuttX
[`riscv32e-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32E ISA)
[`riscv32em-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32EM ISA)
[`riscv32emc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | | Bare RISC-V (RV32EMC ISA)
[`riscv32e-unknown-none-elf`](platform-support/riscv32e-unknown-none-elf.md) | * | | Bare RISC-V (RV32E ISA)
[`riscv32em-unknown-none-elf`](platform-support/riscv32e-unknown-none-elf.md) | * | | Bare RISC-V (RV32EM ISA)
[`riscv32emc-unknown-none-elf`](platform-support/riscv32e-unknown-none-elf.md) | * | | Bare RISC-V (RV32EMC ISA)
[runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets

View file

@ -525,14 +525,6 @@ ${SDK_PATH}/tools/${ARCH}/ffx repository publish \
pkg/repo
```
Then we can add the repository to `ffx`'s package server as `hello-fuchsia` using:
```sh
${SDK_PATH}/tools/${ARCH}/ffx repository add-from-pm \
--repository hello-fuchsia \
pkg/repo
```
## Running a Fuchsia component on an emulator
At this point, we are ready to run our Fuchsia
@ -590,7 +582,8 @@ Now, start a package repository server to serve our
package to the emulator:
```sh
${SDK_PATH}/tools/${ARCH}/ffx repository server start
${SDK_PATH}/tools/${ARCH}/ffx repository server start \
--background --repository hello-fuchsia --repo-path pkg-repo
```
Once the repository server is up and running, register it with the target Fuchsia system running in the emulator:

View file

@ -35,7 +35,7 @@ The following target names are defined:
## Building the target
The target can be built by enabled in the `rustc` build:
The target can be built by enabling it in the `rustc` build:
```toml
[build]

View file

@ -132,10 +132,20 @@ As of the time of this writing the proposals that are enabled by default (the
If you're compiling WebAssembly code for an engine that does not support a
feature in LLVM's default feature set then the feature must be disabled at
compile time. Note, though, that enabled features may be used in the standard
library or precompiled libraries shipped via rustup. This means that not only
does your own code need to be compiled with the correct set of flags but the
Rust standard library additionally must be recompiled.
compile time. There are two approaches to choose from:
- If you are targeting a feature set no smaller than the W3C WebAssembly Core
1.0 recommendation -- which is equivalent to the WebAssembly MVP plus the
`mutable-globals` feature -- and you are building `no_std`, then you can
simply use the [`wasm32v1-none` target](./wasm32v1-none.md) instead of
`wasm32-unknown-unknown`, which uses only those minimal features and
includes a core and alloc library built with only those minimal features.
- Otherwise -- if you need std, or if you need to target the ultra-minimal
"MVP" feature set, excluding `mutable-globals` -- you will need to manually
specify `-Ctarget-cpu=mvp` and also rebuild the stdlib using that target to
ensure no features are used in the stdlib. This in turn requires use of a
nightly compiler.
Compiling all code for the initial release of WebAssembly looks like:
@ -150,9 +160,9 @@ then used to recompile the standard library in addition to your own code. This
will produce a binary that uses only the original WebAssembly features by
default and no proposals since its inception.
To enable individual features it can be done with `-Ctarget-feature=+foo`.
Available features for Rust code itself are documented in the [reference] and
can also be found through:
To enable individual features on either this target or `wasm32v1-none`, pass
arguments of the form `-Ctarget-feature=+foo`. Available features for Rust code
itself are documented in the [reference] and can also be found through:
```sh
$ rustc -Ctarget-feature=help --target wasm32-unknown-unknown

View file

@ -0,0 +1,109 @@
# `wasm32v1-none`
**Tier: 2**
The `wasm32v1-none` target is a WebAssembly compilation target that:
- Imports nothing from its host environment
- Enables no proposals / features past the [W3C WebAssembly Core 1.0 spec]
[W3C WebAssembly Core 1.0 spec]: https://www.w3.org/TR/wasm-core-1/
The target is very similar to [`wasm32-unknown-unknown`](./wasm32-unknown-unknown.md) and similarly uses LLVM's `wasm32-unknown-unknown` backend target. It contains only three minor differences:
* Setting the `target-cpu` to `mvp` rather than the default `generic`. Requesting `mvp` disables _all_ WebAssembly proposals / LLVM target feature flags.
* Enabling the [Import/Export of Mutable Globals] proposal (i.e. the `+mutable-globals` LLVM target feature flag)
* Not compiling the `std` library at all, rather than compiling it with stubs.
[Import/Export of Mutable Globals]: https://github.com/WebAssembly/mutable-global
## Target maintainers
- Alex Crichton, https://github.com/alexcrichton
- Graydon Hoare, https://github.com/graydon
## Requirements
This target is cross-compiled. It does not support `std`, only `core` and `alloc`. Since it imports nothing from its environment, any `std` parts that use OS facilities would be stubbed out with functions-that-fail anyways, and the experience of working with the stub `std` in the `wasm32-unknown-unknown` target was deemed not something worth repeating here.
Everything else about this target's requirements, building, usage and testing is the same as what's described in the [`wasm32-unknown-unknown` document](./wasm32-unknown-unknown.md), just using the target string `wasm32v1-none` in place of `wasm32-unknown-unknown`.
## Conditionally compiling code
It's recommended to conditionally compile code for this target with:
```text
#[cfg(all(target_family = "wasm", target_os = "none"))]
```
Note that there is no way to tell via `#[cfg]` whether code will be running on
the web or not.
## Enabled WebAssembly features
As noted above, _no WebAssembly proposals past 1.0_ are enabled on this target by default. Indeed, the entire point of this target is to have a way to compile for a stable "no post-1.0 proposals" subset of WebAssembly _on stable Rust_.
The [W3C WebAssembly Core 1.0 spec] was adopted as a W3C recommendation in December 2019, and includes exactly one "post-MVP" proposal: the [Import/Export of Mutable Globals] proposal.
All subsequent proposals are _disabled_ on this target by default, though they can be individually enabled by passing LLVM target-feature flags.
For reference sake, the set of proposals that LLVM supports at the time of writing, that this target _does not enable by default_, are listed here along with their LLVM target-feature flags:
* Post-1.0 proposals (integrated into the WebAssembly core 2.0 spec):
* [Bulk memory] - `+bulk-memory`
* [Sign-extending operations] - `+sign-ext`
* [Non-trapping fp-to-int operations] - `+nontrapping-fptoint`
* [Multi-value] - `+multivalue`
* [Reference Types] - `+reference-types`
* [Fixed-width SIMD] - `+simd128`
* Post-2.0 proposals:
* [Threads] (supported by atomics) - `+atomics`
* [Exception handling] - `+exception-handling`
* [Extended Constant Expressions] - `+extended-const`
* [Half Precision] - `+half-precision`
* [Multiple memories]- `+multimemory`
* [Relaxed SIMD] - `+relaxed-simd`
* [Tail call] - `+tail-call`
[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
[Sign-extending operations]: https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
[Non-trapping fp-to-int operations]: https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
[Multi-value]: https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
[Reference Types]: https://github.com/WebAssembly/spec/blob/main/proposals/reference-types/Overview.md
[Fixed-width SIMD]: https://github.com/WebAssembly/spec/blob/main/proposals/simd/SIMD.md
[Threads]: https://github.com/webassembly/threads
[Exception handling]: https://github.com/WebAssembly/exception-handling
[Extended Constant Expressions]: https://github.com/WebAssembly/extended-const
[Half Precision]: https://github.com/WebAssembly/half-precision
[Multiple memories]: https://github.com/WebAssembly/multi-memory
[Relaxed SIMD]: https://github.com/WebAssembly/relaxed-simd
[Tail call]: https://github.com/WebAssembly/tail-call
Additional proposals in the future are, of course, also not enabled by default.
## Rationale relative to wasm32-unknown-unknown
As noted in the [`wasm32-unknown-unknown` document](./wasm32-unknown-unknown.md), it is possible to compile with `--target wasm32-unknown-unknown` and disable all WebAssembly proposals "by hand", by passing `-Ctarget-cpu=mvp`. Furthermore one can enable proposals one by one by passing LLVM target feature flags, such as `-Ctarget-feature=+mutable-globals`.
Is it therefore reasonable to wonder what the difference is between building with this:
```sh
$ rustc --target wasm32-unknown-unknown -Ctarget-cpu=mvp -Ctarget-feature=+mutable-globals
```
and building with this:
```sh
$ rustc --target wasm32v1-none
```
The difference is in how the `core` and `alloc` crates are compiled for distribution with the toolchain, and whether it works on _stable_ Rust toolchains or requires _nightly_ ones. Again referring back to the [`wasm32-unknown-unknown` document](./wasm32-unknown-unknown.md), note that to disable all post-MVP proposals on that target one _actually_ has to compile with this:
```sh
$ export RUSTFLAGS="-Ctarget-cpu=mvp -Ctarget-feature=+mutable-globals"
$ cargo +nightly build -Zbuild-std=panic_abort,std --target wasm32-unknown-unknown
```
Which not only rebuilds `std`, `core` and `alloc` (which is somewhat costly and annoying) but more importantly requires the use of nightly Rust toolchains (for the `-Zbuild-std` flag). This is very undesirable for the target audience, which consists of people targeting WebAssembly implementations that prioritize stability, simplicity and/or security over feature support.
This `wasm32v1-none` target exists as an alternative option that works on stable Rust toolchains, without rebuilding the stdlib.

View file

@ -1208,7 +1208,7 @@ The compiler has some latitude in how an entity is encoded as long as the symbol
* Named functions, methods, and statics shall be represented by a *[path]* production.
* Paths should be rooted at the inner-most entity that can act as a path root.
* Paths should be rooted at the innermost entity that can act as a path root.
Roots can be crate-ids, inherent impls, trait impls, and (for items within default methods) trait definitions.
* The compiler is free to choose disambiguation indices and namespace tags from

View file

@ -0,0 +1,20 @@
# `regparm`
The tracking issue for this feature is: https://github.com/rust-lang/rust/issues/131749.
------------------------
Option -Zregparm=N causes the compiler to pass N arguments
in registers EAX, EDX, and ECX instead of on the stack for "C", "cdecl", and "stdcall" fn.
It is UNSOUND to link together crates that use different values for this flag.
It is only supported on `x86`.
It is equivalent to [Clang]'s and [GCC]'s `-mregparm`.
Supported values for this option are 0-3.
[Clang]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-mregparm
[GCC]: https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#index-regparm-function-attribute_002c-x86
Implementation details:
For eligible arguments, llvm `inreg` attribute is set.

View file

@ -690,7 +690,6 @@ LeakSanitizer is run-time memory leak detector.
LeakSanitizer is supported on the following targets:
* `aarch64-apple-darwin`
* `aarch64-unknown-linux-gnu`
* `x86_64-apple-darwin`
* `x86_64-unknown-linux-gnu`

View file

@ -33,7 +33,6 @@ while getopts ':vieh' OPTION; do
case "$OPTION" in
v)
INVERT=1
ERROR_MSG='should not be found'
;;
i)
GREPFLAGS="i$GREPFLAGS"

View file

@ -250,7 +250,7 @@ def get_known_directive_names():
os.path.join(
# We go back to `src`.
os.path.dirname(os.path.dirname(__file__)),
"tools/compiletest/src/command-list.rs",
"tools/compiletest/src/directive-list.rs",
),
"r",
encoding="utf8"

View file

@ -2,6 +2,7 @@
name = "rustdoc"
version = "0.0.0"
edition = "2021"
build = "build.rs"
[lib]
path = "lib.rs"
@ -24,13 +25,15 @@ tracing = "0.1"
tracing-tree = "0.3.0"
threadpool = "1.8.1"
unicode-segmentation = "1.9"
sha2 = "0.10.8"
[dependencies.tracing-subscriber]
version = "0.3.3"
default-features = false
features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"]
[build-dependencies]
sha2 = "0.10.8"
[dev-dependencies]
expect-test = "1.4.0"

48
src/librustdoc/build.rs Normal file
View file

@ -0,0 +1,48 @@
fn main() {
// generate sha256 files
// this avoids having to perform hashing at runtime
let files = &[
"static/css/rustdoc.css",
"static/css/noscript.css",
"static/css/normalize.css",
"static/js/main.js",
"static/js/search.js",
"static/js/settings.js",
"static/js/src-script.js",
"static/js/storage.js",
"static/js/scrape-examples.js",
"static/COPYRIGHT.txt",
"static/LICENSE-APACHE.txt",
"static/LICENSE-MIT.txt",
"static/images/rust-logo.svg",
"static/images/favicon.svg",
"static/images/favicon-32x32.png",
"static/fonts/FiraSans-Regular.woff2",
"static/fonts/FiraSans-Medium.woff2",
"static/fonts/FiraSans-LICENSE.txt",
"static/fonts/SourceSerif4-Regular.ttf.woff2",
"static/fonts/SourceSerif4-Bold.ttf.woff2",
"static/fonts/SourceSerif4-It.ttf.woff2",
"static/fonts/SourceSerif4-LICENSE.md",
"static/fonts/SourceCodePro-Regular.ttf.woff2",
"static/fonts/SourceCodePro-Semibold.ttf.woff2",
"static/fonts/SourceCodePro-It.ttf.woff2",
"static/fonts/SourceCodePro-LICENSE.txt",
"static/fonts/NanumBarunGothic.ttf.woff2",
"static/fonts/NanumBarunGothic-LICENSE.txt",
];
let out_dir = std::env::var("OUT_DIR").expect("standard Cargo environment variable");
for path in files {
let inpath = format!("html/{path}");
println!("cargo::rerun-if-changed={inpath}");
let bytes = std::fs::read(inpath).expect("static path exists");
use sha2::Digest;
let bytes = sha2::Sha256::digest(bytes);
let mut digest = format!("-{bytes:x}");
digest.truncate(9);
let outpath = std::path::PathBuf::from(format!("{out_dir}/{path}.sha256"));
std::fs::create_dir_all(outpath.parent().expect("all file paths are in a directory"))
.expect("should be able to write to out_dir");
std::fs::write(&outpath, digest.as_bytes()).expect("write to out_dir");
}
}

View file

@ -156,7 +156,7 @@ fn clean_param_env<'tcx>(
.iter()
.inspect(|param| {
if cfg!(debug_assertions) {
debug_assert!(!param.is_anonymous_lifetime() && !param.is_host_effect());
debug_assert!(!param.is_anonymous_lifetime());
if let ty::GenericParamDefKind::Type { synthetic, .. } = param.kind {
debug_assert!(!synthetic && param.name != kw::SelfUpper);
}

View file

@ -248,9 +248,7 @@ pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemT
// Check to see if it is a macro 2.0 or built-in macro
if matches!(
CStore::from_tcx(cx.tcx).load_macro_untracked(did, cx.tcx),
LoadedMacro::MacroDef(def, _)
if matches!(&def.kind, ast::ItemKind::MacroDef(ast_def)
if !ast_def.macro_rules)
LoadedMacro::MacroDef { def, .. } if !def.macro_rules
) {
once(crate_name).chain(relative).collect()
} else {
@ -747,24 +745,12 @@ fn build_macro(
is_doc_hidden: bool,
) -> clean::ItemKind {
match CStore::from_tcx(cx.tcx).load_macro_untracked(def_id, cx.tcx) {
LoadedMacro::MacroDef(item_def, _) => match macro_kind {
LoadedMacro::MacroDef { def, .. } => match macro_kind {
MacroKind::Bang => {
if let ast::ItemKind::MacroDef(ref def) = item_def.kind {
let vis =
cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
clean::MacroItem(clean::Macro {
source: utils::display_macro_source(
cx,
name,
def,
def_id,
vis,
is_doc_hidden,
),
})
} else {
unreachable!()
}
let vis = cx.tcx.visibility(import_def_id.map(|d| d.to_def_id()).unwrap_or(def_id));
clean::MacroItem(clean::Macro {
source: utils::display_macro_source(cx, name, &def, def_id, vis, is_doc_hidden),
})
}
MacroKind::Derive | MacroKind::Attr => {
clean::ProcMacroItem(clean::ProcMacro { kind: macro_kind, helpers: Vec::new() })

View file

@ -216,7 +216,7 @@ fn clean_generic_bound<'tcx>(
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
hir::GenericBound::Trait(ref t) => {
// `T: ~const Destruct` is hidden because `T: Destruct` is a no-op.
if t.modifiers == hir::TraitBoundModifier::MaybeConst
if let hir::BoundConstness::Maybe(_) = t.modifiers.constness
&& cx.tcx.lang_items().destruct_trait() == Some(t.trait_ref.trait_def_id().unwrap())
{
return None;
@ -263,7 +263,7 @@ fn clean_poly_trait_ref_with_constraints<'tcx>(
trait_: clean_trait_ref_with_constraints(cx, poly_trait_ref, constraints),
generic_params: clean_bound_vars(poly_trait_ref.bound_vars()),
},
hir::TraitBoundModifier::None,
hir::TraitBoundModifiers::NONE,
)
}
@ -368,7 +368,9 @@ pub(crate) fn clean_predicate<'tcx>(
// FIXME(generic_const_exprs): should this do something?
ty::ClauseKind::ConstEvaluatable(..)
| ty::ClauseKind::WellFormed(..)
| ty::ClauseKind::ConstArgHasType(..) => None,
| ty::ClauseKind::ConstArgHasType(..)
// FIXME(effects): We can probably use this `HostEffect` pred to render `~const`.
| ty::ClauseKind::HostEffect(_) => None,
}
}
@ -542,7 +544,7 @@ fn clean_generic_param_def(
synthetic,
})
}
ty::GenericParamDefKind::Const { has_default, synthetic, is_host_effect: _ } => {
ty::GenericParamDefKind::Const { has_default, synthetic } => {
(def.name, GenericParamDefKind::Const {
ty: Box::new(clean_middle_ty(
ty::Binder::dummy(
@ -617,7 +619,7 @@ fn clean_generic_param<'tcx>(
synthetic,
})
}
hir::GenericParamKind::Const { ty, default, synthetic, is_host_effect: _ } => {
hir::GenericParamKind::Const { ty, default, synthetic } => {
(param.name.ident().name, GenericParamDefKind::Const {
ty: Box::new(clean_ty(ty, cx)),
default: default.map(|ct| {
@ -797,7 +799,7 @@ fn clean_ty_generics<'tcx>(
}
true
}
ty::GenericParamDefKind::Const { is_host_effect, .. } => !is_host_effect,
ty::GenericParamDefKind::Const { .. } => true,
})
.map(|param| clean_generic_param_def(param, ParamDefaults::Yes, cx))
.collect();
@ -1398,7 +1400,6 @@ pub(crate) fn clean_middle_assoc_item(assoc_item: &ty::AssocItem, cx: &mut DocCo
clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), ty::GenericPredicates {
parent: None,
predicates,
effects_min_tys: ty::List::empty(),
});
simplify::move_bounds_to_generic_parameters(&mut generics);
@ -2189,7 +2190,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
ty::Alias(ty::Weak, data) => {
if cx.tcx.features().lazy_type_alias {
if cx.tcx.features().lazy_type_alias() {
// Weak type alias `data` represents the `type X` in `type X = Y`. If we need `Y`,
// we need to use `type_of`.
let path = clean_middle_path(

View file

@ -8,7 +8,6 @@ use arrayvec::ArrayVec;
use rustc_ast::MetaItemInner;
use rustc_ast_pretty::pprust;
use rustc_attr::{ConstStability, Deprecation, Stability, StableSince};
use rustc_const_eval::const_eval::is_unstable_const_fn;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
@ -641,12 +640,11 @@ impl Item {
asyncness: ty::Asyncness,
) -> hir::FnHeader {
let sig = tcx.fn_sig(def_id).skip_binder();
let constness =
if tcx.is_const_fn(def_id) || is_unstable_const_fn(tcx, def_id).is_some() {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
let constness = if tcx.is_const_fn(def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
let asyncness = match asyncness {
ty::Asyncness::Yes => hir::IsAsync::Async(DUMMY_SP),
ty::Asyncness::No => hir::IsAsync::NotAsync,
@ -664,9 +662,7 @@ impl Item {
safety
},
abi,
constness: if tcx.is_const_fn(def_id)
|| is_unstable_const_fn(tcx, def_id).is_some()
{
constness: if tcx.is_const_fn(def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
@ -966,8 +962,8 @@ pub(crate) trait AttributesExt {
fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
let sess = tcx.sess;
let doc_cfg_active = tcx.features().doc_cfg;
let doc_auto_cfg_active = tcx.features().doc_auto_cfg;
let doc_cfg_active = tcx.features().doc_cfg();
let doc_auto_cfg_active = tcx.features().doc_auto_cfg();
fn single<T: IntoIterator>(it: T) -> Option<T::Item> {
let mut iter = it.into_iter();
@ -1257,7 +1253,7 @@ impl Eq for Attributes {}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub(crate) enum GenericBound {
TraitBound(PolyTrait, hir::TraitBoundModifier),
TraitBound(PolyTrait, hir::TraitBoundModifiers),
Outlives(Lifetime),
/// `use<'a, T>` precise-capturing bound syntax
Use(Vec<Symbol>),
@ -1265,19 +1261,22 @@ pub(crate) enum GenericBound {
impl GenericBound {
pub(crate) fn sized(cx: &mut DocContext<'_>) -> GenericBound {
Self::sized_with(cx, hir::TraitBoundModifier::None)
Self::sized_with(cx, hir::TraitBoundModifiers::NONE)
}
pub(crate) fn maybe_sized(cx: &mut DocContext<'_>) -> GenericBound {
Self::sized_with(cx, hir::TraitBoundModifier::Maybe)
Self::sized_with(cx, hir::TraitBoundModifiers {
polarity: hir::BoundPolarity::Maybe(DUMMY_SP),
constness: hir::BoundConstness::Never,
})
}
fn sized_with(cx: &mut DocContext<'_>, modifier: hir::TraitBoundModifier) -> GenericBound {
fn sized_with(cx: &mut DocContext<'_>, modifiers: hir::TraitBoundModifiers) -> GenericBound {
let did = cx.tcx.require_lang_item(LangItem::Sized, None);
let empty = ty::Binder::dummy(ty::GenericArgs::empty());
let path = clean_middle_path(cx, did, false, ThinVec::new(), empty);
inline::record_extern_fqn(cx, did, ItemType::Trait);
GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifier)
GenericBound::TraitBound(PolyTrait { trait_: path, generic_params: Vec::new() }, modifiers)
}
pub(crate) fn is_trait_bound(&self) -> bool {
@ -1285,8 +1284,10 @@ impl GenericBound {
}
pub(crate) fn is_sized_bound(&self, cx: &DocContext<'_>) -> bool {
use rustc_hir::TraitBoundModifier as TBM;
if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self
if let GenericBound::TraitBound(
PolyTrait { ref trait_, .. },
rustc_hir::TraitBoundModifiers::NONE,
) = *self
&& Some(trait_.def_id()) == cx.tcx.lang_items().sized_trait()
{
return true;
@ -1361,8 +1362,7 @@ impl GenericParamDef {
pub(crate) fn is_synthetic_param(&self) -> bool {
match self.kind {
GenericParamDefKind::Lifetime { .. } => false,
GenericParamDefKind::Const { synthetic: is_host_effect, .. } => is_host_effect,
GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
GenericParamDefKind::Type { synthetic, .. } => synthetic,
}
}

View file

@ -114,10 +114,6 @@ pub(crate) fn clean_middle_generic_args<'tcx>(
// Elide internal host effect args.
let param = generics.param_at(index, cx.tcx);
if param.is_host_effect() {
return None;
}
let arg = ty::Binder::bind_with_vars(arg, bound_vars);
// Elide arguments that coincide with their default.

View file

@ -8,7 +8,7 @@ use rustc_data_structures::unord::UnordSet;
use rustc_errors::codes::*;
use rustc_errors::emitter::{DynEmitter, HumanEmitter, stderr_destination};
use rustc_errors::json::JsonEmitter;
use rustc_errors::{DiagCtxtHandle, ErrorGuaranteed, TerminalUrl};
use rustc_errors::{ErrorGuaranteed, TerminalUrl};
use rustc_feature::UnstableFeatures;
use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
@ -21,8 +21,8 @@ use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks};
pub(crate) use rustc_session::config::{Options, UnstableOptions};
use rustc_session::{Session, lint};
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::{Span, source_map};
use tracing::{debug, info};
use crate::clean::inline::build_external_trait;
@ -381,45 +381,10 @@ pub(crate) fn run_global_ctxt(
);
}
fn report_deprecated_attr(name: &str, dcx: DiagCtxtHandle<'_>, sp: Span) {
let mut msg =
dcx.struct_span_warn(sp, format!("the `#![doc({name})]` attribute is deprecated"));
msg.note(
"see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
for more information",
);
if name == "no_default_passes" {
msg.help("`#![doc(no_default_passes)]` no longer functions; you may want to use `#![doc(document_private_items)]`");
} else if name.starts_with("passes") {
msg.help("`#![doc(passes = \"...\")]` no longer functions; you may want to use `#![doc(document_private_items)]`");
} else if name.starts_with("plugins") {
msg.warn("`#![doc(plugins = \"...\")]` no longer functions; see CVE-2018-1000622 <https://nvd.nist.gov/vuln/detail/CVE-2018-1000622>");
}
msg.emit();
}
// Process all of the crate attributes, extracting plugin metadata along
// with the passes which we are supposed to run.
for attr in krate.module.attrs.lists(sym::doc) {
let dcx = ctxt.sess().dcx();
let name = attr.name_or_empty();
// `plugins = "..."`, `no_default_passes`, and `passes = "..."` have no effect
if attr.is_word() && name == sym::no_default_passes {
report_deprecated_attr("no_default_passes", dcx, attr.span());
} else if attr.value_str().is_some() {
match name {
sym::passes => {
report_deprecated_attr("passes = \"...\"", dcx, attr.span());
}
sym::plugins => {
report_deprecated_attr("plugins = \"...\"", dcx, attr.span());
}
_ => (),
}
}
if attr.is_word() && name == sym::document_private_items {
ctxt.render_options.document_private = true;

View file

@ -289,7 +289,12 @@ fn parse_source(
// Recurse through functions body. It is necessary because the doctest source code is
// wrapped in a function to limit the number of AST errors. If we don't recurse into
// functions, we would thing all top-level items (so basically nothing).
fn check_item(item: &ast::Item, info: &mut ParseSourceInfo, crate_name: &Option<&str>) {
fn check_item(
item: &ast::Item,
info: &mut ParseSourceInfo,
crate_name: &Option<&str>,
is_top_level: bool,
) {
if !info.has_global_allocator
&& item.attrs.iter().any(|attr| attr.name_or_empty() == sym::global_allocator)
{
@ -297,13 +302,15 @@ fn parse_source(
}
match item.kind {
ast::ItemKind::Fn(ref fn_item) if !info.has_main_fn => {
if item.ident.name == sym::main {
if item.ident.name == sym::main && is_top_level {
info.has_main_fn = true;
}
if let Some(ref body) = fn_item.body {
for stmt in &body.stmts {
match stmt.kind {
ast::StmtKind::Item(ref item) => check_item(item, info, crate_name),
ast::StmtKind::Item(ref item) => {
check_item(item, info, crate_name, false)
}
ast::StmtKind::MacCall(..) => info.found_macro = true,
_ => {}
}
@ -329,7 +336,7 @@ fn parse_source(
loop {
match parser.parse_item(ForceCollect::No) {
Ok(Some(item)) => {
check_item(&item, info, crate_name);
check_item(&item, info, crate_name, true);
if info.has_main_fn && info.found_extern_crate {
break;

View file

@ -16,6 +16,7 @@ use itertools::Itertools;
use rustc_attr::{ConstStability, StabilityLevel, StableSince};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_metadata::creader::{CStore, LoadedMacro};
@ -25,7 +26,6 @@ use rustc_span::symbol::kw;
use rustc_span::{Symbol, sym};
use rustc_target::spec::abi::Abi;
use tracing::{debug, trace};
use {rustc_ast as ast, rustc_hir as hir};
use super::url_parts_builder::{UrlPartsBuilder, estimate_item_path_byte_length};
use crate::clean::types::ExternalLocation;
@ -399,13 +399,13 @@ impl clean::GenericBound {
) -> impl Display + 'a + Captures<'tcx> {
display_fn(move |f| match self {
clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
clean::GenericBound::TraitBound(ty, modifier) => {
f.write_str(match modifier {
hir::TraitBoundModifier::None => "",
hir::TraitBoundModifier::Maybe => "?",
hir::TraitBoundModifier::Negative => "!",
// `const` and `~const` trait bounds are experimental; don't render them.
hir::TraitBoundModifier::Const | hir::TraitBoundModifier::MaybeConst => "",
clean::GenericBound::TraitBound(ty, modifiers) => {
// `const` and `~const` trait bounds are experimental; don't render them.
let hir::TraitBoundModifiers { polarity, constness: _ } = modifiers;
f.write_str(match polarity {
hir::BoundPolarity::Positive => "",
hir::BoundPolarity::Maybe(_) => "?",
hir::BoundPolarity::Negative(_) => "!",
})?;
ty.print(cx).fmt(f)
}
@ -554,10 +554,8 @@ fn generate_macro_def_id_path(
// Check to see if it is a macro 2.0 or built-in macro.
// More information in <https://rust-lang.github.io/rfcs/1584-macros.html>.
let is_macro_2 = match cstore.load_macro_untracked(def_id, tcx) {
LoadedMacro::MacroDef(def, _) => {
// If `ast_def.macro_rules` is `true`, then it's not a macro 2.0.
matches!(&def.kind, ast::ItemKind::MacroDef(ast_def) if !ast_def.macro_rules)
}
// If `def.macro_rules` is `true`, then it's not a macro 2.0.
LoadedMacro::MacroDef { def, .. } => !def.macro_rules,
_ => false,
};
@ -1368,6 +1366,24 @@ impl clean::Impl {
write!(f, " -> ")?;
fmt_type(&bare_fn.decl.output, f, use_absolute, cx)?;
}
} else if let clean::Type::Path { path } = type_
&& let Some(generics) = path.generics()
&& generics.len() == 1
&& self.kind.is_fake_variadic()
{
let ty = generics[0];
let wrapper = anchor(path.def_id(), path.last(), cx);
if f.alternate() {
write!(f, "{wrapper:#}&lt;")?;
} else {
write!(f, "{wrapper}<")?;
}
self.print_type(ty, f, use_absolute, cx)?;
if f.alternate() {
write!(f, "&gt;")?;
} else {
write!(f, ">")?;
}
} else {
fmt_type(&type_, f, use_absolute, cx)?;
}

View file

@ -1010,7 +1010,9 @@ fn render_stability_since_raw_with_extra(
// don't display const unstable if entirely unstable
None
} else {
let unstable = if let Some(n) = issue {
let unstable = if let Some(n) = issue
&& let Some(feature) = feature
{
format!(
"<a \
href=\"https://github.com/rust-lang/rust/issues/{n}\" \
@ -2010,9 +2012,9 @@ fn render_rightside(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, render
);
if let Some(link) = src_href {
if has_stability {
write!(rightside, " · <a class=\"src\" href=\"{link}\">source</a>")
write!(rightside, " · <a class=\"src\" href=\"{link}\">Source</a>")
} else {
write!(rightside, "<a class=\"src rightside\" href=\"{link}\">source</a>")
write!(rightside, "<a class=\"src rightside\" href=\"{link}\">Source</a>")
}
}
if has_stability && has_src_ref {

View file

@ -759,7 +759,10 @@ pub(crate) fn get_function_type_for_search<'tcx>(
}
});
let (mut inputs, mut output, where_clause) = match item.kind {
clean::FunctionItem(ref f) | clean::MethodItem(ref f, _) | clean::TyMethodItem(ref f) => {
clean::ForeignFunctionItem(ref f, _)
| clean::FunctionItem(ref f)
| clean::MethodItem(ref f, _)
| clean::TyMethodItem(ref f) => {
get_fn_inputs_and_outputs(f, tcx, impl_or_trait_generics, cache)
}
_ => return None,

View file

@ -60,8 +60,8 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
span_bug!(tcx.def_span(ty_def_id), "not an adt")
};
let name = adt.variant(variant_idx).name;
let is_unsized = variant_layout.abi.is_unsized();
let is_uninhabited = variant_layout.abi.is_uninhabited();
let is_unsized = variant_layout.is_unsized();
let is_uninhabited = variant_layout.is_uninhabited();
let size = variant_layout.size.bytes() - tag_size;
let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size };
(name, type_layout_size)
@ -72,8 +72,8 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>(
};
let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| {
let is_unsized = layout.abi.is_unsized();
let is_uninhabited = layout.abi.is_uninhabited();
let is_unsized = layout.is_unsized();
let is_uninhabited = layout.is_uninhabited();
let size = layout.size.bytes();
TypeLayoutSize { is_unsized, is_uninhabited, size }
});

View file

@ -112,7 +112,7 @@ pub(crate) fn write_shared(
md_opts.output = cx.dst.clone();
md_opts.external_html = cx.shared.layout.external_html.clone();
try_err!(
crate::markdown::render(&index_page, md_opts, cx.shared.edition()),
crate::markdown::render_and_write(&index_page, md_opts, cx.shared.edition()),
&index_page
);
}

View file

@ -185,7 +185,7 @@ h1, h2, h3, h4 {
grid-template-columns: minmax(105px, 1fr) minmax(0, max-content);
grid-template-rows: minmax(25px, min-content) min-content min-content;
padding-bottom: 6px;
margin-bottom: 11px;
margin-bottom: 15px;
}
.rustdoc-breadcrumbs {
grid-area: main-heading-breadcrumbs;
@ -230,7 +230,7 @@ h4.code-header {
padding: 0;
white-space: pre-wrap;
}
.structfield {
.structfield, .sub-variant-field {
margin: 0.6em 0;
}
@ -959,7 +959,7 @@ pre, .rustdoc.src .example-wrap, .example-wrap .src-line-numbers {
background: var(--table-alt-row-background-color);
}
.docblock .stab, .docblock-short .stab {
.docblock .stab, .docblock-short .stab, .docblock p code {
display: inline-block;
}
@ -1004,6 +1004,7 @@ nav.sub {
display: flex;
height: 34px;
flex-grow: 1;
margin-bottom: 4px;
}
.src nav.sub {
margin: 0 0 -10px 0;
@ -2253,7 +2254,12 @@ in src-script.js and main.js
/* We don't display this button on mobile devices. */
#copy-path {
display: none;
/* display: none; avoided as a layout hack.
When there's one line, we get an effective line-height of 34px,
because that's how big the image is, but if the header wraps,
they're packed more tightly than that. */
width: 0;
visibility: hidden;
}
/* Text label takes up too much space at this size. */

View file

@ -12,8 +12,8 @@ pub(crate) struct StaticFile {
}
impl StaticFile {
fn new(filename: &str, bytes: &'static [u8]) -> StaticFile {
Self { filename: static_filename(filename, bytes), bytes }
fn new(filename: &str, bytes: &'static [u8], sha256: &'static str) -> StaticFile {
Self { filename: static_filename(filename, sha256), bytes }
}
pub(crate) fn minified(&self) -> Vec<u8> {
@ -55,17 +55,9 @@ pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf {
filename.into()
}
pub(crate) fn static_filename(filename: &str, contents: &[u8]) -> PathBuf {
pub(crate) fn static_filename(filename: &str, sha256: &str) -> PathBuf {
let filename = filename.rsplit('/').next().unwrap();
suffix_path(filename, &static_suffix(contents))
}
fn static_suffix(bytes: &[u8]) -> String {
use sha2::Digest;
let bytes = sha2::Sha256::digest(bytes);
let mut digest = format!("-{bytes:x}");
digest.truncate(9);
digest
suffix_path(filename, &sha256)
}
macro_rules! static_files {
@ -74,8 +66,9 @@ macro_rules! static_files {
$(pub $field: StaticFile,)+
}
// sha256 files are generated in build.rs
pub(crate) static STATIC_FILES: std::sync::LazyLock<StaticFiles> = std::sync::LazyLock::new(|| StaticFiles {
$($field: StaticFile::new($file_path, include_bytes!($file_path)),)+
$($field: StaticFile::new($file_path, include_bytes!($file_path), include_str!(concat!(env!("OUT_DIR"), "/", $file_path, ".sha256"))),)+
});
pub(crate) fn for_each<E>(f: impl Fn(&StaticFile) -> Result<(), E>) -> Result<(), E> {

View file

@ -26,7 +26,7 @@
{% match src_href %}
{% when Some with (href) %}
{% if !stability_since_raw.is_empty() +%} · {%+ endif %}
<a class="src" href="{{href|safe}}">source</a> {#+ #}
<a class="src" href="{{href|safe}}">Source</a> {#+ #}
{% else %}
{% endmatch %}
</span> {# #}

View file

@ -552,20 +552,18 @@ impl FromClean<clean::GenericBound> for GenericBound {
}
pub(crate) fn from_trait_bound_modifier(
modifier: rustc_hir::TraitBoundModifier,
modifiers: rustc_hir::TraitBoundModifiers,
) -> TraitBoundModifier {
use rustc_hir::TraitBoundModifier::*;
match modifier {
None => TraitBoundModifier::None,
Maybe => TraitBoundModifier::Maybe,
MaybeConst => TraitBoundModifier::MaybeConst,
// FIXME(const_trait_impl): Create rjt::TBM::Const and map to it once always-const bounds
// are less experimental.
Const => TraitBoundModifier::None,
// FIXME(negative-bounds): This bound should be rendered negative, but
// since that's experimental, maybe let's not add it to the rustdoc json
// API just now...
Negative => TraitBoundModifier::None,
use rustc_hir as hir;
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
match (constness, polarity) {
(hir::BoundConstness::Never, hir::BoundPolarity::Positive) => TraitBoundModifier::None,
(hir::BoundConstness::Never, hir::BoundPolarity::Maybe(_)) => TraitBoundModifier::Maybe,
(hir::BoundConstness::Maybe(_), hir::BoundPolarity::Positive) => {
TraitBoundModifier::MaybeConst
}
// FIXME: Fill out the rest of this matrix.
_ => TraitBoundModifier::None,
}
}

View file

@ -37,7 +37,6 @@ extern crate rustc_abi;
extern crate rustc_ast;
extern crate rustc_ast_pretty;
extern crate rustc_attr;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_errors;
@ -817,7 +816,7 @@ fn main_args(
return wrap_return(
dcx,
interface::run_compiler(config, |_compiler| {
markdown::render(&md_input, render_options, edition)
markdown::render_and_write(&md_input, render_options, edition)
}),
);
}

View file

@ -31,9 +31,9 @@ where
allowed_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
let lints = || {
lint::builtin::HardwiredLints::get_lints()
lint::builtin::HardwiredLints::lint_vec()
.into_iter()
.chain(rustc_lint::SoftLints::get_lints())
.chain(rustc_lint::SoftLints::lint_vec())
};
let lint_opts = lints()

View file

@ -1,3 +1,13 @@
//! Standalone markdown rendering.
//!
//! For the (much more common) case of rendering markdown in doc-comments, see
//! [crate::html::markdown].
//!
//! This is used when [rendering a markdown file to an html file][docs], without processing
//! rust source code.
//!
//! [docs]: https://doc.rust-lang.org/stable/rustdoc/#using-standalone-markdown-files
use std::fmt::Write as _;
use std::fs::{File, create_dir_all, read_to_string};
use std::io::prelude::*;
@ -33,7 +43,7 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
/// (e.g., output = "bar" => "bar/foo.html").
///
/// Requires session globals to be available, for symbol interning.
pub(crate) fn render<P: AsRef<Path>>(
pub(crate) fn render_and_write<P: AsRef<Path>>(
input: P,
options: RenderOptions,
edition: Edition,

View file

@ -116,7 +116,7 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
find_testable_code(dox, &mut tests, ErrorCodes::No, false, None);
if tests.found_tests == 0 && cx.tcx.features().rustdoc_missing_doc_code_examples {
if tests.found_tests == 0 && cx.tcx.features().rustdoc_missing_doc_code_examples() {
if should_have_doc_example(cx, item) {
debug!("reporting error for {item:?} (hir_id={hir_id:?})");
let sp = item.attr_span(cx.tcx);

View file

@ -1419,7 +1419,7 @@ impl LinkCollector<'_, '_> {
&& key.path_str.contains("::")
// We only want to check this if this is an associated item.
{
if key.item_id.is_local() && !self.cx.tcx.features().intra_doc_pointers {
if key.item_id.is_local() && !self.cx.tcx.features().intra_doc_pointers() {
self.report_rawptr_assoc_feature_gate(diag.dox, &diag.link_range, diag.item);
return None;
} else {

View file

@ -161,6 +161,7 @@ static TARGETS: &[&str] = &[
"wasm32-wasip1",
"wasm32-wasip1-threads",
"wasm32-wasip2",
"wasm32v1-none",
"x86_64-apple-darwin",
"x86_64-apple-ios",
"x86_64-apple-ios-macabi",

@ -1 +1 @@
Subproject commit cf53cc54bb593b5ec3dc2be4b1702f50c36d24d5
Subproject commit e75214ea4936d2f2c909a71a1237042cc0e14b07

View file

@ -31,6 +31,7 @@ declare_clippy_lint! {
pub COGNITIVE_COMPLEXITY,
nursery,
"functions that should be split up into multiple functions"
@eval_always = true
}
pub struct CognitiveComplexity {

View file

@ -0,0 +1,40 @@
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl};
use rustc_lint::Level::Deny;
use rustc_lint::{LateContext, LateLintPass, Lint};
use rustc_session::declare_lint_pass;
use rustc_span::Span;
/// Ensures that Constant-time Function Evaluation is being done (specifically, MIR lint passes).
/// As Clippy deactivates codegen, this lint ensures that CTFE (used in hard errors) is still ran.
pub static CLIPPY_CTFE: &Lint = &Lint {
name: &"clippy::CLIPPY_CTFE",
default_level: Deny,
desc: "Ensure CTFE is being made",
edition_lint_opts: None,
report_in_external_macro: true,
future_incompatible: None,
is_externally_loaded: true,
crate_level_only: false,
eval_always: true,
..Lint::default_fields_for_macro()
};
// No static CLIPPY_CTFE_INFO because we want this lint to be invisible
declare_lint_pass! { ClippyCtfe => [CLIPPY_CTFE] }
impl<'tcx> LateLintPass<'tcx> for ClippyCtfe {
fn check_fn(
&mut self,
cx: &LateContext<'_>,
_: FnKind<'tcx>,
_: &'tcx FnDecl<'tcx>,
_: &'tcx Body<'tcx>,
_: Span,
defid: LocalDefId,
) {
cx.tcx.ensure().mir_drops_elaborated_and_const_checked(defid); // Lint
}
}

View file

@ -9,6 +9,7 @@ macro_rules! declare_clippy_lint {
$desc:literal,
$version_expr:expr,
$version_lit:literal
$(, $eval_always: literal)?
) => {
rustc_session::declare_tool_lint! {
$(#[doc = $lit])*
@ -17,6 +18,7 @@ macro_rules! declare_clippy_lint {
$category,
$desc,
report_in_external_macro:true
$(, @eval_always = $eval_always)?
}
pub(crate) static ${concat($lint_name, _INFO)}: &'static crate::LintInfo = &crate::LintInfo {
@ -33,11 +35,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
restriction,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Allow, crate::LintCategory::Restriction, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};
(
@ -46,12 +49,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
style,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Warn, crate::LintCategory::Style, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};
(
@ -60,11 +63,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
correctness,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Deny, crate::LintCategory::Correctness, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};
@ -74,11 +78,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
perf,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Warn, crate::LintCategory::Perf, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};
(
@ -87,11 +92,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
complexity,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Warn, crate::LintCategory::Complexity, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};
(
@ -100,11 +106,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
suspicious,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Warn, crate::LintCategory::Suspicious, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};
(
@ -113,11 +120,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
nursery,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Allow, crate::LintCategory::Nursery, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};
(
@ -126,11 +134,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
pedantic,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Allow, crate::LintCategory::Pedantic, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};
(
@ -139,11 +148,12 @@ macro_rules! declare_clippy_lint {
pub $lint_name:ident,
cargo,
$desc:literal
$(@eval_always = $eval_always: literal)?
) => {
declare_clippy_lint! {@
$(#[doc = $lit])*
pub $lint_name, Allow, crate::LintCategory::Cargo, $desc,
Some($version), $version
Some($version), $version $(, $eval_always)?
}
};

View file

@ -166,7 +166,7 @@ declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[
#[clippy::version = ""]
("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
#[clippy::version = ""]
("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
("clippy::temporary_cstring_as_ptr", "dangling_pointers_from_temporaries"),
#[clippy::version = ""]
("clippy::undropped_manually_drops", "undropped_manually_drops"),
#[clippy::version = ""]

View file

@ -324,7 +324,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
// If the current self type doesn't implement Copy (due to generic constraints), search to see if
// there's a Copy impl for any instance of the adt.
if !is_copy(cx, ty) {
if ty_subs.non_erasable_generics(cx.tcx, ty_adt.did()).next().is_some() {
if ty_subs.non_erasable_generics().next().is_some() {
let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).map_or(false, |impls| {
impls.iter().any(|&id| {
matches!(cx.tcx.type_of(id).instantiate_identity().kind(), ty::Adt(adt, _)

View file

@ -64,7 +64,7 @@ impl LateLintPass<'_> for EmptyEnum {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
if let ItemKind::Enum(..) = item.kind
// Only suggest the `never_type` if the feature is enabled
&& cx.tcx.features().never_type
&& cx.tcx.features().never_type()
&& let Some(adt) = cx.tcx.type_of(item.owner_id).instantiate_identity().ty_adt_def()
&& adt.variants().is_empty()
{

View file

@ -3,7 +3,7 @@ use clippy_utils::source::snippet;
use rustc_errors::{Applicability, SuggestionStyle};
use rustc_hir::def_id::DefId;
use rustc_hir::{
AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifier, TyKind,
AssocItemConstraint, GenericArg, GenericBound, GenericBounds, PredicateOrigin, TraitBoundModifiers, TyKind,
WherePredicate,
};
use rustc_hir_analysis::lower_ty;
@ -234,7 +234,7 @@ fn collect_supertrait_bounds<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds
.iter()
.filter_map(|bound| {
if let GenericBound::Trait(poly_trait) = bound
&& let TraitBoundModifier::None = poly_trait.modifiers
&& let TraitBoundModifiers::NONE = poly_trait.modifiers
&& let [.., path] = poly_trait.trait_ref.path.segments
&& poly_trait.bound_generic_params.is_empty()
&& let Some(trait_def_id) = path.res.opt_def_id()
@ -300,7 +300,7 @@ fn check<'tcx>(cx: &LateContext<'tcx>, bounds: GenericBounds<'tcx>) {
// simply comparing trait `DefId`s won't be enough. We also need to compare the generics.
for (index, bound) in bounds.iter().enumerate() {
if let GenericBound::Trait(poly_trait) = bound
&& let TraitBoundModifier::None = poly_trait.modifiers
&& let TraitBoundModifiers::NONE = poly_trait.modifiers
&& let [.., path] = poly_trait.trait_ref.path.segments
&& let implied_args = path.args.map_or([].as_slice(), |a| a.args)
&& let implied_constraints = path.args.map_or([].as_slice(), |a| a.constraints)

View file

@ -65,6 +65,7 @@ extern crate clippy_utils;
#[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
mod utils;
pub mod ctfe; // Very important lint, do not remove (rust#125116)
pub mod declared_lints;
pub mod deprecated_lints;
@ -605,6 +606,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
});
}
store.register_late_pass(|_| Box::new(ctfe::ClippyCtfe));
store.register_late_pass(move |_| Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(conf)));
store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
store.register_late_pass(|_| Box::new(utils::author::Author));

View file

@ -111,11 +111,7 @@ fn check_int_ty_and_feature(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
let expr_ty = cx.typeck_results().expr_ty(expr);
match expr_ty.peel_refs().kind() {
ty::Uint(_) => true,
ty::Int(_) => cx
.tcx
.features()
.declared_features
.contains(&Symbol::intern("int_roundings")),
ty::Int(_) => cx.tcx.features().enabled(Symbol::intern("int_roundings")),
_ => false,
}

View file

@ -114,7 +114,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
let indexed_arms: Vec<(usize, &Arm<'_>)> = arms.iter().enumerate().collect();
for (&(i, arm1), &(j, arm2)) in search_same(&indexed_arms, hash, eq) {
if matches!(arm2.pat.kind, PatKind::Wild) {
if !cx.tcx.features().non_exhaustive_omitted_patterns_lint
if !cx.tcx.features().non_exhaustive_omitted_patterns_lint()
|| is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id)
{
let arm_span = adjusted_arm_span(cx, arm1.span);

View file

@ -251,7 +251,7 @@ fn emit_redundant_guards<'tcx>(
fn expr_can_be_pat(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
for_each_expr_without_closures(expr, |expr| {
if match expr.kind {
ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat,
ExprKind::ConstBlock(..) => cx.tcx.features().inline_const_pat(),
ExprKind::Call(c, ..) if let ExprKind::Path(qpath) = c.kind => {
// Allow ctors
matches!(cx.qpath_res(&qpath, c.hir_id), Res::Def(DefKind::Ctor(..), ..))

View file

@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_hir::def_id::{DefId, DefIdMap};
use rustc_hir::{GenericBound, Generics, PolyTraitRef, TraitBoundModifier, WherePredicate};
use rustc_hir::{GenericBound, Generics, PolyTraitRef, TraitBoundModifiers, BoundPolarity, WherePredicate};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{ClauseKind, PredicatePolarity};
use rustc_session::declare_lint_pass;
@ -118,13 +118,13 @@ impl LateLintPass<'_> for NeedlessMaybeSized {
let maybe_sized_params: DefIdMap<_> = type_param_bounds(generics)
.filter(|bound| {
bound.trait_bound.trait_ref.trait_def_id() == Some(sized_trait)
&& bound.trait_bound.modifiers == TraitBoundModifier::Maybe
&& matches!(bound.trait_bound.modifiers.polarity, BoundPolarity::Maybe(_))
})
.map(|bound| (bound.param, bound))
.collect();
for bound in type_param_bounds(generics) {
if bound.trait_bound.modifiers == TraitBoundModifier::None
if bound.trait_bound.modifiers == TraitBoundModifiers::NONE
&& let Some(sized_bound) = maybe_sized_params.get(&bound.param)
&& let Some(path) = path_to_sized_bound(cx, bound.trait_bound)
{

View file

@ -11,7 +11,7 @@ use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{
GenericBound, Generics, Item, ItemKind, LangItem, Node, Path, PathSegment, PredicateOrigin, QPath,
TraitBoundModifier, TraitItem, TraitRef, Ty, TyKind, WherePredicate,
TraitBoundModifiers, TraitItem, TraitRef, Ty, TyKind, WherePredicate, BoundPolarity,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
@ -233,7 +233,7 @@ impl TraitBounds {
fn cannot_combine_maybe_bound(&self, cx: &LateContext<'_>, bound: &GenericBound<'_>) -> bool {
if !self.msrv.meets(msrvs::MAYBE_BOUND_IN_WHERE)
&& let GenericBound::Trait(tr) = bound
&& let TraitBoundModifier::Maybe = tr.modifiers
&& let BoundPolarity::Maybe(_) = tr.modifiers.polarity
{
cx.tcx.lang_items().get(LangItem::Sized) == tr.trait_ref.path.res.opt_def_id()
} else {
@ -374,12 +374,12 @@ fn check_trait_bound_duplication<'tcx>(cx: &LateContext<'tcx>, generics: &'_ Gen
struct ComparableTraitRef<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
trait_ref: &'tcx TraitRef<'tcx>,
modifier: TraitBoundModifier,
modifiers: TraitBoundModifiers,
}
impl PartialEq for ComparableTraitRef<'_, '_> {
fn eq(&self, other: &Self) -> bool {
self.modifier == other.modifier
SpanlessEq::new(self.cx).eq_modifiers(self.modifiers, other.modifiers)
&& SpanlessEq::new(self.cx)
.paths_by_resolution()
.eq_path(self.trait_ref.path, other.trait_ref.path)
@ -390,8 +390,8 @@ impl Hash for ComparableTraitRef<'_, '_> {
fn hash<H: Hasher>(&self, state: &mut H) {
let mut s = SpanlessHash::new(self.cx).paths_by_resolution();
s.hash_path(self.trait_ref.path);
s.hash_modifiers(self.modifiers);
state.write_u64(s.finish());
self.modifier.hash(state);
}
}
@ -400,7 +400,7 @@ fn get_trait_info_from_bound<'a>(bound: &'a GenericBound<'_>) -> Option<(Res, &'
let trait_path = t.trait_ref.path;
let trait_span = {
let path_span = trait_path.span;
if let TraitBoundModifier::Maybe = t.modifiers {
if let BoundPolarity::Maybe(_) = t.modifiers.polarity {
path_span.with_lo(path_span.lo() - BytePos(1)) // include the `?`
} else {
path_span
@ -427,7 +427,7 @@ fn rollup_traits<'cx, 'tcx>(
ComparableTraitRef {
cx,
trait_ref: &t.trait_ref,
modifier: t.modifiers,
modifiers: t.modifiers,
},
t.span,
))

View file

@ -39,7 +39,7 @@ impl From<&Attribute> for IdentIter {
struct IdentCollector(Vec<Ident>);
impl Visitor<'_> for IdentCollector {
fn visit_ident(&mut self, ident: Ident) {
self.0.push(ident);
fn visit_ident(&mut self, ident: &Ident) {
self.0.push(*ident);
}
}

View file

@ -9,7 +9,8 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::{
ArrayLen, AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, Ty, TyKind,
LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty,
TyKind,
};
use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::LateContext;
@ -126,6 +127,11 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
pub fn eq_path_segments(&mut self, left: &[PathSegment<'_>], right: &[PathSegment<'_>]) -> bool {
self.inter_expr().eq_path_segments(left, right)
}
pub fn eq_modifiers(&mut self, left: TraitBoundModifiers, right: TraitBoundModifiers) -> bool {
std::mem::discriminant(&left.constness) == std::mem::discriminant(&right.constness)
&& std::mem::discriminant(&left.polarity) == std::mem::discriminant(&right.polarity)
}
}
pub struct HirEqInterExpr<'a, 'b, 'tcx> {
@ -1143,6 +1149,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
}
pub fn hash_modifiers(&mut self, modifiers: TraitBoundModifiers) {
let TraitBoundModifiers { constness, polarity } = modifiers;
std::mem::discriminant(&polarity).hash(&mut self.s);
std::mem::discriminant(&constness).hash(&mut self.s);
}
pub fn hash_stmt(&mut self, b: &Stmt<'_>) {
std::mem::discriminant(&b.kind).hash(&mut self.s);

View file

@ -334,7 +334,7 @@ fn check_terminator<'tcx>(
| TerminatorKind::TailCall { func, args, fn_span: _ } => {
let fn_ty = func.ty(body, tcx);
if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() {
if !is_const_fn(tcx, fn_def_id, msrv) {
if !is_stable_const_fn(tcx, fn_def_id, msrv) {
return Err((
span,
format!(
@ -377,12 +377,12 @@ fn check_terminator<'tcx>(
}
}
fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
tcx.is_const_fn(def_id)
&& tcx.lookup_const_stability(def_id).map_or(true, |const_stab| {
&& tcx.lookup_const_stability(def_id).is_none_or(|const_stab| {
if let rustc_attr::StabilityLevel::Stable { since, .. } = const_stab.level {
// Checking MSRV is manually necessary because `rustc` has no such concept. This entire
// function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`.
// function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`.
// as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.
let const_stab_rust_version = match since {
@ -393,8 +393,12 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
msrv.meets(const_stab_rust_version)
} else {
// Unstable const fn with the feature enabled.
msrv.current().is_none()
// Unstable const fn, check if the feature is enabled. We need both the regular stability
// feature and (if set) the const stability feature to const-call this function.
let stab = tcx.lookup_stability(def_id);
let is_enabled = stab.is_some_and(|s| s.is_stable() || tcx.features().enabled(s.feature))
&& const_stab.feature.is_none_or(|f| tcx.features().enabled(f));
is_enabled && msrv.current().is_none()
}
})
}

View file

@ -207,16 +207,7 @@ fn path_segment_certainty(
if cx.tcx.res_generics_def_id(path_segment.res).is_some() {
let generics = cx.tcx.generics_of(def_id);
let own_count = generics.own_params.len()
- usize::from(generics.host_effect_index.is_some_and(|index| {
// Check that the host index actually belongs to this resolution.
// E.g. for `Add::add`, host_effect_index is `Some(2)`, but it's part of the parent `Add`
// trait's generics.
// Add params: [Self#0, Rhs#1, host#2] parent_count=0, count=3
// Add::add params: [] parent_count=3, count=3
// (3..3).contains(&host_effect_index) => false
(generics.parent_count..generics.count()).contains(&index)
}));
let own_count = generics.own_params.len();
let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && own_count == 0 {
Certainty::Certain(None)
} else {
@ -310,8 +301,7 @@ fn type_is_inferable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> bo
// Check that all type parameters appear in the functions input types.
(0..(generics.parent_count + generics.own_params.len()) as u32).all(|index| {
Some(index as usize) == generics.host_effect_index
|| fn_sig
fn_sig
.inputs()
.iter()
.any(|input_ty| contains_param(*input_ty.skip_binder(), index))

View file

@ -346,13 +346,13 @@ pub fn is_const_evaluatable<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) ->
.cx
.qpath_res(p, hir_id)
.opt_def_id()
.map_or(false, |id| self.cx.tcx.is_const_fn_raw(id)) => {},
.map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {},
ExprKind::MethodCall(..)
if self
.cx
.typeck_results()
.type_dependent_def_id(e.hir_id)
.map_or(false, |id| self.cx.tcx.is_const_fn_raw(id)) => {},
.map_or(false, |id| self.cx.tcx.is_const_fn(id)) => {},
ExprKind::Binary(_, lhs, rhs)
if self.cx.typeck_results().expr_ty(lhs).peel_refs().is_primitive_ty()
&& self.cx.typeck_results().expr_ty(rhs).peel_refs().is_primitive_ty() => {},

View file

@ -1,3 +1,5 @@
#![warn(clippy::author)]
fn main() {
#[clippy::author]
let x: char = 0x45 as char;

Some files were not shown because too many files have changed in this diff Show more