Redline is a syntactic lint over one function body. This page is the list of ways it is wrong, not a roadmap.
- Constructs in its allocation table (
Vec::new,String::from,.collect(),vec!,format!, …) appearing in the annotated body - Constructs in its syscall table (
std::fs::*,File::open,TcpStream::connect,println!, …) appearing in the annotated body - Loop multiplication when the range is a literal
- The more expensive arm of an
if/match - Closure bodies written inline
There is no cross-function analysis and there cannot be one in a proc-macro: no MIR, no type information, no cross-crate data. Redline therefore treats an unrecognized call as an error, not as free:
#[redline(latency = "< 1ms")]
fn looks_fine() {
expensive(); // error: cannot analyze `expensive`
}assume_calls_free suppresses that error and restores the old, unsound
behaviour, at your explicit request.
Function pointers, closures held in variables, and dyn Trait method calls are
opaque. They are reported as un-analyzable rather than silently skipped.
#[redline(allocs = 0)]
fn indirect() -> String {
let f: fn() -> String = String::new;
f() // error: the callee is a runtime value
}Matching is on written path segments. use std::collections::HashMap as Map;
followed by Map::new() is not in the table, so it is reported as an
un-analyzable call rather than as an allocation. Generic code, operator
overloads and Deref are invisible: a + b costs 1 ALU op even if Add is
implemented by allocating.
Deallocation and Drop impls are not counted at all.
Macro bodies are not expanded — expansion order makes their contents
unavailable. A macro whose name is not in the recognized list is counted as one
call and its contents are ignored. This is a real hole: a macro that allocates
passes an allocs = 0 check.
unsafe blocks are walked, but an extern "C" call is just an unrecognized
call. It errors rather than passing, which is the best available answer.
Non-literal bounds are assumed to be 1000 iterations. Arbitrary.
.await is reported as un-analyzable: suspension time is not a property of the
syntax. An async fn under a latency bound is not meaningful.
max_stack counts bindings × 8 bytes. There is no type information.
A lint with a hard failure mode, over one function body, matching a fixed list
of names. It is useful for keeping String::from and println! out of a hot
path that someone might edit later. It is not a verifier, and a passing
latency bound is not evidence about runtime.
For actual numbers use iai-callgrind (instruction counts on compiled code) or criterion. For actual compile-time verification of program properties use Kani, Prusti, MIRAI or Creusot.