Auto merge of #123264 - matthiaskrgr:rollup-smyy7j9, r=matthiaskrgr
Rollup of 4 pull requests Successful merges: - #123189 (Log BOLT args in bootstrap `rustc` shim) - #123211 (Stop calling visitors `V`) - #123242 (pattern analysis: Require enum indices to be contiguous) - #123260 (Miri subtree update) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
395f780cd8
28 changed files with 262 additions and 267 deletions
|
@ -540,19 +540,23 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Suggest `map[k] = v` => `map.insert(k, v)` and the like.
|
||||||
fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'tcx>, span: Span) {
|
fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diag<'tcx>, span: Span) {
|
||||||
let Some(adt) = ty.ty_adt_def() else { return };
|
let Some(adt) = ty.ty_adt_def() else { return };
|
||||||
let did = adt.did();
|
let did = adt.did();
|
||||||
if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did)
|
if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did)
|
||||||
|| self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did)
|
|| self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did)
|
||||||
{
|
{
|
||||||
struct V<'a, 'tcx> {
|
/// Walks through the HIR, looking for the corresponding span for this error.
|
||||||
|
/// When it finds it, see if it corresponds to assignment operator whose LHS
|
||||||
|
/// is an index expr.
|
||||||
|
struct SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> {
|
||||||
assign_span: Span,
|
assign_span: Span,
|
||||||
err: &'a mut Diag<'tcx>,
|
err: &'a mut Diag<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
suggested: bool,
|
suggested: bool,
|
||||||
}
|
}
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for SuggestIndexOperatorAlternativeVisitor<'a, 'tcx> {
|
||||||
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
|
fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
|
||||||
hir::intravisit::walk_stmt(self, stmt);
|
hir::intravisit::walk_stmt(self, stmt);
|
||||||
let expr = match stmt.kind {
|
let expr = match stmt.kind {
|
||||||
|
@ -645,7 +649,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return };
|
let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return };
|
||||||
let body = self.infcx.tcx.hir().body(body_id);
|
let body = self.infcx.tcx.hir().body(body_id);
|
||||||
|
|
||||||
let mut v = V { assign_span: span, err, ty, suggested: false };
|
let mut v = SuggestIndexOperatorAlternativeVisitor {
|
||||||
|
assign_span: span,
|
||||||
|
err,
|
||||||
|
ty,
|
||||||
|
suggested: false,
|
||||||
|
};
|
||||||
v.visit_body(body);
|
v.visit_body(body);
|
||||||
if !v.suggested {
|
if !v.suggested {
|
||||||
err.help(format!(
|
err.help(format!(
|
||||||
|
|
|
@ -418,8 +418,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
|
if let &hir::ClosureBinder::For { span: for_sp, .. } = binder {
|
||||||
fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
|
fn span_of_infer(ty: &hir::Ty<'_>) -> Option<Span> {
|
||||||
struct V;
|
/// Look for `_` anywhere in the signature of a `for<> ||` closure.
|
||||||
impl<'v> Visitor<'v> for V {
|
/// This is currently disallowed.
|
||||||
|
struct FindInferInClosureWithBinder;
|
||||||
|
impl<'v> Visitor<'v> for FindInferInClosureWithBinder {
|
||||||
type Result = ControlFlow<Span>;
|
type Result = ControlFlow<Span>;
|
||||||
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result {
|
fn visit_ty(&mut self, t: &'v hir::Ty<'v>) -> Self::Result {
|
||||||
if matches!(t.kind, hir::TyKind::Infer) {
|
if matches!(t.kind, hir::TyKind::Infer) {
|
||||||
|
@ -429,7 +431,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
V.visit_ty(ty).break_value()
|
FindInferInClosureWithBinder.visit_ty(ty).break_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
let infer_in_rt_sp = match fn_decl.output {
|
let infer_in_rt_sp = match fn_decl.output {
|
||||||
|
|
|
@ -1916,22 +1916,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pat: &'tcx hir::Pat<'tcx>,
|
pat: &'tcx hir::Pat<'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) {
|
) {
|
||||||
struct V {
|
|
||||||
pat_hir_ids: Vec<hir::HirId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for V {
|
|
||||||
fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
|
|
||||||
self.pat_hir_ids.push(p.hir_id);
|
|
||||||
hir::intravisit::walk_pat(self, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Err(guar) = ty.error_reported() {
|
if let Err(guar) = ty.error_reported() {
|
||||||
|
struct OverwritePatternsWithError {
|
||||||
|
pat_hir_ids: Vec<hir::HirId>,
|
||||||
|
}
|
||||||
|
impl<'tcx> Visitor<'tcx> for OverwritePatternsWithError {
|
||||||
|
fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) {
|
||||||
|
self.pat_hir_ids.push(p.hir_id);
|
||||||
|
hir::intravisit::walk_pat(self, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Override the types everywhere with `err()` to avoid knock on errors.
|
// Override the types everywhere with `err()` to avoid knock on errors.
|
||||||
let err = Ty::new_error(self.tcx, guar);
|
let err = Ty::new_error(self.tcx, guar);
|
||||||
self.write_ty(hir_id, err);
|
self.write_ty(hir_id, err);
|
||||||
self.write_ty(pat.hir_id, err);
|
self.write_ty(pat.hir_id, err);
|
||||||
let mut visitor = V { pat_hir_ids: vec![] };
|
let mut visitor = OverwritePatternsWithError { pat_hir_ids: vec![] };
|
||||||
hir::intravisit::walk_pat(&mut visitor, pat);
|
hir::intravisit::walk_pat(&mut visitor, pat);
|
||||||
// Mark all the subpatterns as `{type error}` as well. This allows errors for specific
|
// Mark all the subpatterns as `{type error}` as well. This allows errors for specific
|
||||||
// subpatterns to be silenced.
|
// subpatterns to be silenced.
|
||||||
|
|
|
@ -155,13 +155,13 @@ use std::iter::once;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
|
use rustc_apfloat::ieee::{DoubleS, IeeeFloat, SingleS};
|
||||||
use rustc_index::bit_set::GrowableBitSet;
|
use rustc_index::bit_set::{BitSet, GrowableBitSet};
|
||||||
|
use rustc_index::IndexVec;
|
||||||
|
|
||||||
use self::Constructor::*;
|
use self::Constructor::*;
|
||||||
use self::MaybeInfiniteInt::*;
|
use self::MaybeInfiniteInt::*;
|
||||||
use self::SliceKind::*;
|
use self::SliceKind::*;
|
||||||
|
|
||||||
use crate::index;
|
|
||||||
use crate::PatCx;
|
use crate::PatCx;
|
||||||
|
|
||||||
/// Whether we have seen a constructor in the column or not.
|
/// Whether we have seen a constructor in the column or not.
|
||||||
|
@ -920,10 +920,7 @@ pub enum ConstructorSet<Cx: PatCx> {
|
||||||
Struct { empty: bool },
|
Struct { empty: bool },
|
||||||
/// This type has the following list of constructors. If `variants` is empty and
|
/// This type has the following list of constructors. If `variants` is empty and
|
||||||
/// `non_exhaustive` is false, don't use this; use `NoConstructors` instead.
|
/// `non_exhaustive` is false, don't use this; use `NoConstructors` instead.
|
||||||
Variants {
|
Variants { variants: IndexVec<Cx::VariantIdx, VariantVisibility>, non_exhaustive: bool },
|
||||||
variants: index::IdxContainer<Cx::VariantIdx, VariantVisibility>,
|
|
||||||
non_exhaustive: bool,
|
|
||||||
},
|
|
||||||
/// The type is `&T`.
|
/// The type is `&T`.
|
||||||
Ref,
|
Ref,
|
||||||
/// The type is a union.
|
/// The type is a union.
|
||||||
|
@ -1025,7 +1022,7 @@ impl<Cx: PatCx> ConstructorSet<Cx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConstructorSet::Variants { variants, non_exhaustive } => {
|
ConstructorSet::Variants { variants, non_exhaustive } => {
|
||||||
let mut seen_set = index::IdxSet::new_empty(variants.len());
|
let mut seen_set = BitSet::new_empty(variants.len());
|
||||||
for idx in seen.iter().filter_map(|c| c.as_variant()) {
|
for idx in seen.iter().filter_map(|c| c.as_variant()) {
|
||||||
seen_set.insert(idx);
|
seen_set.insert(idx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,50 +25,9 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[cfg(feature = "rustc")]
|
// Re-exports to avoid rustc_index version issues.
|
||||||
pub mod index {
|
pub use rustc_index::Idx;
|
||||||
// Faster version when the indices of variants are `0..variants.len()`.
|
pub use rustc_index::IndexVec;
|
||||||
pub use rustc_index::bit_set::BitSet as IdxSet;
|
|
||||||
pub use rustc_index::Idx;
|
|
||||||
pub use rustc_index::IndexVec as IdxContainer;
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "rustc"))]
|
|
||||||
pub mod index {
|
|
||||||
// Slower version when the indices of variants are something else.
|
|
||||||
pub trait Idx: Copy + PartialEq + Eq + std::hash::Hash {}
|
|
||||||
impl<T: Copy + PartialEq + Eq + std::hash::Hash> Idx for T {}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct IdxContainer<K, V>(pub rustc_hash::FxHashMap<K, V>);
|
|
||||||
impl<K: Idx, V> IdxContainer<K, V> {
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.0.len()
|
|
||||||
}
|
|
||||||
pub fn iter_enumerated(&self) -> impl Iterator<Item = (K, &V)> {
|
|
||||||
self.0.iter().map(|(k, v)| (*k, v))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V> FromIterator<V> for IdxContainer<usize, V> {
|
|
||||||
fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
|
|
||||||
Self(iter.into_iter().enumerate().collect())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct IdxSet<T>(pub rustc_hash::FxHashSet<T>);
|
|
||||||
impl<T: Idx> IdxSet<T> {
|
|
||||||
pub fn new_empty(_len: usize) -> Self {
|
|
||||||
Self(Default::default())
|
|
||||||
}
|
|
||||||
pub fn contains(&self, elem: T) -> bool {
|
|
||||||
self.0.contains(&elem)
|
|
||||||
}
|
|
||||||
pub fn insert(&mut self, elem: T) {
|
|
||||||
self.0.insert(elem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "rustc")]
|
#[cfg(feature = "rustc")]
|
||||||
use rustc_middle::ty::Ty;
|
use rustc_middle::ty::Ty;
|
||||||
|
@ -96,7 +55,7 @@ pub trait PatCx: Sized + fmt::Debug {
|
||||||
/// Errors that can abort analysis.
|
/// Errors that can abort analysis.
|
||||||
type Error: fmt::Debug;
|
type Error: fmt::Debug;
|
||||||
/// The index of an enum variant.
|
/// The index of an enum variant.
|
||||||
type VariantIdx: Clone + index::Idx + fmt::Debug;
|
type VariantIdx: Clone + Idx + fmt::Debug;
|
||||||
/// A string literal
|
/// A string literal
|
||||||
type StrLit: Clone + PartialEq + fmt::Debug;
|
type StrLit: Clone + PartialEq + fmt::Debug;
|
||||||
/// Extra data to store in a match arm.
|
/// Extra data to store in a match arm.
|
||||||
|
|
|
@ -1128,10 +1128,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
err: &mut Diag<'_>,
|
err: &mut Diag<'_>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let span = obligation.cause.span;
|
let span = obligation.cause.span;
|
||||||
struct V {
|
/// Look for the (direct) sub-expr of `?`, and return it if it's a `.` method call.
|
||||||
|
struct FindMethodSubexprOfTry {
|
||||||
search_span: Span,
|
search_span: Span,
|
||||||
}
|
}
|
||||||
impl<'v> Visitor<'v> for V {
|
impl<'v> Visitor<'v> for FindMethodSubexprOfTry {
|
||||||
type Result = ControlFlow<&'v hir::Expr<'v>>;
|
type Result = ControlFlow<&'v hir::Expr<'v>>;
|
||||||
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {
|
fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result {
|
||||||
if let hir::ExprKind::Match(expr, _arms, hir::MatchSource::TryDesugar(_)) = ex.kind
|
if let hir::ExprKind::Match(expr, _arms, hir::MatchSource::TryDesugar(_)) = ex.kind
|
||||||
|
@ -1149,8 +1150,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id,
|
hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) => body_id,
|
||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
let ControlFlow::Break(expr) =
|
let ControlFlow::Break(expr) = (FindMethodSubexprOfTry { search_span: span })
|
||||||
(V { search_span: span }).visit_body(self.tcx.hir().body(*body_id))
|
.visit_body(self.tcx.hir().body(*body_id))
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -220,6 +220,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if env::var_os("RUSTC_BOLT_LINK_FLAGS").is_some() {
|
||||||
|
if let Some("rustc_driver") = crate_name {
|
||||||
|
cmd.arg("-Clink-args=-Wl,-q");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let is_test = args.iter().any(|a| a == "--test");
|
let is_test = args.iter().any(|a| a == "--test");
|
||||||
if verbose > 2 {
|
if verbose > 2 {
|
||||||
let rust_env_vars =
|
let rust_env_vars =
|
||||||
|
@ -244,12 +250,6 @@ fn main() {
|
||||||
eprintln!("{prefix} libdir: {libdir:?}");
|
eprintln!("{prefix} libdir: {libdir:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if env::var_os("RUSTC_BOLT_LINK_FLAGS").is_some() {
|
|
||||||
if let Some("rustc_driver") = crate_name {
|
|
||||||
cmd.arg("-Clink-args=-Wl,-q");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bin_helpers::maybe_dump(format!("stage{stage}-rustc"), &cmd);
|
bin_helpers::maybe_dump(format!("stage{stage}-rustc"), &cmd);
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
|
@ -59,6 +59,7 @@ harness = false
|
||||||
[features]
|
[features]
|
||||||
default = ["stack-cache"]
|
default = ["stack-cache"]
|
||||||
stack-cache = []
|
stack-cache = []
|
||||||
|
stack-cache-consistency-check = ["stack-cache"]
|
||||||
|
|
||||||
# Be aware that this file is inside a workspace when used via the
|
# Be aware that this file is inside a workspace when used via the
|
||||||
# submodule in the rustc repo. That means there are many cargo features
|
# submodule in the rustc repo. That means there are many cargo features
|
||||||
|
|
|
@ -179,18 +179,27 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
cmd.env("RUSTC_WRAPPER", &cargo_miri_path);
|
cmd.env("RUSTC_WRAPPER", &cargo_miri_path);
|
||||||
|
// There's also RUSTC_WORKSPACE_WRAPPER, which gets in the way of our own wrapping.
|
||||||
|
if env::var_os("RUSTC_WORKSPACE_WRAPPER").is_some() {
|
||||||
|
println!(
|
||||||
|
"WARNING: Ignoring `RUSTC_WORKSPACE_WRAPPER` environment variable, Miri does not support wrapping."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
cmd.env_remove("RUSTC_WORKSPACE_WRAPPER");
|
||||||
// We are going to invoke `MIRI` for everything, not `RUSTC`.
|
// We are going to invoke `MIRI` for everything, not `RUSTC`.
|
||||||
if env::var_os("RUSTC").is_some() && env::var_os("MIRI").is_none() {
|
if env::var_os("RUSTC").is_some() && env::var_os("MIRI").is_none() {
|
||||||
println!(
|
println!(
|
||||||
"WARNING: Ignoring `RUSTC` environment variable; set `MIRI` if you want to control the binary used as the driver."
|
"WARNING: Ignoring `RUSTC` environment variable; set `MIRI` if you want to control the binary used as the driver."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Build scripts (and also cargo: https://github.com/rust-lang/cargo/issues/10885) will invoke
|
// Ideally we would set RUSTC to some non-existent path, so we can be sure our wrapping is
|
||||||
// `rustc` even when `RUSTC_WRAPPER` is set. To make sure everything is coherent, we want that
|
// always applied. However, buggy build scripts (https://github.com/eyre-rs/eyre/issues/84) and
|
||||||
// to be the Miri driver, but acting as rustc, on the target level. (Target, rather than host,
|
// also cargo (https://github.com/rust-lang/cargo/issues/10885) will invoke `rustc` even when
|
||||||
// is needed for cross-interpretation situations.) This is not a perfect emulation of real rustc
|
// `RUSTC_WRAPPER` is set, bypassing the wrapper. To make sure everything is coherent, we want
|
||||||
// (it might be unable to produce binaries since the sysroot is check-only), but it's as close
|
// that to be the Miri driver, but acting as rustc, on the target level. (Target, rather than
|
||||||
// as we can get, and it's good enough for autocfg.
|
// host, is needed for cross-interpretation situations.) This is not a perfect emulation of real
|
||||||
|
// rustc (it might be unable to produce binaries since the sysroot is check-only), but it's as
|
||||||
|
// close as we can get, and it's good enough for autocfg.
|
||||||
//
|
//
|
||||||
// In `main`, we need the value of `RUSTC` to distinguish RUSTC_WRAPPER invocations from rustdoc
|
// In `main`, we need the value of `RUSTC` to distinguish RUSTC_WRAPPER invocations from rustdoc
|
||||||
// or TARGET_RUNNER invocations, so we canonicalize it here to make it exceedingly unlikely that
|
// or TARGET_RUNNER invocations, so we canonicalize it here to make it exceedingly unlikely that
|
||||||
|
@ -247,6 +256,16 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
|
||||||
/// Cargo does not give us this information directly, so we need to check
|
/// Cargo does not give us this information directly, so we need to check
|
||||||
/// various command-line flags.
|
/// various command-line flags.
|
||||||
fn is_runnable_crate() -> bool {
|
fn is_runnable_crate() -> bool {
|
||||||
|
// Determine whether this is cargo invoking rustc to get some infos. Ideally we'd check "is
|
||||||
|
// there a filename passed to rustc", but that's very hard as we would have to know whether
|
||||||
|
// e.g. `--print foo` is a booolean flag `--print` followed by filename `foo` or equivalent
|
||||||
|
// to `--print=foo`. So instead we use this more fragile approach of detecting the presence
|
||||||
|
// of a "query" flag rather than the absence of a filename.
|
||||||
|
let info_query = get_arg_flag_value("--print").is_some() || has_arg_flag("-vV");
|
||||||
|
if info_query {
|
||||||
|
// Nothing to run.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
let is_bin = get_arg_flag_value("--crate-type").as_deref().unwrap_or("bin") == "bin";
|
let is_bin = get_arg_flag_value("--crate-type").as_deref().unwrap_or("bin") == "bin";
|
||||||
let is_test = has_arg_flag("--test");
|
let is_test = has_arg_flag("--test");
|
||||||
is_bin || is_test
|
is_bin || is_test
|
||||||
|
@ -285,16 +304,9 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// phase_cargo_miri set `MIRI_BE_RUSTC` for when build scripts directly invoke the driver;
|
|
||||||
// however, if we get called back by cargo here, we'll carefully compute the right flags
|
|
||||||
// ourselves, so we first un-do what the earlier phase did.
|
|
||||||
env::remove_var("MIRI_BE_RUSTC");
|
|
||||||
|
|
||||||
let verbose = std::env::var("MIRI_VERBOSE")
|
let verbose = std::env::var("MIRI_VERBOSE")
|
||||||
.map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
|
.map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
|
||||||
let target_crate = is_target_crate();
|
let target_crate = is_target_crate();
|
||||||
// Determine whether this is cargo invoking rustc to get some infos.
|
|
||||||
let info_query = get_arg_flag_value("--print").is_some() || has_arg_flag("-vV");
|
|
||||||
|
|
||||||
let store_json = |info: CrateRunInfo| {
|
let store_json = |info: CrateRunInfo| {
|
||||||
if get_arg_flag_value("--emit").unwrap_or_default().split(',').any(|e| e == "dep-info") {
|
if get_arg_flag_value("--emit").unwrap_or_default().split(',').any(|e| e == "dep-info") {
|
||||||
|
@ -321,7 +333,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let runnable_crate = !info_query && is_runnable_crate();
|
let runnable_crate = is_runnable_crate();
|
||||||
|
|
||||||
if runnable_crate && target_crate {
|
if runnable_crate && target_crate {
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -395,7 +407,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
|
||||||
let mut emit_link_hack = false;
|
let mut emit_link_hack = false;
|
||||||
// Arguments are treated very differently depending on whether this crate is
|
// Arguments are treated very differently depending on whether this crate is
|
||||||
// for interpretation by Miri, or for use by a build script / proc macro.
|
// for interpretation by Miri, or for use by a build script / proc macro.
|
||||||
if !info_query && target_crate {
|
if target_crate {
|
||||||
// Forward arguments, but remove "link" from "--emit" to make this a check-only build.
|
// Forward arguments, but remove "link" from "--emit" to make this a check-only build.
|
||||||
let emit_flag = "--emit";
|
let emit_flag = "--emit";
|
||||||
while let Some(arg) = args.next() {
|
while let Some(arg) = args.next() {
|
||||||
|
@ -429,17 +441,14 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
|
||||||
cmd.arg("-C").arg("panic=abort");
|
cmd.arg("-C").arg("panic=abort");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For host crates (but not when we are just printing some info),
|
// This is a host crate.
|
||||||
// we might still have to set the sysroot.
|
// When we're running `cargo-miri` from `x.py` we need to pass the sysroot explicitly
|
||||||
if !info_query {
|
// due to bootstrap complications.
|
||||||
// When we're running `cargo-miri` from `x.py` we need to pass the sysroot explicitly
|
if let Some(sysroot) = std::env::var_os("MIRI_HOST_SYSROOT") {
|
||||||
// due to bootstrap complications.
|
cmd.arg("--sysroot").arg(sysroot);
|
||||||
if let Some(sysroot) = std::env::var_os("MIRI_HOST_SYSROOT") {
|
|
||||||
cmd.arg("--sysroot").arg(sysroot);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For host crates or when we are printing, just forward everything.
|
// Forward everything.
|
||||||
cmd.args(args);
|
cmd.args(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,9 +460,7 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
|
||||||
|
|
||||||
// Run it.
|
// Run it.
|
||||||
if verbose > 0 {
|
if verbose > 0 {
|
||||||
eprintln!(
|
eprintln!("[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate}");
|
||||||
"[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate} info_query={info_query}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a stub .rlib file if "link" was requested by cargo.
|
// Create a stub .rlib file if "link" was requested by cargo.
|
||||||
|
@ -480,11 +487,6 @@ pub enum RunnerPhase {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: RunnerPhase) {
|
pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: RunnerPhase) {
|
||||||
// phase_cargo_miri set `MIRI_BE_RUSTC` for when build scripts directly invoke the driver;
|
|
||||||
// however, if we get called back by cargo here, we'll carefully compute the right flags
|
|
||||||
// ourselves, so we first un-do what the earlier phase did.
|
|
||||||
env::remove_var("MIRI_BE_RUSTC");
|
|
||||||
|
|
||||||
let verbose = std::env::var("MIRI_VERBOSE")
|
let verbose = std::env::var("MIRI_VERBOSE")
|
||||||
.map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
|
.map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer"));
|
||||||
|
|
||||||
|
@ -542,15 +544,13 @@ pub fn phase_runner(mut binary_args: impl Iterator<Item = String>, phase: Runner
|
||||||
// but when we run here, cargo does not interpret the JSON any more. `--json`
|
// but when we run here, cargo does not interpret the JSON any more. `--json`
|
||||||
// then also needs to be dropped.
|
// then also needs to be dropped.
|
||||||
let mut args = info.args.into_iter();
|
let mut args = info.args.into_iter();
|
||||||
let error_format_flag = "--error-format";
|
|
||||||
let json_flag = "--json";
|
|
||||||
while let Some(arg) = args.next() {
|
while let Some(arg) = args.next() {
|
||||||
if arg == "--extern" {
|
if arg == "--extern" {
|
||||||
forward_patched_extern_arg(&mut args, &mut cmd);
|
forward_patched_extern_arg(&mut args, &mut cmd);
|
||||||
} else if let Some(suffix) = arg.strip_prefix(error_format_flag) {
|
} else if let Some(suffix) = arg.strip_prefix("--error-format") {
|
||||||
assert!(suffix.starts_with('='));
|
assert!(suffix.starts_with('='));
|
||||||
// Drop this argument.
|
// Drop this argument.
|
||||||
} else if let Some(suffix) = arg.strip_prefix(json_flag) {
|
} else if let Some(suffix) = arg.strip_prefix("--json") {
|
||||||
assert!(suffix.starts_with('='));
|
assert!(suffix.starts_with('='));
|
||||||
// Drop this argument.
|
// Drop this argument.
|
||||||
} else {
|
} else {
|
||||||
|
@ -589,13 +589,11 @@ pub fn phase_rustdoc(mut args: impl Iterator<Item = String>) {
|
||||||
let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string());
|
let rustdoc = env::var("MIRI_ORIG_RUSTDOC").unwrap_or("rustdoc".to_string());
|
||||||
let mut cmd = Command::new(rustdoc);
|
let mut cmd = Command::new(rustdoc);
|
||||||
|
|
||||||
let extern_flag = "--extern";
|
|
||||||
let runtool_flag = "--runtool";
|
|
||||||
while let Some(arg) = args.next() {
|
while let Some(arg) = args.next() {
|
||||||
if arg == extern_flag {
|
if arg == "--extern" {
|
||||||
// Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
|
// Patch --extern arguments to use *.rmeta files, since phase_cargo_rustc only creates stub *.rlib files.
|
||||||
forward_patched_extern_arg(&mut args, &mut cmd);
|
forward_patched_extern_arg(&mut args, &mut cmd);
|
||||||
} else if arg == runtool_flag {
|
} else if arg == "--runtool" {
|
||||||
// An existing --runtool flag indicates cargo is running in cross-target mode, which we don't support.
|
// An existing --runtool flag indicates cargo is running in cross-target mode, which we don't support.
|
||||||
// Note that this is only passed when cargo is run with the unstable -Zdoctest-xcompile flag;
|
// Note that this is only passed when cargo is run with the unstable -Zdoctest-xcompile flag;
|
||||||
// otherwise, we won't be called as rustdoc at all.
|
// otherwise, we won't be called as rustdoc at all.
|
||||||
|
|
|
@ -101,7 +101,12 @@ pub fn find_miri() -> PathBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn miri() -> Command {
|
pub fn miri() -> Command {
|
||||||
Command::new(find_miri())
|
let mut cmd = Command::new(find_miri());
|
||||||
|
// We never want to inherit this from the environment.
|
||||||
|
// However, this is sometimes set in the environment to work around build scripts that don't
|
||||||
|
// honor RUSTC_WRAPPER. So remove it again in case it is set.
|
||||||
|
cmd.env_remove("MIRI_BE_RUSTC");
|
||||||
|
cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn miri_for_host() -> Command {
|
pub fn miri_for_host() -> Command {
|
||||||
|
|
|
@ -22,17 +22,24 @@ if [ "$HOST_TARGET" = i686-pc-windows-msvc ]; then
|
||||||
BASH="C:/Program Files/Git/usr/bin/bash"
|
BASH="C:/Program Files/Git/usr/bin/bash"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Determine configuration for installed build
|
# Global configuration
|
||||||
echo "Installing release version of Miri"
|
|
||||||
export RUSTFLAGS="-D warnings"
|
export RUSTFLAGS="-D warnings"
|
||||||
export CARGO_INCREMENTAL=0
|
export CARGO_INCREMENTAL=0
|
||||||
export CARGO_EXTRA_FLAGS="--locked"
|
export CARGO_EXTRA_FLAGS="--locked"
|
||||||
|
|
||||||
|
# Determine configuration for installed build
|
||||||
|
echo "Installing release version of Miri"
|
||||||
./miri install
|
./miri install
|
||||||
|
|
||||||
# Prepare debug build for direct `./miri` invocations
|
echo "Checking various feature flag configurations"
|
||||||
echo "Building debug version of Miri"
|
|
||||||
./miri check --no-default-features # make sure this can be built
|
./miri check --no-default-features # make sure this can be built
|
||||||
./miri check --all-features # and this, too
|
./miri check # and this, too
|
||||||
|
# `--all-features` is used for the build below, so no extra check needed.
|
||||||
|
|
||||||
|
# Prepare debug build for direct `./miri` invocations.
|
||||||
|
# We enable all features to make sure the Stacked Borrows consistency check runs.
|
||||||
|
echo "Building debug version of Miri"
|
||||||
|
export CARGO_EXTRA_FLAGS="$CARGO_EXTRA_FLAGS --all-features"
|
||||||
./miri build --all-targets # the build that all the `./miri test` below will use
|
./miri build --all-targets # the build that all the `./miri test` below will use
|
||||||
|
|
||||||
endgroup
|
endgroup
|
||||||
|
@ -46,8 +53,8 @@ function run_tests {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
## ui test suite
|
## ui test suite
|
||||||
# On the host and on Linux, also stress-test the GC.
|
# On the host, also stress-test the GC.
|
||||||
if [ -z "${MIRI_TEST_TARGET:-}" ] || [ "$HOST_TARGET" = x86_64-unknown-linux-gnu ]; then
|
if [ -z "${MIRI_TEST_TARGET:-}" ]; then
|
||||||
MIRIFLAGS="${MIRIFLAGS:-} -Zmiri-provenance-gc=1" ./miri test
|
MIRIFLAGS="${MIRIFLAGS:-} -Zmiri-provenance-gc=1" ./miri test
|
||||||
else
|
else
|
||||||
./miri test
|
./miri test
|
||||||
|
@ -130,6 +137,8 @@ case $HOST_TARGET in
|
||||||
MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests
|
MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests
|
||||||
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
|
MIRI_TEST_TARGET=aarch64-apple-darwin run_tests
|
||||||
MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
|
MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests
|
||||||
|
MIRI_TEST_TARGET=x86_64-pc-windows-gnu run_tests
|
||||||
|
MIRI_TEST_TARGET=arm-unknown-linux-gnueabi run_tests
|
||||||
# Some targets are only partially supported.
|
# Some targets are only partially supported.
|
||||||
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align num_cpus
|
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align num_cpus
|
||||||
MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align num_cpus
|
MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align num_cpus
|
||||||
|
@ -145,9 +154,7 @@ case $HOST_TARGET in
|
||||||
MIRI_TEST_TARGET=x86_64-pc-windows-msvc run_tests
|
MIRI_TEST_TARGET=x86_64-pc-windows-msvc run_tests
|
||||||
;;
|
;;
|
||||||
i686-pc-windows-msvc)
|
i686-pc-windows-msvc)
|
||||||
MIRI_TEST_TARGET=arm-unknown-linux-gnueabi run_tests
|
|
||||||
MIRI_TEST_TARGET=x86_64-unknown-linux-gnu run_tests
|
MIRI_TEST_TARGET=x86_64-unknown-linux-gnu run_tests
|
||||||
MIRI_TEST_TARGET=x86_64-pc-windows-gnu run_tests
|
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "FATAL: unknown OS"
|
echo "FATAL: unknown OS"
|
||||||
|
|
|
@ -479,10 +479,11 @@ impl Command {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(dep: bool, flags: Vec<OsString>) -> Result<()> {
|
fn run(dep: bool, mut flags: Vec<OsString>) -> Result<()> {
|
||||||
let mut e = MiriEnv::new()?;
|
let mut e = MiriEnv::new()?;
|
||||||
// Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
|
// Scan for "--target" to overwrite the "MIRI_TEST_TARGET" env var so
|
||||||
// that we set the MIRI_SYSROOT up the right way.
|
// that we set the MIRI_SYSROOT up the right way. We must make sure that
|
||||||
|
// MIRI_TEST_TARGET and `--target` are in sync.
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
let target = flags
|
let target = flags
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -493,33 +494,35 @@ impl Command {
|
||||||
// Found it!
|
// Found it!
|
||||||
e.sh.set_var("MIRI_TEST_TARGET", target);
|
e.sh.set_var("MIRI_TEST_TARGET", target);
|
||||||
} else if let Ok(target) = std::env::var("MIRI_TEST_TARGET") {
|
} else if let Ok(target) = std::env::var("MIRI_TEST_TARGET") {
|
||||||
// Make sure miri actually uses this target.
|
// Convert `MIRI_TEST_TARGET` into `--target`.
|
||||||
let miriflags = e.sh.var("MIRIFLAGS").unwrap_or_default();
|
flags.push("--target".into());
|
||||||
e.sh.set_var("MIRIFLAGS", format!("{miriflags} --target {target}"));
|
flags.push(target.into());
|
||||||
}
|
}
|
||||||
// Scan for "--edition" (we'll set one ourselves if that flag is not present).
|
// Scan for "--edition", set one ourselves if that flag is not present.
|
||||||
let have_edition =
|
let have_edition =
|
||||||
flags.iter().take_while(|arg| *arg != "--").any(|arg| *arg == "--edition");
|
flags.iter().take_while(|arg| *arg != "--").any(|arg| *arg == "--edition");
|
||||||
|
if !have_edition {
|
||||||
|
flags.push("--edition=2021".into()); // keep in sync with `tests/ui.rs`.`
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare a sysroot.
|
// Prepare a sysroot.
|
||||||
e.build_miri_sysroot(/* quiet */ true)?;
|
e.build_miri_sysroot(/* quiet */ true)?;
|
||||||
|
|
||||||
// Then run the actual command.
|
// Then run the actual command. Also add MIRIFLAGS.
|
||||||
let miri_manifest = path!(e.miri_dir / "Cargo.toml");
|
let miri_manifest = path!(e.miri_dir / "Cargo.toml");
|
||||||
let miri_flags = e.sh.var("MIRIFLAGS").unwrap_or_default();
|
let miri_flags = e.sh.var("MIRIFLAGS").unwrap_or_default();
|
||||||
let miri_flags = flagsplit(&miri_flags);
|
let miri_flags = flagsplit(&miri_flags);
|
||||||
let toolchain = &e.toolchain;
|
let toolchain = &e.toolchain;
|
||||||
let extra_flags = &e.cargo_extra_flags;
|
let extra_flags = &e.cargo_extra_flags;
|
||||||
let edition_flags = (!have_edition).then_some("--edition=2021"); // keep in sync with `tests/ui.rs`.`
|
|
||||||
if dep {
|
if dep {
|
||||||
cmd!(
|
cmd!(
|
||||||
e.sh,
|
e.sh,
|
||||||
"cargo +{toolchain} --quiet test {extra_flags...} --manifest-path {miri_manifest} --test ui -- --miri-run-dep-mode {miri_flags...} {edition_flags...} {flags...}"
|
"cargo +{toolchain} --quiet test {extra_flags...} --manifest-path {miri_manifest} --test ui -- --miri-run-dep-mode {miri_flags...} {flags...}"
|
||||||
).quiet().run()?;
|
).quiet().run()?;
|
||||||
} else {
|
} else {
|
||||||
cmd!(
|
cmd!(
|
||||||
e.sh,
|
e.sh,
|
||||||
"cargo +{toolchain} --quiet run {extra_flags...} --manifest-path {miri_manifest} -- {miri_flags...} {edition_flags...} {flags...}"
|
"cargo +{toolchain} --quiet run {extra_flags...} --manifest-path {miri_manifest} -- {miri_flags...} {flags...}"
|
||||||
).quiet().run()?;
|
).quiet().run()?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
cb7c63606e53715f94f3ba04d38e50772e4cd23d
|
5baf1e13f568b61e121953bf6a3d09faee7dd446
|
||||||
|
|
|
@ -146,7 +146,7 @@ impl<'tcx> Stack {
|
||||||
/// Panics if any of the caching mechanisms have broken,
|
/// Panics if any of the caching mechanisms have broken,
|
||||||
/// - The StackCache indices don't refer to the parallel items,
|
/// - The StackCache indices don't refer to the parallel items,
|
||||||
/// - There are no Unique items outside of first_unique..last_unique
|
/// - There are no Unique items outside of first_unique..last_unique
|
||||||
#[cfg(all(feature = "stack-cache", debug_assertions))]
|
#[cfg(feature = "stack-cache-consistency-check")]
|
||||||
fn verify_cache_consistency(&self) {
|
fn verify_cache_consistency(&self) {
|
||||||
// Only a full cache needs to be valid. Also see the comments in find_granting_cache
|
// Only a full cache needs to be valid. Also see the comments in find_granting_cache
|
||||||
// and set_unknown_bottom.
|
// and set_unknown_bottom.
|
||||||
|
@ -190,7 +190,7 @@ impl<'tcx> Stack {
|
||||||
tag: ProvenanceExtra,
|
tag: ProvenanceExtra,
|
||||||
exposed_tags: &FxHashSet<BorTag>,
|
exposed_tags: &FxHashSet<BorTag>,
|
||||||
) -> Result<Option<usize>, ()> {
|
) -> Result<Option<usize>, ()> {
|
||||||
#[cfg(all(feature = "stack-cache", debug_assertions))]
|
#[cfg(feature = "stack-cache-consistency-check")]
|
||||||
self.verify_cache_consistency();
|
self.verify_cache_consistency();
|
||||||
|
|
||||||
let ProvenanceExtra::Concrete(tag) = tag else {
|
let ProvenanceExtra::Concrete(tag) = tag else {
|
||||||
|
@ -327,7 +327,7 @@ impl<'tcx> Stack {
|
||||||
// This primes the cache for the next access, which is almost always the just-added tag.
|
// This primes the cache for the next access, which is almost always the just-added tag.
|
||||||
self.cache.add(new_idx, new);
|
self.cache.add(new_idx, new);
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(feature = "stack-cache-consistency-check")]
|
||||||
self.verify_cache_consistency();
|
self.verify_cache_consistency();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,7 +410,7 @@ impl<'tcx> Stack {
|
||||||
self.unique_range.end = self.unique_range.end.min(disable_start);
|
self.unique_range.end = self.unique_range.end.min(disable_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "stack-cache", debug_assertions))]
|
#[cfg(feature = "stack-cache-consistency-check")]
|
||||||
self.verify_cache_consistency();
|
self.verify_cache_consistency();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -465,7 +465,7 @@ impl<'tcx> Stack {
|
||||||
self.unique_range = 0..0;
|
self.unique_range = 0..0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "stack-cache", debug_assertions))]
|
#[cfg(feature = "stack-cache-consistency-check")]
|
||||||
self.verify_cache_consistency();
|
self.verify_cache_consistency();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,7 +365,7 @@ type S = &'static str;
|
||||||
/// Pretty-printing details
|
/// Pretty-printing details
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```
|
/// ```rust,ignore (private type)
|
||||||
/// DisplayFmtWrapper {
|
/// DisplayFmtWrapper {
|
||||||
/// top: '>',
|
/// top: '>',
|
||||||
/// bot: '<',
|
/// bot: '<',
|
||||||
|
@ -393,7 +393,7 @@ struct DisplayFmtWrapper {
|
||||||
/// Formating of the permissions on each range.
|
/// Formating of the permissions on each range.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```
|
/// ```rust,ignore (private type)
|
||||||
/// DisplayFmtPermission {
|
/// DisplayFmtPermission {
|
||||||
/// open: "[",
|
/// open: "[",
|
||||||
/// sep: "|",
|
/// sep: "|",
|
||||||
|
@ -425,7 +425,7 @@ struct DisplayFmtPermission {
|
||||||
/// Formating of the tree structure.
|
/// Formating of the tree structure.
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```
|
/// ```rust,ignore (private type)
|
||||||
/// DisplayFmtPadding {
|
/// DisplayFmtPadding {
|
||||||
/// join_middle: "|-",
|
/// join_middle: "|-",
|
||||||
/// join_last: "'-",
|
/// join_last: "'-",
|
||||||
|
@ -463,7 +463,7 @@ struct DisplayFmtPadding {
|
||||||
/// How to show whether a location has been accessed
|
/// How to show whether a location has been accessed
|
||||||
///
|
///
|
||||||
/// Example:
|
/// Example:
|
||||||
/// ```
|
/// ```rust,ignore (private type)
|
||||||
/// DisplayFmtAccess {
|
/// DisplayFmtAccess {
|
||||||
/// yes: " ",
|
/// yes: " ",
|
||||||
/// no: "?",
|
/// no: "?",
|
||||||
|
|
|
@ -181,8 +181,12 @@ impl Permission {
|
||||||
pub fn is_initial(&self) -> bool {
|
pub fn is_initial(&self) -> bool {
|
||||||
self.inner.is_initial()
|
self.inner.is_initial()
|
||||||
}
|
}
|
||||||
|
/// Check if `self` is the terminal state of a pointer (is `Disabled`).
|
||||||
|
pub fn is_disabled(&self) -> bool {
|
||||||
|
self.inner == Disabled
|
||||||
|
}
|
||||||
|
|
||||||
/// Default initial permission of the root of a new tree.
|
/// Default initial permission of the root of a new tree at inbounds positions.
|
||||||
/// Must *only* be used for the root, this is not in general an "initial" permission!
|
/// Must *only* be used for the root, this is not in general an "initial" permission!
|
||||||
pub fn new_active() -> Self {
|
pub fn new_active() -> Self {
|
||||||
Self { inner: Active }
|
Self { inner: Active }
|
||||||
|
@ -193,11 +197,17 @@ impl Permission {
|
||||||
Self { inner: Reserved { ty_is_freeze, conflicted: false } }
|
Self { inner: Reserved { ty_is_freeze, conflicted: false } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default initial permission of a reborrowed shared reference
|
/// Default initial permission of a reborrowed shared reference.
|
||||||
pub fn new_frozen() -> Self {
|
pub fn new_frozen() -> Self {
|
||||||
Self { inner: Frozen }
|
Self { inner: Frozen }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Default initial permission of the root of a new tre at out-of-bounds positions.
|
||||||
|
/// Must *only* be used for the root, this is not in general an "initial" permission!
|
||||||
|
pub fn new_disabled() -> Self {
|
||||||
|
Self { inner: Disabled }
|
||||||
|
}
|
||||||
|
|
||||||
/// Apply the transition to the inner PermissionPriv.
|
/// Apply the transition to the inner PermissionPriv.
|
||||||
pub fn perform_access(
|
pub fn perform_access(
|
||||||
kind: AccessKind,
|
kind: AccessKind,
|
||||||
|
|
|
@ -42,6 +42,7 @@ pub(super) struct LocationState {
|
||||||
/// protected, that is *not* the case for uninitialized locations. Instead we just have a latent
|
/// protected, that is *not* the case for uninitialized locations. Instead we just have a latent
|
||||||
/// "future initial permission" of `Disabled`, causing UB only if an access is ever actually
|
/// "future initial permission" of `Disabled`, causing UB only if an access is ever actually
|
||||||
/// performed.
|
/// performed.
|
||||||
|
/// Note that the tree root is also always initialized, as if the allocation was a write access.
|
||||||
initialized: bool,
|
initialized: bool,
|
||||||
/// This pointer's current permission / future initial permission.
|
/// This pointer's current permission / future initial permission.
|
||||||
permission: Permission,
|
permission: Permission,
|
||||||
|
@ -55,17 +56,18 @@ pub(super) struct LocationState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocationState {
|
impl LocationState {
|
||||||
/// Default initial state has never been accessed and has been subjected to no
|
/// Constructs a new initial state. It has neither been accessed, nor been subjected
|
||||||
/// foreign access.
|
/// to any foreign access yet.
|
||||||
fn new(permission: Permission) -> Self {
|
/// The permission is not allowed to be `Active`.
|
||||||
|
fn new_uninit(permission: Permission) -> Self {
|
||||||
|
assert!(permission.is_initial() || permission.is_disabled());
|
||||||
Self { permission, initialized: false, latest_foreign_access: None }
|
Self { permission, initialized: false, latest_foreign_access: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Record that this location was accessed through a child pointer by
|
/// Constructs a new initial state. It has not yet been subjected
|
||||||
/// marking it as initialized
|
/// to any foreign access. However, it is already marked as having been accessed.
|
||||||
fn with_access(mut self) -> Self {
|
fn new_init(permission: Permission) -> Self {
|
||||||
self.initialized = true;
|
Self { permission, initialized: true, latest_foreign_access: None }
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the location has been initialized, i.e. if it has
|
/// Check if the location has been initialized, i.e. if it has
|
||||||
|
@ -238,8 +240,10 @@ pub(super) struct Node {
|
||||||
/// If the pointer was reborrowed, it has children.
|
/// If the pointer was reborrowed, it has children.
|
||||||
// FIXME: bench to compare this to FxHashSet and to other SmallVec sizes
|
// FIXME: bench to compare this to FxHashSet and to other SmallVec sizes
|
||||||
pub children: SmallVec<[UniIndex; 4]>,
|
pub children: SmallVec<[UniIndex; 4]>,
|
||||||
/// Either `Reserved` or `Frozen`, the permission this tag will be lazily initialized
|
/// Either `Reserved`, `Frozen`, or `Disabled`, it is the permission this tag will
|
||||||
/// to on the first access.
|
/// lazily be initialized to on the first access.
|
||||||
|
/// It is only ever `Disabled` for a tree root, since the root is initialized to `Active` by
|
||||||
|
/// its own separate mechanism.
|
||||||
default_initial_perm: Permission,
|
default_initial_perm: Permission,
|
||||||
/// Some extra information useful only for debugging purposes
|
/// Some extra information useful only for debugging purposes
|
||||||
pub debug_info: NodeDebugInfo,
|
pub debug_info: NodeDebugInfo,
|
||||||
|
@ -444,12 +448,14 @@ impl<'tree> TreeVisitor<'tree> {
|
||||||
impl Tree {
|
impl Tree {
|
||||||
/// Create a new tree, with only a root pointer.
|
/// Create a new tree, with only a root pointer.
|
||||||
pub fn new(root_tag: BorTag, size: Size, span: Span) -> Self {
|
pub fn new(root_tag: BorTag, size: Size, span: Span) -> Self {
|
||||||
let root_perm = Permission::new_active();
|
// The root has `Disabled` as the default permission,
|
||||||
|
// so that any access out of bounds is invalid.
|
||||||
|
let root_default_perm = Permission::new_disabled();
|
||||||
let mut tag_mapping = UniKeyMap::default();
|
let mut tag_mapping = UniKeyMap::default();
|
||||||
let root_idx = tag_mapping.insert(root_tag);
|
let root_idx = tag_mapping.insert(root_tag);
|
||||||
let nodes = {
|
let nodes = {
|
||||||
let mut nodes = UniValMap::<Node>::default();
|
let mut nodes = UniValMap::<Node>::default();
|
||||||
let mut debug_info = NodeDebugInfo::new(root_tag, root_perm, span);
|
let mut debug_info = NodeDebugInfo::new(root_tag, root_default_perm, span);
|
||||||
// name the root so that all allocations contain one named pointer
|
// name the root so that all allocations contain one named pointer
|
||||||
debug_info.add_name("root of the allocation");
|
debug_info.add_name("root of the allocation");
|
||||||
nodes.insert(
|
nodes.insert(
|
||||||
|
@ -458,7 +464,7 @@ impl Tree {
|
||||||
tag: root_tag,
|
tag: root_tag,
|
||||||
parent: None,
|
parent: None,
|
||||||
children: SmallVec::default(),
|
children: SmallVec::default(),
|
||||||
default_initial_perm: root_perm,
|
default_initial_perm: root_default_perm,
|
||||||
debug_info,
|
debug_info,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -466,7 +472,11 @@ impl Tree {
|
||||||
};
|
};
|
||||||
let rperms = {
|
let rperms = {
|
||||||
let mut perms = UniValMap::default();
|
let mut perms = UniValMap::default();
|
||||||
perms.insert(root_idx, LocationState::new(root_perm).with_access());
|
// We manually set it to `Active` on all in-bounds positions.
|
||||||
|
// We also ensure that it is initalized, so that no `Active` but
|
||||||
|
// not yet initialized nodes exist. Essentially, we pretend there
|
||||||
|
// was a write that initialized these to `Active`.
|
||||||
|
perms.insert(root_idx, LocationState::new_init(Permission::new_active()));
|
||||||
RangeMap::new(size, perms)
|
RangeMap::new(size, perms)
|
||||||
};
|
};
|
||||||
Self { root: root_idx, nodes, rperms, tag_mapping }
|
Self { root: root_idx, nodes, rperms, tag_mapping }
|
||||||
|
@ -500,7 +510,7 @@ impl<'tcx> Tree {
|
||||||
// Register new_tag as a child of parent_tag
|
// Register new_tag as a child of parent_tag
|
||||||
self.nodes.get_mut(parent_idx).unwrap().children.push(idx);
|
self.nodes.get_mut(parent_idx).unwrap().children.push(idx);
|
||||||
// Initialize perms
|
// Initialize perms
|
||||||
let perm = LocationState::new(default_initial_perm).with_access();
|
let perm = LocationState::new_init(default_initial_perm);
|
||||||
for (_perms_range, perms) in self.rperms.iter_mut(reborrow_range.start, reborrow_range.size)
|
for (_perms_range, perms) in self.rperms.iter_mut(reborrow_range.start, reborrow_range.size)
|
||||||
{
|
{
|
||||||
perms.insert(idx, perm);
|
perms.insert(idx, perm);
|
||||||
|
@ -599,7 +609,7 @@ impl<'tcx> Tree {
|
||||||
-> Result<ContinueTraversal, TransitionError> {
|
-> Result<ContinueTraversal, TransitionError> {
|
||||||
let NodeAppArgs { node, mut perm, rel_pos } = args;
|
let NodeAppArgs { node, mut perm, rel_pos } = args;
|
||||||
|
|
||||||
let old_state = perm.or_insert(LocationState::new(node.default_initial_perm));
|
let old_state = perm.or_insert(LocationState::new_uninit(node.default_initial_perm));
|
||||||
|
|
||||||
match old_state.skip_if_known_noop(access_kind, rel_pos) {
|
match old_state.skip_if_known_noop(access_kind, rel_pos) {
|
||||||
ContinueTraversal::SkipChildren => return Ok(ContinueTraversal::SkipChildren),
|
ContinueTraversal::SkipChildren => return Ok(ContinueTraversal::SkipChildren),
|
||||||
|
|
|
@ -516,11 +516,11 @@ mod spurious_read {
|
||||||
let source = LocStateProtPair {
|
let source = LocStateProtPair {
|
||||||
xy_rel: RelPosXY::MutuallyForeign,
|
xy_rel: RelPosXY::MutuallyForeign,
|
||||||
x: LocStateProt {
|
x: LocStateProt {
|
||||||
state: LocationState::new(Permission::new_frozen()).with_access(),
|
state: LocationState::new_init(Permission::new_frozen()),
|
||||||
prot: true,
|
prot: true,
|
||||||
},
|
},
|
||||||
y: LocStateProt {
|
y: LocStateProt {
|
||||||
state: LocationState::new(Permission::new_reserved(false)),
|
state: LocationState::new_uninit(Permission::new_reserved(false)),
|
||||||
prot: true,
|
prot: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -132,7 +132,7 @@ where
|
||||||
/// the associated `UniIndex` from ALL `UniValMap`s.
|
/// the associated `UniIndex` from ALL `UniValMap`s.
|
||||||
///
|
///
|
||||||
/// Example of such behavior:
|
/// Example of such behavior:
|
||||||
/// ```
|
/// ```rust,ignore (private type can't be doctested)
|
||||||
/// let mut keymap = UniKeyMap::<char>::default();
|
/// let mut keymap = UniKeyMap::<char>::default();
|
||||||
/// let mut valmap = UniValMap::<char>::default();
|
/// let mut valmap = UniValMap::<char>::default();
|
||||||
/// // Insert 'a' -> _ -> 'A'
|
/// // Insert 'a' -> _ -> 'A'
|
||||||
|
|
|
@ -1046,7 +1046,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
|
||||||
/// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
|
/// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
|
||||||
/// termination).
|
/// termination).
|
||||||
fn run_threads(&mut self) -> InterpResult<'tcx, !> {
|
fn run_threads(&mut self) -> InterpResult<'tcx, !> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
loop {
|
loop {
|
||||||
if CTRL_C_RECEIVED.load(Relaxed) {
|
if CTRL_C_RECEIVED.load(Relaxed) {
|
||||||
this.machine.handle_abnormal_termination();
|
this.machine.handle_abnormal_termination();
|
||||||
|
|
|
@ -2,17 +2,11 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "anyhow"
|
|
||||||
version = "1.0.81"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
|
@ -22,33 +16,33 @@ checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cargo-miri-test"
|
name = "cargo-miri-test"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"byteorder 0.5.3",
|
"byteorder 0.5.3",
|
||||||
"byteorder 1.4.3",
|
"byteorder 1.5.0",
|
||||||
"cdylib",
|
"cdylib",
|
||||||
"exported_symbol",
|
"exported_symbol",
|
||||||
|
"eyre",
|
||||||
"issue_1567",
|
"issue_1567",
|
||||||
"issue_1691",
|
"issue_1691",
|
||||||
"issue_1705",
|
"issue_1705",
|
||||||
"issue_1760",
|
|
||||||
"issue_rust_86261",
|
"issue_rust_86261",
|
||||||
"serde_derive",
|
"proc-macro2",
|
||||||
|
"proc_macro_crate",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cdylib"
|
name = "cdylib"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.4.3",
|
"byteorder 1.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -62,11 +56,27 @@ dependencies = [
|
||||||
name = "exported_symbol_dep"
|
name = "exported_symbol_dep"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "eyre"
|
||||||
|
version = "0.6.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
|
||||||
|
dependencies = [
|
||||||
|
"indenter",
|
||||||
|
"once_cell",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indenter"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "issue_1567"
|
name = "issue_1567"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.4.3",
|
"byteorder 1.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -77,66 +87,44 @@ version = "0.1.0"
|
||||||
name = "issue_1705"
|
name = "issue_1705"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.4.3",
|
"byteorder 1.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "issue_1760"
|
|
||||||
version = "0.1.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "issue_rust_86261"
|
name = "issue_rust_86261"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "once_cell"
|
||||||
version = "1.0.66"
|
version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
|
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "proc_macro_crate"
|
||||||
version = "1.0.33"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.185"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subcrate"
|
name = "subcrate"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.4.3",
|
"byteorder 1.5.0",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "2.0.29"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.6"
|
version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
|
@ -12,19 +12,21 @@ edition = "2018"
|
||||||
byteorder = "1.0"
|
byteorder = "1.0"
|
||||||
cdylib = { path = "cdylib" }
|
cdylib = { path = "cdylib" }
|
||||||
exported_symbol = { path = "exported-symbol" }
|
exported_symbol = { path = "exported-symbol" }
|
||||||
|
proc_macro_crate = { path = "proc-macro-crate" }
|
||||||
issue_1567 = { path = "issue-1567" }
|
issue_1567 = { path = "issue-1567" }
|
||||||
issue_1691 = { path = "issue-1691" }
|
issue_1691 = { path = "issue-1691" }
|
||||||
issue_1705 = { path = "issue-1705" }
|
issue_1705 = { path = "issue-1705" }
|
||||||
issue_1760 = { path = "issue-1760" }
|
|
||||||
issue_rust_86261 = { path = "issue-rust-86261" }
|
issue_rust_86261 = { path = "issue-rust-86261" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
byteorder_2 = { package = "byteorder", version = "0.5" } # to test dev-dependencies behave as expected, with renaming
|
byteorder_2 = { package = "byteorder", version = "0.5" } # to test dev-dependencies behave as expected, with renaming
|
||||||
# Not actually used, but exercises some unique code path (`--extern` .so file).
|
## More dependencies that we don't actually use, but add just for extra test coverage.
|
||||||
serde_derive = "1.0.185"
|
# These use custom build probes, let's make sure they don't explode.
|
||||||
# Not actually used, but uses a custom build probe so let's make sure that works.
|
|
||||||
# (Ideally we'd check if the probe was successful, but that's not easily possible.)
|
# (Ideally we'd check if the probe was successful, but that's not easily possible.)
|
||||||
anyhow = "1.0"
|
# proc-macro2 is extra exciting because it is both a host-dependency (of proc_macro_crate above)
|
||||||
|
# and a target-dependency.
|
||||||
|
proc-macro2 = "1.0"
|
||||||
|
eyre = "0.6"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
autocfg = "1"
|
autocfg = "1"
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "issue_1760"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Miri Team"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
proc-macro = true
|
|
13
src/tools/miri/test-cargo-miri/proc-macro-crate/Cargo.toml
Normal file
13
src/tools/miri/test-cargo-miri/proc-macro-crate/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
# regression test for issue 1760
|
||||||
|
name = "proc_macro_crate"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Miri Team"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# A common dependency of proc macros, let's make sure that works.
|
||||||
|
proc-macro2 = "1.0"
|
|
@ -28,9 +28,9 @@
|
||||||
/// ```
|
/// ```
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn make_true() -> bool {
|
pub fn make_true() -> bool {
|
||||||
|
proc_macro_crate::use_the_dependency!();
|
||||||
issue_1567::use_the_dependency();
|
issue_1567::use_the_dependency();
|
||||||
issue_1705::use_the_dependency();
|
issue_1705::use_the_dependency();
|
||||||
issue_1760::use_the_dependency!();
|
|
||||||
issue_1691::use_me()
|
issue_1691::use_me()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,34 +54,13 @@ fn build_so_for_c_ffi_tests() -> PathBuf {
|
||||||
so_file_path
|
so_file_path
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> Config {
|
/// Does *not* set any args or env vars, since it is shared between the test runner and
|
||||||
|
/// run_dep_mode.
|
||||||
|
fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> Config {
|
||||||
// Miri is rustc-like, so we create a default builder for rustc and modify it
|
// Miri is rustc-like, so we create a default builder for rustc and modify it
|
||||||
let mut program = CommandBuilder::rustc();
|
let mut program = CommandBuilder::rustc();
|
||||||
program.program = miri_path();
|
program.program = miri_path();
|
||||||
|
|
||||||
// Add some flags we always want.
|
|
||||||
program.args.push("-Dwarnings".into());
|
|
||||||
program.args.push("-Dunused".into());
|
|
||||||
program.args.push("-Ainternal_features".into());
|
|
||||||
if let Ok(extra_flags) = env::var("MIRIFLAGS") {
|
|
||||||
for flag in extra_flags.split_whitespace() {
|
|
||||||
program.args.push(flag.into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
program.args.push("-Zui-testing".into());
|
|
||||||
program.args.push("--target".into());
|
|
||||||
program.args.push(target.into());
|
|
||||||
|
|
||||||
// If we're on linux, and we're testing the extern-so functionality,
|
|
||||||
// then build the shared object file for testing external C function calls
|
|
||||||
// and push the relevant compiler flag.
|
|
||||||
if cfg!(target_os = "linux") && path.starts_with("tests/extern-so/") {
|
|
||||||
let so_file_path = build_so_for_c_ffi_tests();
|
|
||||||
let mut flag = std::ffi::OsString::from("-Zmiri-extern-so-file=");
|
|
||||||
flag.push(so_file_path.into_os_string());
|
|
||||||
program.args.push(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut config = Config {
|
let mut config = Config {
|
||||||
target: Some(target.to_owned()),
|
target: Some(target.to_owned()),
|
||||||
stderr_filters: STDERR.clone(),
|
stderr_filters: STDERR.clone(),
|
||||||
|
@ -119,17 +98,38 @@ fn run_tests(
|
||||||
with_dependencies: bool,
|
with_dependencies: bool,
|
||||||
tmpdir: &Path,
|
tmpdir: &Path,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut config = test_config(target, path, mode, with_dependencies);
|
let mut config = miri_config(target, path, mode, with_dependencies);
|
||||||
|
|
||||||
// Add a test env var to do environment communication tests.
|
// Add a test env var to do environment communication tests.
|
||||||
config.program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
|
config.program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into())));
|
||||||
|
|
||||||
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
|
// Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
|
||||||
config.program.envs.push(("MIRI_TEMP".into(), Some(tmpdir.to_owned().into())));
|
config.program.envs.push(("MIRI_TEMP".into(), Some(tmpdir.to_owned().into())));
|
||||||
|
|
||||||
// If a test ICEs, we want to see a backtrace.
|
// If a test ICEs, we want to see a backtrace.
|
||||||
config.program.envs.push(("RUST_BACKTRACE".into(), Some("1".into())));
|
config.program.envs.push(("RUST_BACKTRACE".into(), Some("1".into())));
|
||||||
|
|
||||||
|
// Add some flags we always want.
|
||||||
|
config.program.args.push("-Dwarnings".into());
|
||||||
|
config.program.args.push("-Dunused".into());
|
||||||
|
config.program.args.push("-Ainternal_features".into());
|
||||||
|
if let Ok(extra_flags) = env::var("MIRIFLAGS") {
|
||||||
|
for flag in extra_flags.split_whitespace() {
|
||||||
|
config.program.args.push(flag.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.program.args.push("-Zui-testing".into());
|
||||||
|
config.program.args.push("--target".into());
|
||||||
|
config.program.args.push(target.into());
|
||||||
|
|
||||||
|
// If we're on linux, and we're testing the extern-so functionality,
|
||||||
|
// then build the shared object file for testing external C function calls
|
||||||
|
// and push the relevant compiler flag.
|
||||||
|
if cfg!(target_os = "linux") && path.starts_with("tests/extern-so/") {
|
||||||
|
let so_file_path = build_so_for_c_ffi_tests();
|
||||||
|
let mut flag = std::ffi::OsString::from("-Zmiri-extern-so-file=");
|
||||||
|
flag.push(so_file_path.into_os_string());
|
||||||
|
config.program.args.push(flag);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle command-line arguments.
|
// Handle command-line arguments.
|
||||||
let args = ui_test::Args::test()?;
|
let args = ui_test::Args::test()?;
|
||||||
let default_bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
|
let default_bless = env::var_os("RUSTC_BLESS").is_some_and(|v| v != "0");
|
||||||
|
@ -292,13 +292,12 @@ fn main() -> Result<()> {
|
||||||
|
|
||||||
fn run_dep_mode(target: String, mut args: impl Iterator<Item = OsString>) -> Result<()> {
|
fn run_dep_mode(target: String, mut args: impl Iterator<Item = OsString>) -> Result<()> {
|
||||||
let path = args.next().expect("./miri run-dep must be followed by a file name");
|
let path = args.next().expect("./miri run-dep must be followed by a file name");
|
||||||
let mut config = test_config(
|
let config = miri_config(
|
||||||
&target,
|
&target,
|
||||||
"",
|
"",
|
||||||
Mode::Yolo { rustfix: RustfixMode::Disabled },
|
Mode::Yolo { rustfix: RustfixMode::Disabled },
|
||||||
/* with dependencies */ true,
|
/* with dependencies */ true,
|
||||||
);
|
);
|
||||||
config.program.args.clear(); // We want to give the user full control over flags
|
|
||||||
let dep_args = config.build_dependencies()?;
|
let dep_args = config.build_dependencies()?;
|
||||||
|
|
||||||
let mut cmd = config.program.build(&config.out_dir);
|
let mut cmd = config.program.build(&config.out_dir);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue