Auto merge of #113022 - GuillaumeGomez:rollup-vkpzsuw, r=GuillaumeGomez
Rollup of 4 pull requests Successful merges: - #112918 (display PID of process holding lock) - #112990 (Add a regression test for #96699) - #113011 (Add enum for `can_access_statics` boolean) - #113018 (Fix test for #96258) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0d03812e24
@ -14,7 +14,7 @@ use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_target::abi::{self, Abi};
|
||||
|
||||
use super::{CompileTimeEvalContext, CompileTimeInterpreter};
|
||||
use super::{CanAccessStatics, CompileTimeEvalContext, CompileTimeInterpreter};
|
||||
use crate::errors;
|
||||
use crate::interpret::eval_nullary_intrinsic;
|
||||
use crate::interpret::{
|
||||
@ -93,7 +93,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
root_span: Span,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
can_access_statics: bool,
|
||||
can_access_statics: CanAccessStatics,
|
||||
) -> CompileTimeEvalContext<'mir, 'tcx> {
|
||||
debug!("mk_eval_cx: {:?}", param_env);
|
||||
InterpCx::new(
|
||||
@ -207,7 +207,7 @@ pub(crate) fn turn_into_const_value<'tcx>(
|
||||
tcx,
|
||||
tcx.def_span(key.value.instance.def_id()),
|
||||
key.param_env,
|
||||
/*can_access_statics:*/ is_static,
|
||||
CanAccessStatics::from(is_static),
|
||||
);
|
||||
|
||||
let mplace = ecx.raw_const_to_mplace(constant).expect(
|
||||
@ -309,7 +309,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
|
||||
// Statics (and promoteds inside statics) may access other statics, because unlike consts
|
||||
// they do not have to behave "as if" they were evaluated at runtime.
|
||||
CompileTimeInterpreter::new(
|
||||
/*can_access_statics:*/ is_static,
|
||||
CanAccessStatics::from(is_static),
|
||||
if tcx.sess.opts.unstable_opts.extra_const_ub_checks {
|
||||
CheckAlignment::Error
|
||||
} else {
|
||||
|
@ -57,7 +57,7 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> {
|
||||
/// * Interning makes everything outside of statics immutable.
|
||||
/// * Pointers to allocations inside of statics can never leak outside, to a non-static global.
|
||||
/// This boolean here controls the second part.
|
||||
pub(super) can_access_statics: bool,
|
||||
pub(super) can_access_statics: CanAccessStatics,
|
||||
|
||||
/// Whether to check alignment during evaluation.
|
||||
pub(super) check_alignment: CheckAlignment,
|
||||
@ -83,8 +83,23 @@ impl CheckAlignment {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub(crate) enum CanAccessStatics {
|
||||
No,
|
||||
Yes,
|
||||
}
|
||||
|
||||
impl From<bool> for CanAccessStatics {
|
||||
fn from(value: bool) -> Self {
|
||||
if value { Self::Yes } else { Self::No }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
|
||||
pub(crate) fn new(can_access_statics: bool, check_alignment: CheckAlignment) -> Self {
|
||||
pub(crate) fn new(
|
||||
can_access_statics: CanAccessStatics,
|
||||
check_alignment: CheckAlignment,
|
||||
) -> Self {
|
||||
CompileTimeInterpreter {
|
||||
num_evaluated_steps: 0,
|
||||
stack: Vec::new(),
|
||||
@ -699,7 +714,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
||||
}
|
||||
} else {
|
||||
// Read access. These are usually allowed, with some exceptions.
|
||||
if machine.can_access_statics {
|
||||
if machine.can_access_statics == CanAccessStatics::Yes {
|
||||
// Machine configuration allows us read from anything (e.g., `static` initializer).
|
||||
Ok(())
|
||||
} else if static_def_id.is_some() {
|
||||
|
@ -26,7 +26,7 @@ pub(crate) fn const_caller_location(
|
||||
(file, line, col): (Symbol, u32, u32),
|
||||
) -> ConstValue<'_> {
|
||||
trace!("const_caller_location: {}:{}:{}", file, line, col);
|
||||
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false);
|
||||
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), CanAccessStatics::No);
|
||||
|
||||
let loc_place = ecx.alloc_caller_location(file, line, col);
|
||||
if intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &loc_place).is_err() {
|
||||
@ -55,10 +55,12 @@ pub(crate) fn eval_to_valtree<'tcx>(
|
||||
|
||||
// FIXME Need to provide a span to `eval_to_valtree`
|
||||
let ecx = mk_eval_cx(
|
||||
tcx, DUMMY_SP, param_env,
|
||||
tcx,
|
||||
DUMMY_SP,
|
||||
param_env,
|
||||
// It is absolutely crucial for soundness that
|
||||
// we do not read from static items or other mutable memory.
|
||||
false,
|
||||
CanAccessStatics::No,
|
||||
);
|
||||
let place = ecx.raw_const_to_mplace(const_alloc).unwrap();
|
||||
debug!(?place);
|
||||
@ -91,7 +93,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
|
||||
val: mir::ConstantKind<'tcx>,
|
||||
) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> {
|
||||
trace!("destructure_mir_constant: {:?}", val);
|
||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
|
||||
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No);
|
||||
let op = ecx.eval_mir_constant(&val, None, None)?;
|
||||
|
||||
// We go to `usize` as we cannot allocate anything bigger anyway.
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::eval_queries::{mk_eval_cx, op_to_const};
|
||||
use super::machine::CompileTimeEvalContext;
|
||||
use super::{ValTreeCreationError, ValTreeCreationResult, VALTREE_MAX_NODES};
|
||||
use crate::const_eval::CanAccessStatics;
|
||||
use crate::interpret::{
|
||||
intern_const_alloc_recursive, ConstValue, ImmTy, Immediate, InternKind, MemPlaceMeta,
|
||||
MemoryKind, PlaceTy, Scalar,
|
||||
@ -263,7 +264,11 @@ pub fn valtree_to_const_value<'tcx>(
|
||||
// FIXME Does this need an example?
|
||||
|
||||
let (param_env, ty) = param_env_ty.into_parts();
|
||||
let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
|
||||
let mut ecx: crate::interpret::InterpCx<
|
||||
'_,
|
||||
'_,
|
||||
crate::const_eval::CompileTimeInterpreter<'_, '_>,
|
||||
> = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No);
|
||||
|
||||
match ty.kind() {
|
||||
ty::FnDef(..) => {
|
||||
|
@ -2,7 +2,7 @@ use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, Val
|
||||
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
|
||||
use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
|
||||
|
||||
use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
|
||||
use crate::const_eval::{CanAccessStatics, CheckAlignment, CompileTimeInterpreter};
|
||||
use crate::interpret::{InterpCx, MemoryKind, OpTy};
|
||||
|
||||
/// Determines if this type permits "raw" initialization by just transmuting some memory into an
|
||||
@ -44,8 +44,7 @@ fn might_permit_raw_init_strict<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
kind: ValidityRequirement,
|
||||
) -> Result<bool, LayoutError<'tcx>> {
|
||||
let machine =
|
||||
CompileTimeInterpreter::new(/*can_access_statics:*/ false, CheckAlignment::Error);
|
||||
let machine = CompileTimeInterpreter::new(CanAccessStatics::No, CheckAlignment::Error);
|
||||
|
||||
let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
|
||||
|
||||
|
@ -5,7 +5,9 @@
|
||||
//! parent directory, and otherwise documentation can be found throughout the `build`
|
||||
//! directory in each respective module.
|
||||
|
||||
use std::env;
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
use std::{env, fs, process};
|
||||
|
||||
#[cfg(all(any(unix, windows), not(target_os = "solaris")))]
|
||||
use bootstrap::t;
|
||||
@ -20,22 +22,32 @@ fn main() {
|
||||
#[cfg(all(any(unix, windows), not(target_os = "solaris")))]
|
||||
let _build_lock_guard;
|
||||
#[cfg(all(any(unix, windows), not(target_os = "solaris")))]
|
||||
// Display PID of process holding the lock
|
||||
// PID will be stored in a lock file
|
||||
{
|
||||
let path = config.out.join("lock");
|
||||
build_lock = fd_lock::RwLock::new(t!(std::fs::File::create(&path)));
|
||||
let pid = match fs::read_to_string(&path) {
|
||||
Ok(contents) => contents,
|
||||
Err(_) => String::new(),
|
||||
};
|
||||
|
||||
build_lock =
|
||||
fd_lock::RwLock::new(t!(OpenOptions::new().write(true).create(true).open(&path)));
|
||||
_build_lock_guard = match build_lock.try_write() {
|
||||
Ok(lock) => lock,
|
||||
Ok(mut lock) => {
|
||||
t!(lock.write(&process::id().to_string().as_ref()));
|
||||
lock
|
||||
}
|
||||
err => {
|
||||
drop(err);
|
||||
if let Some(pid) = get_lock_owner(&path) {
|
||||
println!("warning: build directory locked by process {pid}, waiting for lock");
|
||||
} else {
|
||||
println!("warning: build directory locked, waiting for lock");
|
||||
}
|
||||
t!(build_lock.write())
|
||||
println!("warning: build directory locked by process {pid}, waiting for lock");
|
||||
let mut lock = t!(build_lock.write());
|
||||
t!(lock.write(&process::id().to_string().as_ref()));
|
||||
lock
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(any(not(any(unix, windows)), target_os = "solaris"))]
|
||||
println!("warning: file locking not supported for target, not locking build directory");
|
||||
|
||||
@ -108,30 +120,3 @@ fn check_version(config: &Config) -> Option<String> {
|
||||
|
||||
Some(msg)
|
||||
}
|
||||
|
||||
/// Get the PID of the process which took the write lock by
|
||||
/// parsing `/proc/locks`.
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_lock_owner(f: &std::path::Path) -> Option<u64> {
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
let lock_inode = std::fs::metadata(f).ok()?.ino();
|
||||
let lockfile = File::open("/proc/locks").ok()?;
|
||||
BufReader::new(lockfile).lines().find_map(|line| {
|
||||
// pid--vvvvvv vvvvvvv--- inode
|
||||
// 21: FLOCK ADVISORY WRITE 359238 08:02:3719774 0 EOF
|
||||
let line = line.ok()?;
|
||||
let parts = line.split_whitespace().collect::<Vec<_>>();
|
||||
let (pid, inode) = (parts[4].parse::<u64>().ok()?, &parts[5]);
|
||||
let inode = inode.rsplit_once(':')?.1.parse::<u64>().ok()?;
|
||||
if inode == lock_inode { Some(pid) } else { None }
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "solaris")))]
|
||||
fn get_lock_owner(_: &std::path::Path) -> Option<u64> {
|
||||
// FIXME: Implement on other OS's
|
||||
None
|
||||
}
|
||||
|
87
tests/ui/const-generics/generic_const_exprs/issue-96699.rs
Normal file
87
tests/ui/const-generics/generic_const_exprs/issue-96699.rs
Normal file
@ -0,0 +1,87 @@
|
||||
// check-pass
|
||||
|
||||
#![allow(dead_code, incomplete_features)]
|
||||
#![feature(generic_const_exprs)]
|
||||
|
||||
const fn min(a: usize, b: usize) -> usize {
|
||||
if a < b {
|
||||
a
|
||||
} else {
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
trait Trait1<Inner1>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn crash_here()
|
||||
where
|
||||
Inner1: Default,
|
||||
{
|
||||
Inner1::default();
|
||||
}
|
||||
}
|
||||
|
||||
struct Struct1<T>(T);
|
||||
impl<T> Trait1<T> for Struct1<T> {}
|
||||
|
||||
trait Trait2<Inner2>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
type Assoc: Trait1<Inner2>;
|
||||
|
||||
fn call_crash()
|
||||
where
|
||||
Inner2: Default,
|
||||
{
|
||||
// if Inner2 implements Default, we can call crash_here.
|
||||
Self::Assoc::crash_here();
|
||||
}
|
||||
}
|
||||
|
||||
struct Struct2<const SIZE1: usize, const SIZE2: usize> {}
|
||||
/*
|
||||
where
|
||||
[(); min(SIZE1, SIZE2)]:,
|
||||
{
|
||||
elem: [i32; min(SIZE1, SIZE2)],
|
||||
}
|
||||
*/
|
||||
|
||||
impl<const SIZE1: usize, const SIZE2: usize> Trait2<[i32; min(SIZE1, SIZE2)]>
|
||||
for Struct2<SIZE1, SIZE2>
|
||||
{
|
||||
type Assoc = Struct1<[i32; min(SIZE1, SIZE2)]>;
|
||||
// dose Struct1<[i32; min(SIZE1, SIZE2)]> implement Default?
|
||||
}
|
||||
|
||||
fn main() {
|
||||
pattern2();
|
||||
|
||||
print_fully_name(<Struct2<1, 2> as Trait2<[i32; min(1, 2)]>>::Assoc::crash_here);
|
||||
// <compiler_bug2::Struct1<[i32; 1]> as compiler_bug2::Trait1<[i32; 1]>>::crash_here
|
||||
}
|
||||
|
||||
fn pattern1() {
|
||||
// no crash
|
||||
<Struct2<1, 2> as Trait2<[i32; min(1, 2)]>>::Assoc::crash_here();
|
||||
<Struct2<1, 2> as Trait2<[i32; min(1, 2)]>>::call_crash();
|
||||
}
|
||||
|
||||
fn pattern2() {
|
||||
// crash
|
||||
<Struct2<1, 2> as Trait2<[i32; min(1, 2)]>>::call_crash();
|
||||
|
||||
// undefined reference to `compiler_bug2::Trait1::crash_here'
|
||||
}
|
||||
|
||||
fn pattern3() {
|
||||
// no crash
|
||||
<Struct2<1, 2> as Trait2<[i32; min(1, 2)]>>::Assoc::crash_here();
|
||||
}
|
||||
|
||||
fn print_fully_name<T>(_: T) {
|
||||
let _ = std::any::type_name::<T>();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// compile-flags -Wrust-2021-incompatible-closure-captures
|
||||
#![warn(rust_2021_incompatible_closure_captures)]
|
||||
|
||||
fn main() {}
|
||||
|
||||
@ -9,7 +9,7 @@ impl Numberer {
|
||||
//~^ ERROR `async fn` is not permitted in Rust 2015
|
||||
interval: Duration,
|
||||
//~^ ERROR cannot find type `Duration` in this scope
|
||||
) -> Numberer {
|
||||
) -> Numberer { //~WARN: changes to closure capture in Rust 2021
|
||||
Numberer {}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,32 @@ help: consider importing this struct
|
||||
LL + use std::time::Duration;
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
warning: changes to closure capture in Rust 2021 will affect drop order
|
||||
--> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:12:19
|
||||
|
|
||||
LL | interval: Duration,
|
||||
| -------- in Rust 2018, this causes the closure to capture `interval`, but in Rust 2021, it has no effect
|
||||
LL |
|
||||
LL | ) -> Numberer {
|
||||
| _________________-_^
|
||||
| | |
|
||||
| | in Rust 2018, `interval` is dropped here along with the closure, but in Rust 2021 `interval` is not part of the closure
|
||||
LL | | Numberer {}
|
||||
LL | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs:1:9
|
||||
|
|
||||
LL | #![warn(rust_2021_incompatible_closure_captures)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: add a dummy let to cause `interval` to be fully captured
|
||||
|
|
||||
LL | ) -> Numberer { let _ = &interval;
|
||||
| ++++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0412, E0670.
|
||||
For more information about an error, try `rustc --explain E0412`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user