ISLE: reject multi-term rules with explicit priorities (#5663)

In multi-terms, all matching rules fire. We treat the result as an
unordered set of values, so setting rule priorities is meaningless. We
want to prohibit relying on the rule match order in this case.

Also, codegen can produce invalid Rust if rules with different
priorities both match against a multi-term. We first documented this
symptom in #5647. As far as I can figure, prohibiting rule priorities
prevents all possible instances of that bug.

At some point in the future we might decide we want to carefully define
semantics for multi-term result ordering, at which point we can revisit
this.
This commit is contained in:
Jamey Sharp
2023-01-31 09:08:31 -08:00
committed by GitHub
parent d61758e2e9
commit 61270cdaed
4 changed files with 24 additions and 4 deletions

View File

@@ -0,0 +1,4 @@
(type u32 (primitive u32))
(decl multi A (u32) u32)
(rule 0 (A x) x)

View File

@@ -7,7 +7,7 @@
(decl multi Rule (u32) u32) (decl multi Rule (u32) u32)
(rule 1 (Rule (E1 a idx)) (rule (Rule (E1 a idx))
(if-let (A.B) a) (if-let (A.B) a)
idx) idx)
(rule (Rule _) (rule (Rule _)

View File

@@ -1744,6 +1744,18 @@ impl TermEnv {
bindings.exit_scope(); bindings.exit_scope();
let prio = if let Some(prio) = rule.prio {
if flags.multi {
tyenv.report_error(
pos,
"Cannot set rule priorities in multi-terms".to_string(),
);
}
prio
} else {
0
};
let rid = RuleId(self.rules.len()); let rid = RuleId(self.rules.len());
self.rules.push(Rule { self.rules.push(Rule {
id: rid, id: rid,
@@ -1752,7 +1764,7 @@ impl TermEnv {
iflets, iflets,
rhs, rhs,
vars: bindings.seen, vars: bindings.seen,
prio: rule.prio.unwrap_or(0), prio,
pos, pos,
}); });
} }

View File

@@ -15,8 +15,12 @@ pub fn run_pass(filename: &str) {
} }
pub fn run_fail(filename: &str) { pub fn run_fail(filename: &str) {
if build(filename).is_ok() { match build(filename) {
panic!("test {} passed unexpectedly", filename); Ok(_) => panic!("test {} passed unexpectedly", filename),
Err(err) => {
// Log the actual errors for use with `cargo test -- --nocapture`
println!("failed, as expected:\n{:?}", err);
}
} }
} }