Merge from rustc
This commit is contained in:
commit
4481569b28
303 changed files with 3902 additions and 1663 deletions
|
|
@ -13,7 +13,7 @@ use std::process::Command;
|
|||
use std::time::{Duration, Instant};
|
||||
|
||||
use crate::cache::{Cache, Interned, INTERNER};
|
||||
use crate::config::{SplitDebuginfo, TargetSelection};
|
||||
use crate::config::{DryRun, SplitDebuginfo, TargetSelection};
|
||||
use crate::doc;
|
||||
use crate::flags::{Color, Subcommand};
|
||||
use crate::install;
|
||||
|
|
@ -281,11 +281,15 @@ impl StepDescription {
|
|||
|
||||
fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
|
||||
if builder.config.exclude.iter().any(|e| pathset.has(&e, builder.kind)) {
|
||||
println!("Skipping {:?} because it is excluded", pathset);
|
||||
if !matches!(builder.config.dry_run, DryRun::SelfCheck) {
|
||||
println!("Skipping {:?} because it is excluded", pathset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if !builder.config.exclude.is_empty() {
|
||||
if !builder.config.exclude.is_empty()
|
||||
&& !matches!(builder.config.dry_run, DryRun::SelfCheck)
|
||||
{
|
||||
builder.verbose(&format!(
|
||||
"{:?} not skipped for {:?} -- not in {:?}",
|
||||
pathset, self.name, builder.config.exclude
|
||||
|
|
|
|||
|
|
@ -688,8 +688,8 @@ fn cp_rustc_component_to_ci_sysroot(
|
|||
contents: Vec<String>,
|
||||
) {
|
||||
let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
|
||||
let ci_rustc_dir = builder.config.ci_rustc_dir();
|
||||
|
||||
let ci_rustc_dir = builder.out.join(&*builder.build.build.triple).join("ci-rustc");
|
||||
for file in contents {
|
||||
let src = ci_rustc_dir.join(&file);
|
||||
let dst = sysroot.join(file);
|
||||
|
|
@ -1424,7 +1424,7 @@ impl Step for Sysroot {
|
|||
// FIXME: this is wrong when compiler.host != build, but we don't support that today
|
||||
OsStr::new(std::env::consts::DLL_EXTENSION),
|
||||
];
|
||||
let ci_rustc_dir = builder.ci_rustc_dir(builder.config.build);
|
||||
let ci_rustc_dir = builder.config.ci_rustc_dir();
|
||||
builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| {
|
||||
if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1375,6 +1375,25 @@ impl Config {
|
|||
let mut omit_git_hash = None;
|
||||
|
||||
if let Some(rust) = toml.rust {
|
||||
set(&mut config.channel, rust.channel);
|
||||
|
||||
config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
|
||||
// This list is incomplete, please help by expanding it!
|
||||
if config.download_rustc_commit.is_some() {
|
||||
// We need the channel used by the downloaded compiler to match the one we set for rustdoc;
|
||||
// otherwise rustdoc-ui tests break.
|
||||
let ci_channel = t!(fs::read_to_string(config.src.join("src/ci/channel")));
|
||||
let ci_channel = ci_channel.trim_end();
|
||||
if config.channel != ci_channel
|
||||
&& !(config.channel == "dev" && ci_channel == "nightly")
|
||||
{
|
||||
panic!(
|
||||
"setting rust.channel={} is incompatible with download-rustc",
|
||||
config.channel
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
debug = rust.debug;
|
||||
debug_assertions = rust.debug_assertions;
|
||||
debug_assertions_std = rust.debug_assertions_std;
|
||||
|
|
@ -1386,6 +1405,7 @@ impl Config {
|
|||
debuginfo_level_std = rust.debuginfo_level_std;
|
||||
debuginfo_level_tools = rust.debuginfo_level_tools;
|
||||
debuginfo_level_tests = rust.debuginfo_level_tests;
|
||||
|
||||
config.rust_split_debuginfo = rust
|
||||
.split_debuginfo
|
||||
.as_deref()
|
||||
|
|
@ -1401,7 +1421,6 @@ impl Config {
|
|||
set(&mut config.jemalloc, rust.jemalloc);
|
||||
set(&mut config.test_compare_mode, rust.test_compare_mode);
|
||||
set(&mut config.backtrace, rust.backtrace);
|
||||
set(&mut config.channel, rust.channel);
|
||||
config.description = rust.description;
|
||||
set(&mut config.rust_dist_src, rust.dist_src);
|
||||
set(&mut config.verbose_tests, rust.verbose_tests);
|
||||
|
|
@ -1442,8 +1461,6 @@ impl Config {
|
|||
config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
|
||||
config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
|
||||
config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
|
||||
config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
|
||||
|
||||
config.rust_lto = rust
|
||||
.lto
|
||||
.as_deref()
|
||||
|
|
@ -1555,6 +1572,11 @@ impl Config {
|
|||
let mut target = Target::from_triple(&triple);
|
||||
|
||||
if let Some(ref s) = cfg.llvm_config {
|
||||
if config.download_rustc_commit.is_some() && triple == &*config.build.triple {
|
||||
panic!(
|
||||
"setting llvm_config for the host is incompatible with download-rustc"
|
||||
);
|
||||
}
|
||||
target.llvm_config = Some(config.src.join(s));
|
||||
}
|
||||
target.llvm_has_rust_patches = cfg.llvm_has_rust_patches;
|
||||
|
|
@ -1825,6 +1847,12 @@ impl Config {
|
|||
self.out.join(&*self.build.triple).join("ci-llvm")
|
||||
}
|
||||
|
||||
/// Directory where the extracted `rustc-dev` component is stored.
|
||||
pub(crate) fn ci_rustc_dir(&self) -> PathBuf {
|
||||
assert!(self.download_rustc());
|
||||
self.out.join(self.build.triple).join("ci-rustc")
|
||||
}
|
||||
|
||||
/// Determine whether llvm should be linked dynamically.
|
||||
///
|
||||
/// If `false`, llvm should be linked statically.
|
||||
|
|
@ -1860,11 +1888,11 @@ impl Config {
|
|||
self.download_rustc_commit().is_some()
|
||||
}
|
||||
|
||||
pub(crate) fn download_rustc_commit(&self) -> Option<&'static str> {
|
||||
pub(crate) fn download_rustc_commit(&self) -> Option<&str> {
|
||||
static DOWNLOAD_RUSTC: OnceCell<Option<String>> = OnceCell::new();
|
||||
if self.dry_run() && DOWNLOAD_RUSTC.get().is_none() {
|
||||
// avoid trying to actually download the commit
|
||||
return None;
|
||||
return self.download_rustc_commit.as_deref();
|
||||
}
|
||||
|
||||
DOWNLOAD_RUSTC
|
||||
|
|
|
|||
|
|
@ -1074,11 +1074,7 @@ impl Step for Cargo {
|
|||
|
||||
tarball.add_file(&cargo, "bin", 0o755);
|
||||
tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
|
||||
tarball.add_renamed_file(
|
||||
etc.join("cargo.bashcomp.sh"),
|
||||
"src/etc/bash_completion.d",
|
||||
"cargo",
|
||||
);
|
||||
tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
|
||||
tarball.add_dir(etc.join("man"), "share/man/man1");
|
||||
tarball.add_legal_and_readme_to("share/doc/cargo");
|
||||
|
||||
|
|
|
|||
|
|
@ -402,7 +402,11 @@ impl Config {
|
|||
|
||||
fn ci_component_contents(&self, stamp_file: &str) -> Vec<String> {
|
||||
assert!(self.download_rustc());
|
||||
let ci_rustc_dir = self.out.join(&*self.build.triple).join("ci-rustc");
|
||||
if self.dry_run() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let ci_rustc_dir = self.ci_rustc_dir();
|
||||
let stamp_file = ci_rustc_dir.join(stamp_file);
|
||||
let contents_file = t!(File::open(&stamp_file), stamp_file.display().to_string());
|
||||
t!(BufReader::new(contents_file).lines().collect())
|
||||
|
|
@ -419,7 +423,7 @@ impl Config {
|
|||
self.download_toolchain(
|
||||
&version,
|
||||
"ci-rustc",
|
||||
commit,
|
||||
&format!("{commit}-{}", self.llvm_assertions),
|
||||
&extra_components,
|
||||
Self::download_ci_component,
|
||||
);
|
||||
|
|
@ -495,8 +499,15 @@ impl Config {
|
|||
|
||||
/// Download a single component of a CI-built toolchain (not necessarily a published nightly).
|
||||
// NOTE: intentionally takes an owned string to avoid downloading multiple times by accident
|
||||
fn download_ci_component(&self, filename: String, prefix: &str, commit: &str) {
|
||||
Self::download_component(self, DownloadSource::CI, filename, prefix, commit, "ci-rustc")
|
||||
fn download_ci_component(&self, filename: String, prefix: &str, commit_with_assertions: &str) {
|
||||
Self::download_component(
|
||||
self,
|
||||
DownloadSource::CI,
|
||||
filename,
|
||||
prefix,
|
||||
commit_with_assertions,
|
||||
"ci-rustc",
|
||||
)
|
||||
}
|
||||
|
||||
fn download_component(
|
||||
|
|
@ -516,11 +527,18 @@ impl Config {
|
|||
let bin_root = self.out.join(self.build.triple).join(destination);
|
||||
let tarball = cache_dir.join(&filename);
|
||||
let (base_url, url, should_verify) = match mode {
|
||||
DownloadSource::CI => (
|
||||
self.stage0_metadata.config.artifacts_server.clone(),
|
||||
format!("{key}/{filename}"),
|
||||
false,
|
||||
),
|
||||
DownloadSource::CI => {
|
||||
let dist_server = if self.llvm_assertions {
|
||||
self.stage0_metadata.config.artifacts_with_llvm_assertions_server.clone()
|
||||
} else {
|
||||
self.stage0_metadata.config.artifacts_server.clone()
|
||||
};
|
||||
let url = format!(
|
||||
"{}/{filename}",
|
||||
key.strip_suffix(&format!("-{}", self.llvm_assertions)).unwrap()
|
||||
);
|
||||
(dist_server, url, false)
|
||||
}
|
||||
DownloadSource::Dist => {
|
||||
let dist_server = env::var("RUSTUP_DIST_SERVER")
|
||||
.unwrap_or(self.stage0_metadata.config.dist_server.to_string());
|
||||
|
|
|
|||
|
|
@ -822,11 +822,6 @@ impl Build {
|
|||
self.stage_out(compiler, mode).join(&*target.triple).join(self.cargo_dir())
|
||||
}
|
||||
|
||||
/// Directory where the extracted `rustc-dev` component is stored.
|
||||
fn ci_rustc_dir(&self, target: TargetSelection) -> PathBuf {
|
||||
self.out.join(&*target.triple).join("ci-rustc")
|
||||
}
|
||||
|
||||
/// Root output directory for LLVM compiled for `target`
|
||||
///
|
||||
/// Note that if LLVM is configured externally then the directory returned
|
||||
|
|
|
|||
|
|
@ -2348,7 +2348,7 @@ impl Step for Crate {
|
|||
// `std_cargo` actually does the wrong thing: it passes `--sysroot build/host/stage2`,
|
||||
// but we want to use the force-recompile std we just built in `build/host/stage2-test-sysroot`.
|
||||
// Override it.
|
||||
if builder.download_rustc() {
|
||||
if builder.download_rustc() && compiler.stage > 0 {
|
||||
let sysroot = builder
|
||||
.out
|
||||
.join(compiler.host.triple)
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ x--expand-yaml-anchors--remove:
|
|||
<<: *base-job
|
||||
|
||||
- &job-macos-xl
|
||||
os: macos-latest # We use the standard runner for now
|
||||
os: macos-13 # We use the standard runner for now
|
||||
<<: *base-job
|
||||
|
||||
- &job-windows-8c
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 21cf840842bdf768a798869f06373c96c1cc5122
|
||||
Subproject commit 668c64760b5c7ea654facb4ba5fe9faddfda27cc
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit f63e578b92ff43e8cc38fcaa257b660f45c8a8c2
|
||||
Subproject commit 2751bdcef125468ea2ee006c11992cd1405aebe5
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit f2aed2fe8e9f55508c86ba3aa4b6789b18a08a22
|
||||
Subproject commit 1e5556dd1b864109985d5871616ae6b9164bcead
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit c369e4b489332f8721fbae630354fa83385d457d
|
||||
Subproject commit 302b995bcb24b70fd883980fd174738c3a10b705
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5ca365eac678cb0d41a20b3204546d6ed70c7171
|
||||
Subproject commit 1ea0178266b3f3f613b0fabdaf16a83961c99cdb
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 57636d6926762861f34e030d52ca25a71e95e5bf
|
||||
Subproject commit 8a87926a985ce32ca1fad1be4008ee161a0b91eb
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 17fe3e948498c50e208047a750f17d6a8d89669b
|
||||
Subproject commit b5a12d95e32ae53791cc6ab44417774667ed2ac6
|
||||
|
|
@ -451,12 +451,11 @@ foo(
|
|||
|
||||
#### Multi-line elements
|
||||
|
||||
If any element in a chain is formatted across multiple lines, then that element
|
||||
and any later elements must be on their own line. Earlier elements may be kept
|
||||
on a single line. E.g.,
|
||||
If any element in a chain is formatted across multiple lines, put that element
|
||||
and any later elements on their own lines.
|
||||
|
||||
```rust
|
||||
a.b.c()?.d
|
||||
a.b.c()?
|
||||
.foo(
|
||||
an_expr,
|
||||
another_expr,
|
||||
|
|
@ -803,6 +802,16 @@ foo(|param| {
|
|||
action();
|
||||
foo(param)
|
||||
})
|
||||
|
||||
let x = combinable([
|
||||
an_expr,
|
||||
another_expr,
|
||||
]);
|
||||
|
||||
let arr = [combinable(
|
||||
an_expr,
|
||||
another_expr,
|
||||
)];
|
||||
```
|
||||
|
||||
Such behaviour should extend recursively, however, tools may choose to limit the
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ impl From<DefKind> for ItemType {
|
|||
| DefKind::AnonConst
|
||||
| DefKind::InlineConst
|
||||
| DefKind::OpaqueTy
|
||||
| DefKind::ImplTraitPlaceholder
|
||||
| DefKind::Field
|
||||
| DefKind::LifetimeParam
|
||||
| DefKind::GlobalAsm
|
||||
|
|
|
|||
|
|
@ -1860,8 +1860,8 @@ fn resolution_failure(
|
|||
}
|
||||
return;
|
||||
}
|
||||
Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder
|
||||
| TraitAlias | TyParam | Static(_) => "associated item",
|
||||
Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam
|
||||
| Static(_) => "associated item",
|
||||
Impl { .. } | GlobalAsm => unreachable!("not a path"),
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -171,7 +171,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
|
||||
crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO,
|
||||
crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO,
|
||||
crate::fn_null_check::FN_NULL_CHECK_INFO,
|
||||
crate::format::USELESS_FORMAT_INFO,
|
||||
crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO,
|
||||
crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO,
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
use clippy_utils::consts::{constant, Constant};
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
|
||||
use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::sym;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for comparing a function pointer to null.
|
||||
///
|
||||
/// ### Why is this bad?
|
||||
/// Function pointers are assumed to not be null.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```rust,ignore
|
||||
/// let fn_ptr: fn() = /* somehow obtained nullable function pointer */
|
||||
///
|
||||
/// if (fn_ptr as *const ()).is_null() { ... }
|
||||
/// ```
|
||||
/// Use instead:
|
||||
/// ```rust,ignore
|
||||
/// let fn_ptr: Option<fn()> = /* somehow obtained nullable function pointer */
|
||||
///
|
||||
/// if fn_ptr.is_none() { ... }
|
||||
/// ```
|
||||
#[clippy::version = "1.68.0"]
|
||||
pub FN_NULL_CHECK,
|
||||
correctness,
|
||||
"`fn()` type assumed to be nullable"
|
||||
}
|
||||
declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]);
|
||||
|
||||
fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||
span_lint_and_help(
|
||||
cx,
|
||||
FN_NULL_CHECK,
|
||||
expr.span,
|
||||
"function pointer assumed to be nullable, even though it isn't",
|
||||
None,
|
||||
"try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value",
|
||||
);
|
||||
}
|
||||
|
||||
fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||
if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind
|
||||
&& let TyKind::Ptr(_) = cast_ty.kind
|
||||
{
|
||||
cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
match expr.kind {
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>).is_null()
|
||||
ExprKind::MethodCall(method_name, receiver, _, _)
|
||||
if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) =>
|
||||
{
|
||||
lint_expr(cx, expr);
|
||||
},
|
||||
|
||||
ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
|
||||
let to_check: &Expr<'_>;
|
||||
if is_fn_ptr_cast(cx, left) {
|
||||
to_check = right;
|
||||
} else if is_fn_ptr_cast(cx, right) {
|
||||
to_check = left;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
match to_check.kind {
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
|
||||
ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => {
|
||||
lint_expr(cx, expr);
|
||||
},
|
||||
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
|
||||
ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => {
|
||||
lint_expr(cx, expr);
|
||||
},
|
||||
|
||||
// Catching:
|
||||
// (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
|
||||
_ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => {
|
||||
lint_expr(cx, expr);
|
||||
},
|
||||
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -131,7 +131,6 @@ mod extra_unused_type_parameters;
|
|||
mod fallible_impl_from;
|
||||
mod float_literal;
|
||||
mod floating_point_arithmetic;
|
||||
mod fn_null_check;
|
||||
mod format;
|
||||
mod format_args;
|
||||
mod format_impl;
|
||||
|
|
@ -1003,7 +1002,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
semicolon_outside_block_ignore_multiline,
|
||||
))
|
||||
});
|
||||
store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
|
||||
store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
|
||||
store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
|
||||
store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
|
|||
("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
|
||||
("clippy::forget_copy", "forgetting_copy_types"),
|
||||
("clippy::forget_ref", "forgetting_references"),
|
||||
("clippy::fn_null_check", "incorrect_fn_null_checks"),
|
||||
("clippy::into_iter_on_array", "array_into_iter"),
|
||||
("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
|
||||
("clippy::invalid_ref", "invalid_value"),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
//@aux-build:proc_macro_attr.rs:proc-macro
|
||||
// Flaky test, see https://github.com/rust-lang/rust/issues/113585.
|
||||
//@ignore-32bit
|
||||
//@ignore-64bit
|
||||
#![warn(clippy::empty_line_after_doc_comments)]
|
||||
#![allow(clippy::assertions_on_constants)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
//@aux-build:proc_macro_attr.rs:proc-macro
|
||||
// Flaky test, see https://github.com/rust-lang/rust/issues/113585.
|
||||
//@ignore-32bit
|
||||
//@ignore-64bit
|
||||
#![warn(clippy::empty_line_after_outer_attr)]
|
||||
#![allow(clippy::assertions_on_constants)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
#![allow(unused)]
|
||||
#![warn(clippy::fn_null_check)]
|
||||
#![allow(clippy::cmp_null)]
|
||||
#![allow(clippy::needless_if)]
|
||||
#![allow(clippy::ptr_eq)]
|
||||
#![allow(clippy::zero_ptr)]
|
||||
|
||||
pub const ZPTR: *const () = 0 as *const _;
|
||||
pub const NOT_ZPTR: *const () = 1 as *const _;
|
||||
|
||||
fn main() {
|
||||
let fn_ptr = main;
|
||||
|
||||
if (fn_ptr as *mut ()).is_null() {}
|
||||
if (fn_ptr as *const u8).is_null() {}
|
||||
if (fn_ptr as *const ()) == std::ptr::null() {}
|
||||
if (fn_ptr as *const ()) == (0 as *const ()) {}
|
||||
if (fn_ptr as *const ()) == ZPTR {}
|
||||
|
||||
// no lint
|
||||
if (fn_ptr as *const ()) == NOT_ZPTR {}
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
error: function pointer assumed to be nullable, even though it isn't
|
||||
--> $DIR/fn_null_check.rs:14:8
|
||||
|
|
||||
LL | if (fn_ptr as *mut ()).is_null() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
|
||||
= note: `-D clippy::fn-null-check` implied by `-D warnings`
|
||||
|
||||
error: function pointer assumed to be nullable, even though it isn't
|
||||
--> $DIR/fn_null_check.rs:15:8
|
||||
|
|
||||
LL | if (fn_ptr as *const u8).is_null() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
|
||||
|
||||
error: function pointer assumed to be nullable, even though it isn't
|
||||
--> $DIR/fn_null_check.rs:16:8
|
||||
|
|
||||
LL | if (fn_ptr as *const ()) == std::ptr::null() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
|
||||
|
||||
error: function pointer assumed to be nullable, even though it isn't
|
||||
--> $DIR/fn_null_check.rs:17:8
|
||||
|
|
||||
LL | if (fn_ptr as *const ()) == (0 as *const ()) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
|
||||
|
||||
error: function pointer assumed to be nullable, even though it isn't
|
||||
--> $DIR/fn_null_check.rs:18:8
|
||||
|
|
||||
LL | if (fn_ptr as *const ()) == ZPTR {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
|
@ -1,4 +1,7 @@
|
|||
//@aux-build:proc_macro_attr.rs:proc-macro
|
||||
// Flaky test, see https://github.com/rust-lang/rust/issues/113585.
|
||||
//@ignore-32bit
|
||||
//@ignore-64bit
|
||||
|
||||
#![warn(clippy::needless_arbitrary_self_type)]
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#![allow(for_loops_over_fallibles)]
|
||||
#![allow(forgetting_copy_types)]
|
||||
#![allow(forgetting_references)]
|
||||
#![allow(incorrect_fn_null_checks)]
|
||||
#![allow(array_into_iter)]
|
||||
#![allow(invalid_atomic_ordering)]
|
||||
#![allow(invalid_value)]
|
||||
|
|
@ -89,6 +90,7 @@
|
|||
#![warn(for_loops_over_fallibles)]
|
||||
#![warn(forgetting_copy_types)]
|
||||
#![warn(forgetting_references)]
|
||||
#![warn(incorrect_fn_null_checks)]
|
||||
#![warn(array_into_iter)]
|
||||
#![warn(invalid_atomic_ordering)]
|
||||
#![warn(invalid_value)]
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#![allow(for_loops_over_fallibles)]
|
||||
#![allow(forgetting_copy_types)]
|
||||
#![allow(forgetting_references)]
|
||||
#![allow(incorrect_fn_null_checks)]
|
||||
#![allow(array_into_iter)]
|
||||
#![allow(invalid_atomic_ordering)]
|
||||
#![allow(invalid_value)]
|
||||
|
|
@ -89,6 +90,7 @@
|
|||
#![warn(clippy::for_loops_over_fallibles)]
|
||||
#![warn(clippy::forget_copy)]
|
||||
#![warn(clippy::forget_ref)]
|
||||
#![warn(clippy::fn_null_check)]
|
||||
#![warn(clippy::into_iter_on_array)]
|
||||
#![warn(clippy::invalid_atomic_ordering)]
|
||||
#![warn(clippy::invalid_ref)]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
|
||||
--> $DIR/rename.rs:52:9
|
||||
--> $DIR/rename.rs:53:9
|
||||
|
|
||||
LL | #![warn(clippy::almost_complete_letter_range)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
|
||||
|
|
@ -7,310 +7,316 @@ LL | #![warn(clippy::almost_complete_letter_range)]
|
|||
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
|
||||
|
||||
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
|
||||
--> $DIR/rename.rs:53:9
|
||||
--> $DIR/rename.rs:54:9
|
||||
|
|
||||
LL | #![warn(clippy::blacklisted_name)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:54:9
|
||||
--> $DIR/rename.rs:55:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_expr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
|
||||
--> $DIR/rename.rs:55:9
|
||||
--> $DIR/rename.rs:56:9
|
||||
|
|
||||
LL | #![warn(clippy::block_in_if_condition_stmt)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
|
||||
|
||||
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
|
||||
--> $DIR/rename.rs:56:9
|
||||
--> $DIR/rename.rs:57:9
|
||||
|
|
||||
LL | #![warn(clippy::box_vec)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
|
||||
|
||||
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
|
||||
--> $DIR/rename.rs:57:9
|
||||
--> $DIR/rename.rs:58:9
|
||||
|
|
||||
LL | #![warn(clippy::const_static_lifetime)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
|
||||
|
||||
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
|
||||
--> $DIR/rename.rs:58:9
|
||||
--> $DIR/rename.rs:59:9
|
||||
|
|
||||
LL | #![warn(clippy::cyclomatic_complexity)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
|
||||
|
||||
error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
|
||||
--> $DIR/rename.rs:59:9
|
||||
--> $DIR/rename.rs:60:9
|
||||
|
|
||||
LL | #![warn(clippy::derive_hash_xor_eq)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
|
||||
|
||||
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
|
||||
--> $DIR/rename.rs:60:9
|
||||
--> $DIR/rename.rs:61:9
|
||||
|
|
||||
LL | #![warn(clippy::disallowed_method)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
|
||||
|
||||
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
|
||||
--> $DIR/rename.rs:61:9
|
||||
--> $DIR/rename.rs:62:9
|
||||
|
|
||||
LL | #![warn(clippy::disallowed_type)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
|
||||
|
||||
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
|
||||
--> $DIR/rename.rs:62:9
|
||||
--> $DIR/rename.rs:63:9
|
||||
|
|
||||
LL | #![warn(clippy::eval_order_dependence)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
|
||||
|
||||
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
|
||||
--> $DIR/rename.rs:63:9
|
||||
--> $DIR/rename.rs:64:9
|
||||
|
|
||||
LL | #![warn(clippy::identity_conversion)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
|
||||
|
||||
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
|
||||
--> $DIR/rename.rs:64:9
|
||||
--> $DIR/rename.rs:65:9
|
||||
|
|
||||
LL | #![warn(clippy::if_let_some_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
|
||||
|
||||
error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
|
||||
--> $DIR/rename.rs:65:9
|
||||
--> $DIR/rename.rs:66:9
|
||||
|
|
||||
LL | #![warn(clippy::integer_arithmetic)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
|
||||
|
||||
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
|
||||
--> $DIR/rename.rs:66:9
|
||||
--> $DIR/rename.rs:67:9
|
||||
|
|
||||
LL | #![warn(clippy::logic_bug)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
|
||||
|
||||
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
|
||||
--> $DIR/rename.rs:67:9
|
||||
--> $DIR/rename.rs:68:9
|
||||
|
|
||||
LL | #![warn(clippy::new_without_default_derive)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
|
||||
|
||||
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
|
||||
--> $DIR/rename.rs:68:9
|
||||
--> $DIR/rename.rs:69:9
|
||||
|
|
||||
LL | #![warn(clippy::option_and_then_some)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
|
||||
|
||||
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
|
||||
--> $DIR/rename.rs:69:9
|
||||
--> $DIR/rename.rs:70:9
|
||||
|
|
||||
LL | #![warn(clippy::option_expect_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:70:9
|
||||
--> $DIR/rename.rs:71:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:71:9
|
||||
--> $DIR/rename.rs:72:9
|
||||
|
|
||||
LL | #![warn(clippy::option_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||
--> $DIR/rename.rs:72:9
|
||||
--> $DIR/rename.rs:73:9
|
||||
|
|
||||
LL | #![warn(clippy::option_unwrap_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
|
||||
--> $DIR/rename.rs:73:9
|
||||
--> $DIR/rename.rs:74:9
|
||||
|
|
||||
LL | #![warn(clippy::ref_in_deref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
|
||||
|
||||
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
|
||||
--> $DIR/rename.rs:74:9
|
||||
--> $DIR/rename.rs:75:9
|
||||
|
|
||||
LL | #![warn(clippy::result_expect_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
|
||||
|
||||
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
|
||||
--> $DIR/rename.rs:75:9
|
||||
--> $DIR/rename.rs:76:9
|
||||
|
|
||||
LL | #![warn(clippy::result_map_unwrap_or_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
|
||||
|
||||
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
|
||||
--> $DIR/rename.rs:76:9
|
||||
--> $DIR/rename.rs:77:9
|
||||
|
|
||||
LL | #![warn(clippy::result_unwrap_used)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
|
||||
|
||||
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
|
||||
--> $DIR/rename.rs:77:9
|
||||
--> $DIR/rename.rs:78:9
|
||||
|
|
||||
LL | #![warn(clippy::single_char_push_str)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
|
||||
|
||||
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
|
||||
--> $DIR/rename.rs:78:9
|
||||
--> $DIR/rename.rs:79:9
|
||||
|
|
||||
LL | #![warn(clippy::stutter)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
|
||||
|
||||
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
|
||||
--> $DIR/rename.rs:79:9
|
||||
--> $DIR/rename.rs:80:9
|
||||
|
|
||||
LL | #![warn(clippy::to_string_in_display)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
|
||||
|
||||
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
|
||||
--> $DIR/rename.rs:80:9
|
||||
--> $DIR/rename.rs:81:9
|
||||
|
|
||||
LL | #![warn(clippy::zero_width_space)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
|
||||
|
||||
error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut`
|
||||
--> $DIR/rename.rs:81:9
|
||||
--> $DIR/rename.rs:82:9
|
||||
|
|
||||
LL | #![warn(clippy::cast_ref_to_mut)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut`
|
||||
|
||||
error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
|
||||
--> $DIR/rename.rs:82:9
|
||||
--> $DIR/rename.rs:83:9
|
||||
|
|
||||
LL | #![warn(clippy::clone_double_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
|
||||
|
||||
error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
|
||||
--> $DIR/rename.rs:83:9
|
||||
--> $DIR/rename.rs:84:9
|
||||
|
|
||||
LL | #![warn(clippy::cmp_nan)]
|
||||
| ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
|
||||
|
||||
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
|
||||
--> $DIR/rename.rs:84:9
|
||||
--> $DIR/rename.rs:85:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_bounds)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
|
||||
|
||||
error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
|
||||
--> $DIR/rename.rs:85:9
|
||||
--> $DIR/rename.rs:86:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_copy)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
|
||||
|
||||
error: lint `clippy::drop_ref` has been renamed to `dropping_references`
|
||||
--> $DIR/rename.rs:86:9
|
||||
--> $DIR/rename.rs:87:9
|
||||
|
|
||||
LL | #![warn(clippy::drop_ref)]
|
||||
| ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
|
||||
|
||||
error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:87:9
|
||||
--> $DIR/rename.rs:88:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_option)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:88:9
|
||||
--> $DIR/rename.rs:89:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loop_over_result)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
|
||||
--> $DIR/rename.rs:89:9
|
||||
--> $DIR/rename.rs:90:9
|
||||
|
|
||||
LL | #![warn(clippy::for_loops_over_fallibles)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
|
||||
|
||||
error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
|
||||
--> $DIR/rename.rs:90:9
|
||||
--> $DIR/rename.rs:91:9
|
||||
|
|
||||
LL | #![warn(clippy::forget_copy)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
|
||||
|
||||
error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
|
||||
--> $DIR/rename.rs:91:9
|
||||
--> $DIR/rename.rs:92:9
|
||||
|
|
||||
LL | #![warn(clippy::forget_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
|
||||
|
||||
error: lint `clippy::fn_null_check` has been renamed to `incorrect_fn_null_checks`
|
||||
--> $DIR/rename.rs:93:9
|
||||
|
|
||||
LL | #![warn(clippy::fn_null_check)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `incorrect_fn_null_checks`
|
||||
|
||||
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
|
||||
--> $DIR/rename.rs:92:9
|
||||
--> $DIR/rename.rs:94:9
|
||||
|
|
||||
LL | #![warn(clippy::into_iter_on_array)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
|
||||
|
||||
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
|
||||
--> $DIR/rename.rs:93:9
|
||||
--> $DIR/rename.rs:95:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_atomic_ordering)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
|
||||
|
||||
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
|
||||
--> $DIR/rename.rs:94:9
|
||||
--> $DIR/rename.rs:96:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_ref)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
|
||||
|
||||
error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
|
||||
--> $DIR/rename.rs:95:9
|
||||
--> $DIR/rename.rs:97:9
|
||||
|
|
||||
LL | #![warn(clippy::invalid_utf8_in_unchecked)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
|
||||
|
||||
error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
|
||||
--> $DIR/rename.rs:96:9
|
||||
--> $DIR/rename.rs:98:9
|
||||
|
|
||||
LL | #![warn(clippy::let_underscore_drop)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
|
||||
|
||||
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
|
||||
--> $DIR/rename.rs:97:9
|
||||
--> $DIR/rename.rs:99:9
|
||||
|
|
||||
LL | #![warn(clippy::mem_discriminant_non_enum)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
|
||||
|
||||
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
|
||||
--> $DIR/rename.rs:98:9
|
||||
--> $DIR/rename.rs:100:9
|
||||
|
|
||||
LL | #![warn(clippy::panic_params)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
|
||||
|
||||
error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
|
||||
--> $DIR/rename.rs:99:9
|
||||
--> $DIR/rename.rs:101:9
|
||||
|
|
||||
LL | #![warn(clippy::positional_named_format_parameters)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
|
||||
|
||||
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
|
||||
--> $DIR/rename.rs:100:9
|
||||
--> $DIR/rename.rs:102:9
|
||||
|
|
||||
LL | #![warn(clippy::temporary_cstring_as_ptr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
|
||||
|
||||
error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
|
||||
--> $DIR/rename.rs:101:9
|
||||
--> $DIR/rename.rs:103:9
|
||||
|
|
||||
LL | #![warn(clippy::undropped_manually_drops)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
|
||||
|
||||
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
|
||||
--> $DIR/rename.rs:102:9
|
||||
--> $DIR/rename.rs:104:9
|
||||
|
|
||||
LL | #![warn(clippy::unknown_clippy_lints)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
|
||||
|
||||
error: lint `clippy::unused_label` has been renamed to `unused_labels`
|
||||
--> $DIR/rename.rs:103:9
|
||||
--> $DIR/rename.rs:105:9
|
||||
|
|
||||
LL | #![warn(clippy::unused_label)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
|
||||
|
||||
error: aborting due to 52 previous errors
|
||||
error: aborting due to 53 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ impl<'a> LintExtractor<'a> {
|
|||
fn collect_groups(&self) -> Result<LintGroups, Box<dyn Error>> {
|
||||
let mut result = BTreeMap::new();
|
||||
let mut cmd = Command::new(self.rustc_path);
|
||||
cmd.env_remove("LD_LIBRARY_PATH");
|
||||
cmd.arg("-Whelp");
|
||||
let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?;
|
||||
if !output.status.success() {
|
||||
|
|
|
|||
|
|
@ -403,12 +403,6 @@ impl<'a> LintExtractor<'a> {
|
|||
fs::write(&tempfile, source)
|
||||
.map_err(|e| format!("failed to write {}: {}", tempfile.display(), e))?;
|
||||
let mut cmd = Command::new(self.rustc_path);
|
||||
// NOTE: bootstrap sets `LD_LIBRARY_PATH` for building lint-docs itself.
|
||||
// Unfortunately, lint-docs is a bootstrap tool while rustc is built from source,
|
||||
// and sometimes the paths conflict. In particular, when using `download-rustc`,
|
||||
// the LLVM versions can differ between `ci-llvm` and `ci-rustc-sysroot`.
|
||||
// Unset LD_LIBRARY_PATH here so it doesn't interfere with running the compiler.
|
||||
cmd.env_remove("LD_LIBRARY_PATH");
|
||||
if options.contains(&"edition2015") {
|
||||
cmd.arg("--edition=2015");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -302,12 +302,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn retag_return_place(&mut self) -> InterpResult<'tcx> {
|
||||
fn protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
|
||||
match method {
|
||||
BorrowTrackerMethod::StackedBorrows => this.sb_retag_return_place(),
|
||||
BorrowTrackerMethod::TreeBorrows => this.tb_retag_return_place(),
|
||||
BorrowTrackerMethod::StackedBorrows => this.sb_protect_place(place),
|
||||
BorrowTrackerMethod::TreeBorrows => this.tb_protect_place(place),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@ struct RetagOp {
|
|||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum RetagCause {
|
||||
Normal,
|
||||
FnReturnPlace,
|
||||
InPlaceFnPassing,
|
||||
FnEntry,
|
||||
TwoPhase,
|
||||
}
|
||||
|
|
@ -501,7 +501,7 @@ impl RetagCause {
|
|||
match self {
|
||||
RetagCause::Normal => "retag",
|
||||
RetagCause::FnEntry => "function-entry retag",
|
||||
RetagCause::FnReturnPlace => "return-place retag",
|
||||
RetagCause::InPlaceFnPassing => "in-place function argument/return passing protection",
|
||||
RetagCause::TwoPhase => "two-phase retag",
|
||||
}
|
||||
.to_string()
|
||||
|
|
|
|||
|
|
@ -994,35 +994,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// After a stack frame got pushed, retag the return place so that we are sure
|
||||
/// it does not alias with anything.
|
||||
///
|
||||
/// This is a HACK because there is nothing in MIR that would make the retag
|
||||
/// explicit. Also see <https://github.com/rust-lang/rust/issues/71117>.
|
||||
fn sb_retag_return_place(&mut self) -> InterpResult<'tcx> {
|
||||
/// Protect a place so that it cannot be used any more for the duration of the current function
|
||||
/// call.
|
||||
///
|
||||
/// This is used to ensure soundness of in-place function argument/return passing.
|
||||
fn sb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let return_place = &this.frame().return_place;
|
||||
if return_place.layout.is_zst() {
|
||||
// There may not be any memory here, nothing to do.
|
||||
return Ok(());
|
||||
}
|
||||
// We need this to be in-memory to use tagged pointers.
|
||||
let return_place = this.force_allocation(&return_place.clone())?;
|
||||
|
||||
// We have to turn the place into a pointer to use the existing code.
|
||||
// We have to turn the place into a pointer to use the usual retagging logic.
|
||||
// (The pointer type does not matter, so we use a raw pointer.)
|
||||
let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, return_place.layout.ty))?;
|
||||
let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
|
||||
// Reborrow it. With protection! That is part of the point.
|
||||
let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, place.layout.ty))?;
|
||||
let ptr = ImmTy::from_immediate(place.to_ref(this), ptr_layout);
|
||||
// Reborrow it. With protection! That is the entire point.
|
||||
let new_perm = NewPermission::Uniform {
|
||||
perm: Permission::Unique,
|
||||
access: Some(AccessKind::Write),
|
||||
protector: Some(ProtectorKind::StrongProtector),
|
||||
};
|
||||
let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturnPlace)?;
|
||||
// And use reborrowed pointer for return place.
|
||||
let return_place = this.ref_to_mplace(&val)?;
|
||||
this.frame_mut().return_place = return_place.into();
|
||||
let _new_ptr = this.sb_retag_reference(&ptr, new_perm, RetagCause::InPlaceFnPassing)?;
|
||||
// We just throw away `new_ptr`, so nobody can access this memory while it is protected.
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Provenance>, // parent tag extracted from here
|
||||
ptr_size: Size,
|
||||
new_perm: Option<NewPermission>,
|
||||
new_perm: NewPermission,
|
||||
new_tag: BorTag,
|
||||
) -> InterpResult<'tcx, Option<(AllocId, BorTag)>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
|
@ -256,10 +256,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||
ptr_size.bytes()
|
||||
);
|
||||
|
||||
let Some(new_perm) = new_perm else {
|
||||
return Ok(Some((alloc_id, orig_tag)));
|
||||
};
|
||||
|
||||
if let Some(protect) = new_perm.protector {
|
||||
// We register the protection in two different places.
|
||||
// This makes creating a protector slower, but checking whether a tag
|
||||
|
|
@ -305,7 +301,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||
fn tb_retag_reference(
|
||||
&mut self,
|
||||
val: &ImmTy<'tcx, Provenance>,
|
||||
new_perm: Option<NewPermission>,
|
||||
new_perm: NewPermission,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
// We want a place for where the ptr *points to*, so we get one.
|
||||
|
|
@ -317,7 +313,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
|
|||
// - if the pointer is not reborrowed (raw pointer) or if `zero_size` is set
|
||||
// then we override the size to do a zero-length reborrow.
|
||||
let reborrow_size = match new_perm {
|
||||
Some(NewPermission { zero_size: false, .. }) =>
|
||||
NewPermission { zero_size: false, .. } =>
|
||||
this.size_and_align_of_mplace(&place)?
|
||||
.map(|(size, _)| size)
|
||||
.unwrap_or(place.layout.size),
|
||||
|
|
@ -374,7 +370,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
NewPermission::from_ref_ty(pointee, mutability, kind, this),
|
||||
_ => None,
|
||||
};
|
||||
this.tb_retag_reference(val, new_perm)
|
||||
if let Some(new_perm) = new_perm {
|
||||
this.tb_retag_reference(val, new_perm)
|
||||
} else {
|
||||
Ok(val.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Retag all pointers that are stored in this place.
|
||||
|
|
@ -405,9 +405,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
place: &PlaceTy<'tcx, Provenance>,
|
||||
new_perm: Option<NewPermission>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
|
||||
let val = self.ecx.tb_retag_reference(&val, new_perm)?;
|
||||
self.ecx.write_immediate(*val, place)?;
|
||||
if let Some(new_perm) = new_perm {
|
||||
let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
|
||||
let val = self.ecx.tb_retag_reference(&val, new_perm)?;
|
||||
self.ecx.write_immediate(*val, place)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -493,36 +495,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// After a stack frame got pushed, retag the return place so that we are sure
|
||||
/// it does not alias with anything.
|
||||
///
|
||||
/// This is a HACK because there is nothing in MIR that would make the retag
|
||||
/// explicit. Also see <https://github.com/rust-lang/rust/issues/71117>.
|
||||
fn tb_retag_return_place(&mut self) -> InterpResult<'tcx> {
|
||||
/// Protect a place so that it cannot be used any more for the duration of the current function
|
||||
/// call.
|
||||
///
|
||||
/// This is used to ensure soundness of in-place function argument/return passing.
|
||||
fn tb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
//this.debug_hint_location();
|
||||
let return_place = &this.frame().return_place;
|
||||
if return_place.layout.is_zst() {
|
||||
// There may not be any memory here, nothing to do.
|
||||
return Ok(());
|
||||
}
|
||||
// We need this to be in-memory to use tagged pointers.
|
||||
let return_place = this.force_allocation(&return_place.clone())?;
|
||||
|
||||
// We have to turn the place into a pointer to use the existing code.
|
||||
// We have to turn the place into a pointer to use the usual retagging logic.
|
||||
// (The pointer type does not matter, so we use a raw pointer.)
|
||||
let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, return_place.layout.ty))?;
|
||||
let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
|
||||
// Reborrow it. With protection! That is part of the point.
|
||||
let new_perm = Some(NewPermission {
|
||||
let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, place.layout.ty))?;
|
||||
let ptr = ImmTy::from_immediate(place.to_ref(this), ptr_layout);
|
||||
// Reborrow it. With protection! That is the entire point.
|
||||
let new_perm = NewPermission {
|
||||
initial_state: Permission::new_active(),
|
||||
zero_size: false,
|
||||
protector: Some(ProtectorKind::StrongProtector),
|
||||
});
|
||||
let val = this.tb_retag_reference(&val, new_perm)?;
|
||||
// And use reborrowed pointer for return place.
|
||||
let return_place = this.ref_to_mplace(&val)?;
|
||||
this.frame_mut().return_place = return_place.into();
|
||||
};
|
||||
let _new_ptr = this.tb_retag_reference(&ptr, new_perm)?;
|
||||
// We just throw away `new_ptr`, so nobody can access this memory while it is protected.
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ extern crate rustc_index;
|
|||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
extern crate rustc_target;
|
||||
extern crate either; // the one from rustc
|
||||
|
||||
// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
|
||||
// files.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use std::fmt;
|
|||
use std::path::Path;
|
||||
use std::process;
|
||||
|
||||
use either::Either;
|
||||
use rand::rngs::StdRng;
|
||||
use rand::SeedableRng;
|
||||
|
||||
|
|
@ -533,7 +534,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||
let target = &tcx.sess.target;
|
||||
match target.arch.as_ref() {
|
||||
"wasm32" | "wasm64" => 64 * 1024, // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances
|
||||
"aarch64" =>
|
||||
"aarch64" => {
|
||||
if target.options.vendor.as_ref() == "apple" {
|
||||
// No "definitive" source, but see:
|
||||
// https://www.wwdcnotes.com/notes/wwdc20/10214/
|
||||
|
|
@ -541,7 +542,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
|
|||
16 * 1024
|
||||
} else {
|
||||
4 * 1024
|
||||
},
|
||||
}
|
||||
}
|
||||
_ => 4 * 1024,
|
||||
}
|
||||
};
|
||||
|
|
@ -892,7 +894,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||
ecx: &mut MiriInterpCx<'mir, 'tcx>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
args: &[FnArg<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
unwind: mir::UnwindAction,
|
||||
|
|
@ -905,12 +907,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||
ecx: &mut MiriInterpCx<'mir, 'tcx>,
|
||||
fn_val: Dlsym,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
args: &[FnArg<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
_unwind: mir::UnwindAction,
|
||||
) -> InterpResult<'tcx> {
|
||||
ecx.call_dlsym(fn_val, abi, args, dest, ret)
|
||||
let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
|
||||
ecx.call_dlsym(fn_val, abi, &args, dest, ret)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
|
@ -1094,8 +1097,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||
ptr: Pointer<Self::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
match ptr.provenance {
|
||||
Provenance::Concrete { alloc_id, tag } =>
|
||||
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
|
||||
Provenance::Concrete { alloc_id, tag } => {
|
||||
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
|
||||
}
|
||||
Provenance::Wildcard => {
|
||||
// No need to do anything for wildcard pointers as
|
||||
// their provenances have already been previously exposed.
|
||||
|
|
@ -1206,6 +1210,25 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn protect_in_place_function_argument(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
place: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// We do need to write `uninit` so that even after the call ends, the former contents of
|
||||
// this place cannot be observed any more.
|
||||
ecx.write_uninit(place)?;
|
||||
// If we have a borrow tracker, we also have it set up protection so that all reads *and
|
||||
// writes* during this call are insta-UB.
|
||||
if ecx.machine.borrow_tracker.is_some() {
|
||||
if let Either::Left(place) = place.as_mplace_or_local() {
|
||||
ecx.protect_place(&place)?;
|
||||
} else {
|
||||
// Locals that don't have their address taken are as protected as they can ever be.
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn init_frame_extra(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
|
|
@ -1288,8 +1311,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||
let stack_len = ecx.active_thread_stack().len();
|
||||
ecx.active_thread_mut().set_top_user_relevant_frame(stack_len - 1);
|
||||
}
|
||||
if ecx.machine.borrow_tracker.is_some() {
|
||||
ecx.retag_return_place()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn before_stack_pop(
|
||||
ecx: &InterpCx<'mir, 'tcx, Self>,
|
||||
frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// We want this *before* the return value copy, because the return place itself is protected
|
||||
// until we do `end_call` here.
|
||||
if let Some(borrow_tracker) = &ecx.machine.borrow_tracker {
|
||||
borrow_tracker.borrow_mut().end_call(&frame.extra);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1308,9 +1340,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
|
|||
ecx.active_thread_mut().recompute_top_user_relevant_frame();
|
||||
}
|
||||
let timing = frame.extra.timing.take();
|
||||
if let Some(borrow_tracker) = &ecx.machine.borrow_tracker {
|
||||
borrow_tracker.borrow_mut().end_call(&frame.extra);
|
||||
}
|
||||
let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding);
|
||||
if let Some(profiler) = ecx.machine.profiler.as_ref() {
|
||||
profiler.finish_recording_interval_event(timing.unwrap());
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
args: &[FnArg<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
unwind: mir::UnwindAction,
|
||||
|
|
@ -41,7 +41,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
|
||||
// There are some more lang items we want to hook that CTFE does not hook (yet).
|
||||
if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) {
|
||||
let [ptr, align] = check_arg_count(args)?;
|
||||
let args = this.copy_fn_args(args)?;
|
||||
let [ptr, align] = check_arg_count(&args)?;
|
||||
if this.align_offset(ptr, align, dest, ret, unwind)? {
|
||||
return Ok(None);
|
||||
}
|
||||
|
|
@ -55,7 +56,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
|||
// to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
|
||||
// foreign function
|
||||
// Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
|
||||
return this.emulate_foreign_item(instance.def_id(), abi, args, dest, ret, unwind);
|
||||
let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
|
||||
return this.emulate_foreign_item(instance.def_id(), abi, &args, dest, ret, unwind);
|
||||
}
|
||||
|
||||
// Otherwise, load the MIR.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
//@revisions: stack tree
|
||||
//@[tree]compile-flags: -Zmiri-tree-borrows
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
use std::intrinsics::mir::*;
|
||||
|
||||
pub struct S(i32);
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
fn main() {
|
||||
mir! {
|
||||
let unit: ();
|
||||
{
|
||||
let non_copy = S(42);
|
||||
let ptr = std::ptr::addr_of_mut!(non_copy);
|
||||
// Inside `callee`, the first argument and `*ptr` are basically
|
||||
// aliasing places!
|
||||
Call(unit, after_call, callee(Move(*ptr), ptr))
|
||||
}
|
||||
after_call = {
|
||||
Return()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn callee(x: S, ptr: *mut S) {
|
||||
// With the setup above, if `x` is indeed moved in
|
||||
// (i.e. we actually just get a pointer to the underlying storage),
|
||||
// then writing to `ptr` will change the value stored in `x`!
|
||||
unsafe { ptr.write(S(0)) };
|
||||
//~[stack]^ ERROR: not granting access
|
||||
//~[tree]| ERROR: /write access .* forbidden/
|
||||
assert_eq!(x.0, 42);
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.write(S(0)) };
|
||||
| ^^^^^^^^^^^^^^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
|
||||
|
|
||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||
help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | / mir! {
|
||||
LL | | let unit: ();
|
||||
LL | | {
|
||||
LL | | let non_copy = S(42);
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^
|
||||
help: <TAG> is this argument
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.write(S(0)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `callee` at $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | Call(unit, after_call, callee(Move(*ptr), ptr))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
error: Undefined Behavior: write access through <TAG> (root of the allocation) is forbidden
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.write(S(0)) };
|
||||
| ^^^^^^^^^^^^^^^ write access through <TAG> (root of the allocation) is forbidden
|
||||
|
|
||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
|
||||
= help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
|
||||
= help: this foreign write access would cause the protected tag <TAG> to transition from Active to Disabled
|
||||
= help: this transition would be a loss of read and write permissions, which is not allowed for protected tags
|
||||
help: the accessed tag <TAG> was created here
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | / mir! {
|
||||
LL | | let unit: ();
|
||||
LL | | {
|
||||
LL | | let non_copy = S(42);
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^
|
||||
help: the protected tag <TAG> was created here, in the initial state Active
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.write(S(0)) };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `callee` at $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_mutate.rs:LL:CC
|
||||
|
|
||||
LL | Call(unit, after_call, callee(Move(*ptr), ptr))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#![feature(custom_mir, core_intrinsics)]
|
||||
use std::intrinsics::mir::*;
|
||||
|
||||
pub struct S(i32);
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
fn main() {
|
||||
// FIXME: the span is not great (probably caused by custom MIR)
|
||||
mir! { //~ERROR: uninitialized
|
||||
let unit: ();
|
||||
{
|
||||
let non_copy = S(42);
|
||||
// This could change `non_copy` in-place
|
||||
Call(unit, after_call, change_arg(Move(non_copy)))
|
||||
}
|
||||
after_call = {
|
||||
// So now we must not be allowed to observe non-copy again.
|
||||
let _observe = non_copy.0;
|
||||
Return()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn change_arg(mut x: S) {
|
||||
x.0 = 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
|
||||
--> $DIR/arg_inplace_observe_after.rs:LL:CC
|
||||
|
|
||||
LL | / mir! {
|
||||
LL | | let unit: ();
|
||||
LL | | {
|
||||
LL | | let non_copy = S(42);
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^ using uninitialized data, but this operation requires initialized memory
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `main` at RUSTLIB/core/src/intrinsics/mir.rs:LL:CC
|
||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.read() };
|
||||
| ^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | Call(unit, after_call, change_arg(Move(*ptr), ptr))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
//@revisions: stack tree none
|
||||
//@[tree]compile-flags: -Zmiri-tree-borrows
|
||||
//@[none]compile-flags: -Zmiri-disable-stacked-borrows
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
use std::intrinsics::mir::*;
|
||||
|
||||
pub struct S(i32);
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
fn main() {
|
||||
mir! {
|
||||
let unit: ();
|
||||
{
|
||||
let non_copy = S(42);
|
||||
let ptr = std::ptr::addr_of_mut!(non_copy);
|
||||
// This could change `non_copy` in-place
|
||||
Call(unit, after_call, change_arg(Move(*ptr), ptr))
|
||||
}
|
||||
after_call = {
|
||||
Return()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn change_arg(mut x: S, ptr: *mut S) {
|
||||
x.0 = 0;
|
||||
// If `x` got passed in-place, we'd see the write through `ptr`!
|
||||
// Make sure we are not allowed to do that read.
|
||||
unsafe { ptr.read() };
|
||||
//~[stack]^ ERROR: not granting access
|
||||
//~[tree]| ERROR: /read access .* forbidden/
|
||||
//~[none]| ERROR: uninitialized
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.read() };
|
||||
| ^^^^^^^^^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
|
||||
|
|
||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||
help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | / mir! {
|
||||
LL | | let unit: ();
|
||||
LL | | {
|
||||
LL | | let non_copy = S(42);
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^
|
||||
help: <TAG> is this argument
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | x.0 = 0;
|
||||
| ^^^^^^^
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | Call(unit, after_call, change_arg(Move(*ptr), ptr))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
error: Undefined Behavior: read access through <TAG> (root of the allocation) is forbidden
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.read() };
|
||||
| ^^^^^^^^^^ read access through <TAG> (root of the allocation) is forbidden
|
||||
|
|
||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
|
||||
= help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
|
||||
= help: this foreign read access would cause the protected tag <TAG> to transition from Active to Frozen
|
||||
= help: this transition would be a loss of write permissions, which is not allowed for protected tags
|
||||
help: the accessed tag <TAG> was created here
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | / mir! {
|
||||
LL | | let unit: ();
|
||||
LL | | {
|
||||
LL | | let non_copy = S(42);
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____^
|
||||
help: the protected tag <TAG> was created here, in the initial state Active
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | x.0 = 0;
|
||||
| ^^^^^^^
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/arg_inplace_observe_during.rs:LL:CC
|
||||
|
|
||||
LL | Call(unit, after_call, change_arg(Move(*ptr), ptr))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
|
||||
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.read() };
|
||||
| ^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
= note: BACKTRACE:
|
||||
= note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
note: inside `main`
|
||||
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
|
|
||||
LL | Call(*ptr, after_call, myfun(ptr))
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
//@revisions: stack tree
|
||||
//@revisions: stack tree none
|
||||
//@[tree]compile-flags: -Zmiri-tree-borrows
|
||||
//@[none]compile-flags: -Zmiri-disable-stacked-borrows
|
||||
#![feature(raw_ref_op)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(custom_mir)]
|
||||
|
||||
use std::intrinsics::mir::*;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
pub fn main() {
|
||||
|
|
@ -25,8 +25,10 @@ pub fn main() {
|
|||
}
|
||||
|
||||
fn myfun(ptr: *mut i32) -> i32 {
|
||||
unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
|
||||
//~[stack]^ ERROR: /not granting access/
|
||||
unsafe { ptr.read() };
|
||||
//~[stack]^ ERROR: not granting access
|
||||
//~[tree]| ERROR: /read access .* forbidden/
|
||||
//~[none]| ERROR: uninitialized
|
||||
// Without an aliasing model, reads are "fine" but at least they return uninit data.
|
||||
13
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
|
||||
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
|
||||
LL | unsafe { ptr.read() };
|
||||
| ^^^^^^^^^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
|
||||
|
|
||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||
|
|
@ -20,13 +20,8 @@ LL | | }
|
|||
help: <TAG> is this argument
|
||||
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
|
|
||||
LL | / fn myfun(ptr: *mut i32) -> i32 {
|
||||
LL | | unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | 13
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | unsafe { ptr.read() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
note: inside `main`
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
error: Undefined Behavior: read access through <TAG> (root of the allocation) is forbidden
|
||||
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
|
|
||||
LL | unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ read access through <TAG> (root of the allocation) is forbidden
|
||||
LL | unsafe { ptr.read() };
|
||||
| ^^^^^^^^^^ read access through <TAG> (root of the allocation) is forbidden
|
||||
|
|
||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
|
||||
= help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
|
||||
|
|
@ -22,13 +22,8 @@ LL | | }
|
|||
help: the protected tag <TAG> was created here, in the initial state Active
|
||||
--> $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
|
|
||||
LL | / fn myfun(ptr: *mut i32) -> i32 {
|
||||
LL | | unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | 13
|
||||
LL | | }
|
||||
| |_^
|
||||
LL | unsafe { ptr.read() };
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: BACKTRACE (of the first span):
|
||||
= note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC
|
||||
note: inside `main`
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
// should find the bug even without validation and stacked borrows, but gets masked by optimizations
|
||||
//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no
|
||||
// should find the bug even without, but gets masked by optimizations
|
||||
//@compile-flags: -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no
|
||||
//@normalize-stderr-test: "but found [0-9]+" -> "but found $$ALIGN"
|
||||
|
||||
#[repr(align(256))]
|
||||
#[derive(Debug)]
|
||||
|
|
@ -19,6 +20,6 @@ fn main() {
|
|||
(&mut ptr as *mut _ as *mut *const u8).write(&buf as *const _ as *const u8);
|
||||
}
|
||||
// Re-borrow that. This should be UB.
|
||||
let _ptr = &*ptr; //~ERROR: alignment 256 is required
|
||||
let _ptr = &*ptr; //~ERROR: required 256 byte alignment
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
|
||||
error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required 256 byte alignment but found $ALIGN)
|
||||
--> $DIR/dyn_alignment.rs:LL:CC
|
||||
|
|
||||
LL | let _ptr = &*ptr;
|
||||
| ^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
|
||||
| ^^^^^ constructing invalid value: encountered an unaligned reference (required 256 byte alignment but found $ALIGN)
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
#![feature(raw_ref_op)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(custom_mir)]
|
||||
|
||||
use std::intrinsics::mir::*;
|
||||
|
||||
// Make sure calls with the return place "on the heap" work.
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
pub fn main() {
|
||||
mir! {
|
||||
{
|
||||
let x = 0;
|
||||
let ptr = &raw mut x;
|
||||
Call(*ptr, after_call, myfun())
|
||||
}
|
||||
|
||||
after_call = {
|
||||
Return()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn myfun() -> i32 {
|
||||
13
|
||||
}
|
||||
|
|
@ -5,5 +5,4 @@ edition = "2021"
|
|||
license = "Apache-2.0/MIT"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.143", features = ["derive"] }
|
||||
serde_json = "1.0.83"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
//! This is a small stub that replaces RLS to alert the user that RLS is no
|
||||
//! longer available.
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use std::error::Error;
|
||||
use std::io::BufRead;
|
||||
use std::io::Write;
|
||||
|
|
@ -21,7 +21,6 @@ fn main() {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Message {
|
||||
method: Option<String>,
|
||||
}
|
||||
|
|
@ -88,8 +87,10 @@ fn read_message_raw<R: BufRead>(reader: &mut R) -> Result<String, Box<dyn Error>
|
|||
|
||||
fn read_message<R: BufRead>(reader: &mut R) -> Result<Message, Box<dyn Error>> {
|
||||
let m = read_message_raw(reader)?;
|
||||
match serde_json::from_str(&m) {
|
||||
Ok(m) => Ok(m),
|
||||
match serde_json::from_str::<Value>(&m) {
|
||||
Ok(message) => Ok(Message {
|
||||
method: message.get("method").and_then(|value| value.as_str().map(String::from)),
|
||||
}),
|
||||
Err(e) => Err(format!("failed to parse message {m}\n{e}").into()),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ const EXCEPTION_PATHS: &[&str] = &[
|
|||
"library/panic_unwind",
|
||||
"library/unwind",
|
||||
"library/rtstartup", // Not sure what to do about this. magic stuff for mingw
|
||||
"library/term", // Not sure how to make this crate portable, but test crate needs it.
|
||||
"library/test", // Probably should defer to unstable `std::sys` APIs.
|
||||
// The `VaList` implementation must have platform specific code.
|
||||
// The Windows implementation of a `va_list` is always a character
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue