Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit cb18a6a

Browse files
author
Hendrik van Antwerpen
committed
Disallow recursive stack unifications
1 parent 43fa595 commit cb18a6a

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

stack-graphs/src/partial.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -724,15 +724,23 @@ impl PartialSymbolStack {
724724

725725
// CASE 3:
726726
// One of the stacks contains symbols and the other doesn't, and the “empty” stack _does_
727-
// have a variable. That means the answer is YES, and the “empty” side's variable needs to
728-
// capture the entirety of the non-empty side.
727+
// have a variable. If both sides have the same variable, the answer is NO. Otherwise,
728+
// the answer is YES, and the “empty” side's variable needs to capture the entirety of the
729+
// non-empty side.
729730
//
730731
// lhs rhs
731732
// ============ ============
733+
// (...) $1 (...) $1 => no
732734
// () $1 (stuff) => yes rhs, $1 => rhs
733735
// () $1 (stuff) $2 => yes rhs, $1 => rhs
734736
// (stuff) () $2 => yes lhs, $2 => lhs
735737
// (stuff) $1 () $2 => yes lhs, $2 => lhs
738+
match (lhs.variable.into_option(), rhs.variable.into_option()) {
739+
(Some(v1), Some(v2)) if v1 == v2 => {
740+
return Err(PathResolutionError::ScopeStackUnsatisfied)
741+
}
742+
_ => {}
743+
}
736744
if lhs.contains_symbols() {
737745
let rhs_variable = rhs.variable.into_option().unwrap();
738746
symbol_bindings.add(partials, rhs_variable, lhs, scope_bindings)?;
@@ -1095,15 +1103,23 @@ impl PartialScopeStack {
10951103

10961104
// CASE 3:
10971105
// One of the stacks contains scopes and the other doesn't, and the “empty” stack _does_
1098-
// have a variable. That means the answer is YES, and the “empty” side's variable needs to
1099-
// capture the entirety of the non-empty side.
1106+
// have a variable. If both sides have the same variable, the answer is NO. Otherwise,
1107+
// the answer is YES, and the “empty” side's variable needs to capture the entirety of the
1108+
// non-empty side.
11001109
//
11011110
// lhs rhs
11021111
// ============ ============
1112+
// (...) $1 (...) $1 => no
11031113
// () $1 (stuff) => yes rhs, $1 => rhs
11041114
// () $1 (stuff) $2 => yes rhs, $1 => rhs
11051115
// (stuff) () $2 => yes lhs, $2 => lhs
11061116
// (stuff) $1 () $2 => yes lhs, $2 => lhs
1117+
match (lhs.variable.into_option(), rhs.variable.into_option()) {
1118+
(Some(v1), Some(v2)) if v1 == v2 => {
1119+
return Err(PathResolutionError::ScopeStackUnsatisfied)
1120+
}
1121+
_ => {}
1122+
}
11071123
if lhs.contains_scopes() {
11081124
let rhs_variable = rhs.variable.into_option().unwrap();
11091125
bindings.add(partials, rhs_variable, lhs)?;

stack-graphs/tests/it/partial.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ fn can_unify_partial_symbol_stacks() -> Result<(), PathResolutionError> {
238238
"{}",
239239
)?;
240240

241+
verify_not((&[a], var1), (&[], var1))?;
242+
verify_not((&[], var1), (&[a], var1))?;
243+
241244
let dot = (".", None);
242245
let b = ("b", None);
243246

@@ -430,6 +433,9 @@ fn can_unify_partial_scope_stacks() -> Result<(), PathResolutionError> {
430433
"{$2 => ($1)}",
431434
)?;
432435

436+
verify_not((&[10], var1), (&[], var1))?;
437+
verify_not((&[], var1), (&[10], var1))?;
438+
433439
Ok(())
434440
}
435441

0 commit comments

Comments
 (0)