about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs8
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs21
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs7
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs5
-rw-r--r--src/bootstrap/bin/main.rs57
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-96699.rs87
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs4
-rw-r--r--tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr27
9 files changed, 172 insertions, 54 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 8b8e8ff58e9..417ab78fd54 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -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 {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 7391f567040..f9f645af41f 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -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() {
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index 6e462d3a1e9..b9ab0a4b7c8 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -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.
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index b10f2e9f862..e574df27694 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -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(..) => {
diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
index 29063261ada..f56798d4c32 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -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);
 
diff --git a/src/bootstrap/bin/main.rs b/src/bootstrap/bin/main.rs
index a80379e85c1..7ce4599c424 100644
--- a/src/bootstrap/bin/main.rs
+++ b/src/bootstrap/bin/main.rs
@@ -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
-}
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-96699.rs b/tests/ui/const-generics/generic_const_exprs/issue-96699.rs
new file mode 100644
index 00000000000..83f329d2a2d
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_exprs/issue-96699.rs
@@ -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>();
+}
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs
index a776e508907..a9d678c1e6a 100644
--- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.rs
@@ -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 {}
     }
 }
diff --git a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr
index 60433e1c284..71e9e7602e8 100644
--- a/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr
+++ b/tests/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-96258.stderr
@@ -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`.