diff --git a/kernel-rs/Cargo.toml b/kernel-rs/Cargo.toml index aa8ea82c..14cc158c 100644 --- a/kernel-rs/Cargo.toml +++ b/kernel-rs/Cargo.toml @@ -18,6 +18,9 @@ lfs = [] [profile.dev] panic = "abort" opt-level = 1 +# TODO: The `const_generics` and `const_evaluatable_checked` feature causes an ICE on low nightly versions +# when trying incremental compilation. Remove this after upgrading to a higher nightly version. +incremental = false [profile.release] panic = "abort" diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 6c477bab..091a67a0 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -48,6 +48,8 @@ #![feature(const_mut_refs)] #![feature(const_precise_live_drops)] #![feature(const_trait_impl)] +#![feature(const_generics)] +#![feature(const_evaluatable_checked)] #![feature(generic_associated_types)] #![feature(maybe_uninit_extra)] #![feature(raw_ref_op)] diff --git a/kernel-rs/src/page.rs b/kernel-rs/src/page.rs index a957be77..ea10f1e4 100644 --- a/kernel-rs/src/page.rs +++ b/kernel-rs/src/page.rs @@ -74,16 +74,11 @@ impl Page { } } - pub fn as_uninit_mut(&mut self) -> &mut MaybeUninit { - // TODO(https://github.com/kaist-cp/rv6/issues/471): Use const_assert! (or equivalent) - // instead. Currently, use of T inside const_assert! incurs a compile error: "can't use - // generic parameters from outer function". Also, there's a workaround using - // feature(const_generics) and feature(const_evaluatable_checked). However, using them makes - // the compiler panic. When the compiler becomes updated, we will fix the following lines to - // use static checks. - assert!(mem::size_of::() <= PGSIZE); - assert_eq!(PGSIZE % mem::align_of::(), 0); - + pub fn as_uninit_mut(&mut self) -> &mut MaybeUninit + where + [(); PGSIZE - mem::size_of::()]: , /* We need mem::size_of::() <= PGSIZE */ + [(); PGSIZE % mem::align_of::() + usize::MAX]: , /* We need PGSIZE % mem::align_of:: == 0 */ + { // SAFETY: self.inner is an array of length PGSIZE aligned with PGSIZE bytes. // The above assertions show that it can contain a value of T. As it contains arbitrary // data, we cannot treat it as &mut T. Instead, we use &mut MaybeUninit. It's ok because diff --git a/kernel-rs/src/util/mod.rs b/kernel-rs/src/util/mod.rs index dad1924c..da5a1f3c 100644 --- a/kernel-rs/src/util/mod.rs +++ b/kernel-rs/src/util/mod.rs @@ -53,10 +53,11 @@ pub fn memmove(dst: &mut [u8], src: &[u8]) { /// # SAFETY /// /// Filling a value of `T` with a value of `S` must not break the invariant of `T`. -pub unsafe fn memset(dst: &mut T, v: S) { - // Cannot use `const_assert!` here. Compiler optimization will remove `assert!`. - assert!(core::mem::size_of::() % core::mem::size_of::() == 0); - assert!(core::mem::align_of::() % core::mem::align_of::() == 0); +pub unsafe fn memset(dst: &mut T, v: S) +where + [(); core::mem::size_of::() % core::mem::size_of::() + usize::MAX]: , /* We need mem::size_of::() % mem::size_of::() == 0 */ + [(); core::mem::align_of::() % core::mem::align_of::() + usize::MAX]: , /* We need mem::align_of::() % mem::align_of::() == 0 */ +{ // SAFETY: T's size/alignment is a multiple of S's size/alignment. let buf = unsafe { core::slice::from_raw_parts_mut(