Skip to content

Commit a7c71ed

Browse files
committed
fix(cfg): work around the ICE caused by &'static [_] const generic parameters
This commit implements a work-around for this issue: <rust-lang/rust#73727>
1 parent b096f68 commit a7c71ed

File tree

2 files changed

+34
-43
lines changed

2 files changed

+34
-43
lines changed

src/constance/src/kernel/cfg.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,11 @@ macro_rules! build {
383383
const NUM_INTERRUPT_HANDLERS: usize = INTERRUPT_HANDLERS.len();
384384
const NUM_INTERRUPT_LINES: usize =
385385
$crate::kernel::cfg::num_required_interrupt_line_slots(&INTERRUPT_HANDLERS);
386+
struct Handlers;
387+
impl $crate::kernel::cfg::CfgBuilderInterruptHandlerList for Handlers {
388+
type NumHandlers = U<NUM_INTERRUPT_HANDLERS>;
389+
const HANDLERS: &'static [CfgBuilderInterruptHandler] = &INTERRUPT_HANDLERS;
390+
}
386391
const INTERRUPT_HANDLERS_SIZED: InterruptHandlerTable<
387392
[Option<InterruptHandlerFn>; NUM_INTERRUPT_LINES],
388393
> = unsafe {
@@ -392,10 +397,9 @@ macro_rules! build {
392397
$crate::kernel::cfg::new_interrupt_handler_table::<
393398
$sys,
394399
U<NUM_INTERRUPT_LINES>,
395-
U<NUM_INTERRUPT_HANDLERS>,
396-
{ &INTERRUPT_HANDLERS },
397-
NUM_INTERRUPT_HANDLERS,
400+
Handlers,
398401
NUM_INTERRUPT_LINES,
402+
NUM_INTERRUPT_HANDLERS,
399403
>()
400404
};
401405

src/constance/src/kernel/cfg/interrupt.rs

+27-40
Original file line numberDiff line numberDiff line change
@@ -402,15 +402,23 @@ impl InterruptHandlerTable {
402402
/// ```
403403
type ProtoCombinedHandlerFn = fn(interrupt::InterruptNum, bool);
404404

405+
// FIXME: Passing `&'static [_]` as a const generic parameter causes ICE:
406+
// <https://github.com/rust-lang/rust/issues/73727>
407+
// `CfgBuilderInterruptHandlerList` is a work-around for this issue.
408+
/// A static list of [`CfgBuilderInterruptHandler`]s.
409+
#[doc(hidden)]
410+
pub trait CfgBuilderInterruptHandlerList {
411+
/// `U<Self::NUM_HANDLERS>`
412+
type NumHandlers: Nat;
413+
const HANDLERS: &'static [CfgBuilderInterruptHandler];
414+
}
415+
405416
/// The ultimate purpose of this type is to make `PROTO_COMBINED_HANDLERS`
406417
/// (a list of `ProtoCombinedHandlerFn`s) and `FIRST_PROTO_COMBINED_HANDLER`
407418
/// available to `new_interrupt_handler_table`.
408-
struct MakeProtoCombinedHandlers<
409-
System,
410-
NumHandlers,
411-
const HANDLERS: &'static [CfgBuilderInterruptHandler],
412-
const NUM_HANDLERS: usize,
413-
>(PhantomData<(System, NumHandlers)>);
419+
struct MakeProtoCombinedHandlers<System, Handlers, const NUM_HANDLERS: usize>(
420+
PhantomData<(System, Handlers)>,
421+
);
414422

415423
trait MakeProtoCombinedHandlersTrait {
416424
type System: Port;
@@ -421,17 +429,12 @@ trait MakeProtoCombinedHandlersTrait {
421429
const FIRST_PROTO_COMBINED_HANDLER: Option<ProtoCombinedHandlerFn>;
422430
}
423431

424-
impl<
425-
System: Port,
426-
NumHandlers: Nat,
427-
const HANDLERS: &'static [CfgBuilderInterruptHandler],
428-
const NUM_HANDLERS: usize,
429-
> MakeProtoCombinedHandlersTrait
430-
for MakeProtoCombinedHandlers<System, NumHandlers, HANDLERS, NUM_HANDLERS>
432+
impl<System: Port, Handlers: CfgBuilderInterruptHandlerList, const NUM_HANDLERS: usize>
433+
MakeProtoCombinedHandlersTrait for MakeProtoCombinedHandlers<System, Handlers, NUM_HANDLERS>
431434
{
432435
type System = System;
433-
type NumHandlers = NumHandlers;
434-
const HANDLERS: &'static [CfgBuilderInterruptHandler] = HANDLERS;
436+
type NumHandlers = Handlers::NumHandlers;
437+
const HANDLERS: &'static [CfgBuilderInterruptHandler] = Handlers::HANDLERS;
435438
const NUM_HANDLERS: usize = NUM_HANDLERS;
436439
const PROTO_COMBINED_HANDLERS: &'static [ProtoCombinedHandlerFn] =
437440
&Self::PROTO_COMBINED_HANDLERS_ARRAY;
@@ -442,12 +445,8 @@ impl<
442445
};
443446
}
444447

445-
impl<
446-
System: Port,
447-
NumHandlers: Nat,
448-
const HANDLERS: &'static [CfgBuilderInterruptHandler],
449-
const NUM_HANDLERS: usize,
450-
> MakeProtoCombinedHandlers<System, NumHandlers, HANDLERS, NUM_HANDLERS>
448+
impl<System: Port, Handlers: CfgBuilderInterruptHandlerList, const NUM_HANDLERS: usize>
449+
MakeProtoCombinedHandlers<System, Handlers, NUM_HANDLERS>
451450
{
452451
const PROTO_COMBINED_HANDLERS_ARRAY: [ProtoCombinedHandlerFn; NUM_HANDLERS] =
453452
Self::proto_combined_handlers_array();
@@ -488,30 +487,19 @@ impl<
488487

489488
// `Self: MakeProtoCombinedHandlersTrait` is used as the context type
490489
// for the iteration
491-
(0..NUM_HANDLERS).map(|i| iter::<[Self], i>(Self(PhantomData))).collect::<[_; NumHandlers]>()
490+
(0..NUM_HANDLERS).map(|i| iter::<[Self], i>(Self(PhantomData))).collect::<[_; Handlers::NumHandlers]>()
492491
}
493492
}
494493
}
495494

496-
// TODO: ICE results because this has type `&'static [_]`.
497-
// Pointer generic parameters entail raw pointer comparison
498-
// (<https://github.com/rust-lang/rust/issues/53020>), which has
499-
// unclear aspects, thus they are forbidden in const generic parameters,
500-
// meaning the work-around with `*const CfgBuilderInterruptHandler`
501-
// doesn't work anymore.
502-
// FIXME: ↑ This was meant to be inserted before `const HANDLERS: ...`, but when
503-
// I did that, rustfmt tried to destroy the code
504-
// <https://github.com/rust-lang/rustfmt/issues/4263>
505-
506495
/// Construct `InterruptHandlerTable`. Only meant to be used by `build!`
507496
#[doc(hidden)]
508497
pub const unsafe fn new_interrupt_handler_table<
509498
System: Port,
510499
NumLines: Nat,
511-
NumHandlers: Nat,
512-
const HANDLERS: &'static [CfgBuilderInterruptHandler],
513-
const NUM_HANDLERS: usize,
500+
Handlers: CfgBuilderInterruptHandlerList,
514501
const NUM_LINES: usize,
502+
const NUM_HANDLERS: usize,
515503
>() -> InterruptHandlerTable<[Option<InterruptHandlerFn>; NUM_LINES]> {
516504
// Check generic parameters
517505

@@ -522,14 +510,14 @@ pub const unsafe fn new_interrupt_handler_table<
522510
if NumLines::N != NUM_LINES {
523511
panic!("`NumLines::N != NUM_LINES`");
524512
}
525-
if NumHandlers::N != NUM_HANDLERS {
513+
if Handlers::NumHandlers::N != NUM_HANDLERS {
526514
panic!("`NumHandlers::N != NUM_HANDLERS`");
527515
}
528516

529517
// FIXME: Work-around for `for` being unsupported in `const fn`
530518
let mut i = 0;
531519
while i < NUM_HANDLERS {
532-
let handler = HANDLERS[i];
520+
let handler = Handlers::HANDLERS[i];
533521
if handler.line >= NUM_LINES {
534522
panic!("`handler.line >= NUM_LINES`");
535523
}
@@ -553,9 +541,8 @@ pub const unsafe fn new_interrupt_handler_table<
553541

554542
(0..NUM_LINES).map(|i| iter::<[MakeProtoCombinedHandlers<
555543
System,
556-
NumHandlers,
557-
HANDLERS,
558-
NUM_HANDLERS
544+
Handlers,
545+
NUM_HANDLERS,
559546
>], i>(MakeProtoCombinedHandlers(PhantomData))).collect::<[_; NumLines]>()
560547
};
561548

0 commit comments

Comments
 (0)