Skip to content

Commit

Permalink
chore: update the target compiler version to nightly-2020-06-24
Browse files Browse the repository at this point in the history
This commit includes work-arounds for the following changes in the
compiler:

- Raw pointers as const generic parameters are now forbidden.
  <rust-lang/rust#73398>

  This means the work-around for ICE caused by `&'static [_]` const
  generic parameters doesn't work anymore. An alternative work-around is
  yet to be implemented.

- Mutable references are now forbidden in all constant contexts except
  for `const fn`s.
  <rust-lang/rust#72934>

  Working around this change was as easy as mechanically replacing
  `const` with `const fn` for most cases. The only tricky case was the
  definition of `id_map` inside `build!`, which is a macro meant to be
  called inside a `const` item. The type of `id_map` isn't explicitly
  specified but is rather implied by a given configuration function, so
  this couldn't be mechanically replaced with a `const` item. To resolve
  this problem, I added an explicit type to `build!`'s signature.
  • Loading branch information
yvt committed Jun 25, 2020
1 parent ff6165c commit b096f68
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 80 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct Objects {
task: Task<System>,
}

const COTTAGE: Objects = constance::build!(System, configure_app);
const COTTAGE: Objects = constance::build!(System, configure_app => Objects);

constance::configure! {
const fn configure_app(_: &mut CfgBuilder<System>) -> Objects {
Expand Down
2 changes: 1 addition & 1 deletion examples/basic/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct Objects {
mutex1: Mutex<System, u32>,
}

const COTTAGE: Objects = constance::build!(System, configure_app);
const COTTAGE: Objects = constance::build!(System, configure_app => Objects);

constance::configure! {
const fn configure_app(_: &mut CfgBuilder<System>) -> Objects {
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2020-06-06
nightly-2020-06-24
23 changes: 17 additions & 6 deletions src/constance/src/kernel/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ macro_rules! configure {
/// [`KernelCfg2`]: crate::kernel::KernelCfg2
#[macro_export]
macro_rules! build {
($sys:ty, $configure:expr) => {{
($sys:ty, $configure:expr => $id_map_ty:ty) => {{
use $crate::{
kernel::{
cfg::{
Expand All @@ -312,17 +312,28 @@ macro_rules! build {
// `$configure` produces two values: a `CfgBuilder` and an ID map
// (custom type). We need the first one to be `const` so that we can
// calculate the values of generic parameters based on its contents.
const CFG: CfgBuilderInner<$sys> = {
const CFG: CfgBuilderInner<$sys> = get_cfg();

const fn get_cfg() -> CfgBuilderInner<$sys> {
// FIXME: Unable to do this inside a `const` item because of
// <https://github.com/rust-lang/rust/pull/72934>

// Safety: We are `build!`, so it's okay to use `CfgBuilder::new`
let mut cfg = unsafe { CfgBuilder::new() };
$configure(&mut cfg);
cfg.finalize();
cfg.into_inner()
};
}

// The second value can be just `let`
// Safety: We are `build!`, so it's okay to use `CfgBuilder::new`
let id_map = $configure(&mut unsafe { CfgBuilder::new() });
const fn id_map() -> $id_map_ty {
// FIXME: Unable to do this inside a `const` item because of
// <https://github.com/rust-lang/rust/pull/72934>
// This is also why `$id_map_ty` has to be given.

$configure(&mut unsafe { CfgBuilder::new() })
}

// Set up task priority levels
type TaskPriority = UIntegerWithBound<{ CFG.num_task_priority_levels as u128 - 1 }>;
Expand Down Expand Up @@ -382,7 +393,7 @@ macro_rules! build {
$sys,
U<NUM_INTERRUPT_LINES>,
U<NUM_INTERRUPT_HANDLERS>,
{ INTERRUPT_HANDLERS.as_ptr() },
{ &INTERRUPT_HANDLERS },
NUM_INTERRUPT_HANDLERS,
NUM_INTERRUPT_LINES,
>()
Expand Down Expand Up @@ -426,7 +437,7 @@ macro_rules! build {
}
}

id_map
id_map()
}};
}

Expand Down
95 changes: 48 additions & 47 deletions src/constance/src/kernel/cfg/interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,14 +408,14 @@ type ProtoCombinedHandlerFn = fn(interrupt::InterruptNum, bool);
struct MakeProtoCombinedHandlers<
System,
NumHandlers,
const HANDLERS: *const CfgBuilderInterruptHandler,
const HANDLERS: &'static [CfgBuilderInterruptHandler],
const NUM_HANDLERS: usize,
>(PhantomData<(System, NumHandlers)>);

trait MakeProtoCombinedHandlersTrait {
type System: Port;
type NumHandlers: Nat;
const HANDLERS: *const CfgBuilderInterruptHandler;
const HANDLERS: &'static [CfgBuilderInterruptHandler];
const NUM_HANDLERS: usize;
const PROTO_COMBINED_HANDLERS: &'static [ProtoCombinedHandlerFn];
const FIRST_PROTO_COMBINED_HANDLER: Option<ProtoCombinedHandlerFn>;
Expand All @@ -424,14 +424,14 @@ trait MakeProtoCombinedHandlersTrait {
impl<
System: Port,
NumHandlers: Nat,
const HANDLERS: *const CfgBuilderInterruptHandler,
const HANDLERS: &'static [CfgBuilderInterruptHandler],
const NUM_HANDLERS: usize,
> MakeProtoCombinedHandlersTrait
for MakeProtoCombinedHandlers<System, NumHandlers, HANDLERS, NUM_HANDLERS>
{
type System = System;
type NumHandlers = NumHandlers;
const HANDLERS: *const CfgBuilderInterruptHandler = HANDLERS;
const HANDLERS: &'static [CfgBuilderInterruptHandler] = HANDLERS;
const NUM_HANDLERS: usize = NUM_HANDLERS;
const PROTO_COMBINED_HANDLERS: &'static [ProtoCombinedHandlerFn] =
&Self::PROTO_COMBINED_HANDLERS_ARRAY;
Expand All @@ -445,68 +445,71 @@ impl<
impl<
System: Port,
NumHandlers: Nat,
const HANDLERS: *const CfgBuilderInterruptHandler,
const HANDLERS: &'static [CfgBuilderInterruptHandler],
const NUM_HANDLERS: usize,
> MakeProtoCombinedHandlers<System, NumHandlers, HANDLERS, NUM_HANDLERS>
{
const PROTO_COMBINED_HANDLERS_ARRAY: [ProtoCombinedHandlerFn; NUM_HANDLERS] = const_array_from_fn! {
fn iter<[T: MakeProtoCombinedHandlersTrait], I: Nat>(ref mut cell: T) -> ProtoCombinedHandlerFn {
#[inline(always)]
fn proto_combined_handler<T: MakeProtoCombinedHandlersTrait, I: Nat>(cur_line: interrupt::InterruptNum, mut should_unlock_cpu: bool) {
// Safety: `I::N < NUM_HANDLERS`
let handler = unsafe { &*T::HANDLERS.wrapping_add(I::N) };

if cur_line == handler.line {
if should_unlock_cpu {
// Relinquish CPU Lock before calling the next handler
if T::System::is_cpu_lock_active() {
// Safety: CPU Lock active, we have the ownership
// of the current CPU Lock (because a previously
// called handler left it active)
unsafe { T::System::leave_cpu_lock() };
const PROTO_COMBINED_HANDLERS_ARRAY: [ProtoCombinedHandlerFn; NUM_HANDLERS] =
Self::proto_combined_handlers_array();

const fn proto_combined_handlers_array() -> [ProtoCombinedHandlerFn; NUM_HANDLERS] {
// FIXME: Unable to do this inside a `const` item because of
// <https://github.com/rust-lang/rust/pull/72934>
const_array_from_fn! {
fn iter<[T: MakeProtoCombinedHandlersTrait], I: Nat>(ref mut cell: T) -> ProtoCombinedHandlerFn {
#[inline(always)]
fn proto_combined_handler<T: MakeProtoCombinedHandlersTrait, I: Nat>(cur_line: interrupt::InterruptNum, mut should_unlock_cpu: bool) {
let handler = T::HANDLERS[I::N];

if cur_line == handler.line {
if should_unlock_cpu {
// Relinquish CPU Lock before calling the next handler
if T::System::is_cpu_lock_active() {
// Safety: CPU Lock active, we have the ownership
// of the current CPU Lock (because a previously
// called handler left it active)
unsafe { T::System::leave_cpu_lock() };
}
}
}

(handler.start)(handler.param);
(handler.start)(handler.param);

should_unlock_cpu = true;
}
should_unlock_cpu = true;
}

// Call the next proto combined handler
let i = I::N + 1;
if i < T::NUM_HANDLERS {
T::PROTO_COMBINED_HANDLERS[i](cur_line, should_unlock_cpu);
// Call the next proto combined handler
let i = I::N + 1;
if i < T::NUM_HANDLERS {
T::PROTO_COMBINED_HANDLERS[i](cur_line, should_unlock_cpu);
}
}
proto_combined_handler::<T, I>
}
proto_combined_handler::<T, I>
}

// `Self: MakeProtoCombinedHandlersTrait` is used as the context type
// for the iteration
(0..NUM_HANDLERS).map(|i| iter::<[Self], i>(Self(PhantomData))).collect::<[_; NumHandlers]>()
};
// `Self: MakeProtoCombinedHandlersTrait` is used as the context type
// for the iteration
(0..NUM_HANDLERS).map(|i| iter::<[Self], i>(Self(PhantomData))).collect::<[_; NumHandlers]>()
}
}
}

// FIXME: ICE results if this has type `&'static [_]`.
// Pointer generic parameters entail raw pointer comparison
// (<https://github.com/rust-lang/rust/issues/53020>), which has
// unclear aspects and thus is unstable at this point.
// TODO: ICE results because this has type `&'static [_]`.
// Pointer generic parameters entail raw pointer comparison
// (<https://github.com/rust-lang/rust/issues/53020>), which has
// unclear aspects, thus they are forbidden in const generic parameters,
// meaning the work-around with `*const CfgBuilderInterruptHandler`
// doesn't work anymore.
// FIXME: ↑ This was meant to be inserted before `const HANDLERS: ...`, but when
// I did that, rustfmt tried to destroy the code
// <https://github.com/rust-lang/rustfmt/issues/4263>

/// Construct `InterruptHandlerTable`. Only meant to be used by `build!`
///
/// # Safety
///
/// `std::slice::from_raw_parts(HANDLERS, NUM_HANDLERS)` must be a valid
/// reference.
#[doc(hidden)]
pub const unsafe fn new_interrupt_handler_table<
System: Port,
NumLines: Nat,
NumHandlers: Nat,
const HANDLERS: *const CfgBuilderInterruptHandler,
const HANDLERS: &'static [CfgBuilderInterruptHandler],
const NUM_HANDLERS: usize,
const NUM_LINES: usize,
>() -> InterruptHandlerTable<[Option<InterruptHandlerFn>; NUM_LINES]> {
Expand All @@ -526,9 +529,7 @@ pub const unsafe fn new_interrupt_handler_table<
// FIXME: Work-around for `for` being unsupported in `const fn`
let mut i = 0;
while i < NUM_HANDLERS {
// Safety: `i < NUM_HANDLERS`. MIRI (the compile-time interpreter)
// actually can catch unsafe pointer references.
let handler = unsafe { &*HANDLERS.wrapping_add(i) };
let handler = HANDLERS[i];
if handler.line >= NUM_LINES {
panic!("`handler.line >= NUM_LINES`");
}
Expand Down
2 changes: 1 addition & 1 deletion src/constance/src/lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ crate your_app {
task1: constance::Task<System>,
}
static COTTAGE: Objects = constance::build!(System, configure_app);
static COTTAGE: Objects = constance::build!(System, configure_app => Objects);
// The configuration function. See "Static Configuration" for details.
fn configure_app(b: &mut constance::CfgBuilder<System>) -> Objects {
Expand Down
1 change: 0 additions & 1 deletion src/constance/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#![feature(const_mut_refs)]
#![feature(const_slice_from_raw_parts)]
#![feature(const_raw_ptr_deref)]
#![feature(const_compare_raw_pointers)]
#![feature(ptr_wrapping_offset_from)]
#![feature(unsafe_block_in_unsafe_fn)] // `unsafe fn` doesn't imply `unsafe {}`
#![feature(never_type)] // `!`
Expand Down
12 changes: 6 additions & 6 deletions src/constance/src/utils/for_times.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ mod tests {
fn test() {
struct Cell<T>(T, u128);

const GOT: u128 = {
const fn got() -> u128 {
let mut cell = Cell("unused", 0);
const_for_times! {
fn iter<[T], I: Nat>(cell: &mut Cell<T>) {
Expand All @@ -267,7 +267,7 @@ mod tests {
(0..U<20>).for_each(|i| iter::<[_], i>(&mut cell))
}
cell.1
};
}

let expected = {
let mut cell = 0;
Expand All @@ -277,13 +277,13 @@ mod tests {
cell
};

assert_eq!(expected, GOT);
assert_eq!(expected, got());
}

#[test]
fn const_array_from_fn() {
struct Cell<T>(T, u128);
const GOT: [u128; 20] = {
const fn got() -> [u128; 20] {
let mut cell = Cell("unused", 0);
const_array_from_fn! {
fn iter<[T], I: Nat>(ref mut cell: &mut Cell<T>) -> u128 {
Expand All @@ -293,7 +293,7 @@ mod tests {

(0..20).map(|i| iter::<[&'static str], i>(&mut cell)).collect::<[_; U<20>]>()
}
};
}

let expected = {
let mut cell = Cell("unused", 0);
Expand All @@ -308,6 +308,6 @@ mod tests {
.collect::<Vec<_>>()
};

assert_eq!(GOT[..], *expected);
assert_eq!(got()[..], *expected);
}
}
6 changes: 3 additions & 3 deletions src/constance/src/utils/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ mod tests {

#[test]
fn const_sort() {
const RESULT: [u32; 14] = {
const fn result() -> [u32; 14] {
let mut array = [2, 6, 1, 9, 13, 3, 8, 12, 5, 11, 14, 7, 4, 10];
sort_by!(14, |i| &mut array[i], |x, y| x < y);
array
};
}

assert_eq!(RESULT, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
assert_eq!(result(), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]);
}

#[quickcheck]
Expand Down
25 changes: 14 additions & 11 deletions src/constance/src/utils/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,14 @@ mod tests {

#[test]
fn push() {
const VEC: ComptimeVec<u32> = {
const fn vec() -> ComptimeVec<u32> {
// FIXME: Unable to do this inside a `const` item because of
// <https://github.com/rust-lang/rust/pull/72934>
let mut v = ComptimeVec::new();
v.push(42);
v
};
}
const VEC: ComptimeVec<u32> = vec();

const VEC_LEN: usize = VEC.len();
assert_eq!(VEC_LEN, 1);
Expand All @@ -118,32 +121,32 @@ mod tests {

#[test]
fn to_array() {
const ARRAY: [u32; 3] = {
const fn array() -> [u32; 3] {
let mut v = ComptimeVec::new();
v.push(1);
v.push(2);
v.push(3);
v.to_array()
};
assert_eq!(ARRAY, [1, 2, 3]);
}
assert_eq!(array(), [1, 2, 3]);
}

#[test]
fn get_mut() {
const VAL: u32 = {
const fn val() -> u32 {
let mut v = ComptimeVec::new();
v.push(1);
v.push(2);
v.push(3);
*v.get_mut(1) += 2;
*v.get(1)
};
assert_eq!(VAL, 4);
}
assert_eq!(val(), 4);
}

#[test]
fn const_vec_position() {
const POS: [Option<usize>; 2] = {
const fn pos() -> [Option<usize>; 2] {
let mut v = ComptimeVec::new();
v.push(42);
v.push(43);
Expand All @@ -152,8 +155,8 @@ mod tests {
vec_position!(v, |i| *i == 43),
vec_position!(v, |i| *i == 50),
]
};
assert_eq!(POS, [Some(1), None]);
}
assert_eq!(pos(), [Some(1), None]);
}

#[quickcheck]
Expand Down
2 changes: 1 addition & 1 deletion src/constance_port_std/src/lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use constance::kernel::Task;
// Use the simulator port
constance_port_std::use_port!(unsafe struct System);

const COTTAGE: () = constance::build!(System, configure_app);
const COTTAGE: () = constance::build!(System, configure_app => ());

constance::configure! {
const fn configure_app(_: &mut CfgBuilder<System>) -> () {
Expand Down
Loading

0 comments on commit b096f68

Please sign in to comment.