Skip to content

Commit 984ec0b

Browse files
committed
Reject removed runtime effects
1 parent 93d60d7 commit 984ec0b

3 files changed

Lines changed: 59 additions & 0 deletions

File tree

src/analyzer.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,26 @@ impl Analyzer<'_> {
187187

188188
for effect in &function.effects {
189189
let effect_name = effect_name(effect);
190+
if let Some(replacement) = removed_runtime_effect_replacement(effect_name) {
191+
self.diagnostics.push(
192+
Diagnostic::error(
193+
code::REMOVED_RUNTIME_EFFECT,
194+
format!(
195+
"`{effect_name}` is not a valid RSScript v0.4.1 effect in `{}`.",
196+
function.name
197+
),
198+
function.span.clone(),
199+
"removed runtime effect",
200+
)
201+
.with_cause("v0.4.1 uses reductive guarantees such as `no_panic`, `noalloc`, `no_block`, and `pure`.")
202+
.with_fix(
203+
"replace_removed_effect",
204+
replacement,
205+
"manual",
206+
),
207+
);
208+
continue;
209+
}
190210
let valid = effect_name == "no_panic"
191211
|| effect_name == "noalloc"
192212
|| effect_name == "no_block"
@@ -660,6 +680,27 @@ fn effect_display(effect: &EffectDecl) -> String {
660680
}
661681
}
662682

683+
fn removed_runtime_effect_replacement(effect_name: &str) -> Option<&'static str> {
684+
match effect_name {
685+
"io" => Some(
686+
"Remove `io`; I/O is allowed by default unless a guarantee such as `pure` or `no_block` forbids it.",
687+
),
688+
"allocates" => Some(
689+
"Remove `allocates`; allocation is allowed by default. Use `noalloc` only when the function guarantees no allocation.",
690+
),
691+
"may_panic" => Some(
692+
"Remove `may_panic`; panic is allowed by default. Use `no_panic` only when the function guarantees no panic.",
693+
),
694+
"may_fail" => Some(
695+
"Remove `may_fail`; represent failure in the return type, for example `Result<T, E>`.",
696+
),
697+
"async" => Some(
698+
"Remove `async` from `effects(...)`; write `async fn` when the function itself is async.",
699+
),
700+
_ => None,
701+
}
702+
}
703+
663704
fn duplicate_symbol_label(kind: DuplicateSymbolKind) -> &'static str {
664705
match kind {
665706
DuplicateSymbolKind::Function => "function",

src/diagnostic.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub mod code {
1212
pub const INVALID_PURE_EFFECT: &str = "RS0009";
1313
pub const REMOVED_PROFILE_DECLARATION: &str = "RS0010";
1414
pub const REMOVED_SHARE_EFFECT: &str = "RS0011";
15+
pub const REMOVED_RUNTIME_EFFECT: &str = "RS0012";
1516
pub const FILE_MODE_VIOLATION: &str = "RS0101";
1617
pub const UNNAMED_ARGUMENT: &str = "RS0201";
1718
pub const MISSING_DATA_EFFECT: &str = "RS0202";
@@ -255,6 +256,11 @@ static DIAGNOSTIC_EXPLANATIONS: &[DiagnosticExplanation] = &[
255256
title: "removed share data effect",
256257
explanation: "RSScript v0.4.1 removed `share` as a data effect. Retention must be declared with `effects(retains(param))`.",
257258
},
259+
DiagnosticExplanation {
260+
code: code::REMOVED_RUNTIME_EFFECT,
261+
title: "removed runtime effect",
262+
explanation: "RSScript v0.4.1 uses reductive guarantees. Additive runtime effects such as `io`, `allocates`, `may_panic`, and `may_fail` are not valid effects.",
263+
},
258264
DiagnosticExplanation {
259265
code: code::FILE_MODE_VIOLATION,
260266
title: "file mode violation",
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// expect: RS0012
2+
mode: managed
3+
4+
struct Image {
5+
pixels: Buffer
6+
}
7+
8+
fn load(path: read Path) -> Result<fresh Image, ImageError>
9+
effects(io, allocates, may_panic, may_fail, async)
10+
{
11+
return Image.load(path: read path)
12+
}

0 commit comments

Comments
 (0)