Skip to content

Duplicate variable checking in patterns#1752

Merged
cyrus- merged 20 commits intodevfrom
duplicate-variable-checking-in-patterns
Feb 17, 2026
Merged

Duplicate variable checking in patterns#1752
cyrus- merged 20 commits intodevfrom
duplicate-variable-checking-in-patterns

Conversation

@joshqwang
Copy link
Contributor

@joshqwang joshqwang commented Jul 3, 2025

Causes Hazel to give an error message on patterns that contain duplicate variables, including labels in tuples.
Screenshot 2025-07-03 at 5 18 05 PM

Added a new get_duplicate_bindings function in Term.re.
Changed Duplicate type in Self.re to DuplicateLabel so it isn't confused with the new DuplicateVar type.

@codecov
Copy link

codecov bot commented Jul 10, 2025

Codecov Report

❌ Patch coverage is 67.56757% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 50.17%. Comparing base (322405a) to head (0dd89fc).
⚠️ Report is 98 commits behind head on dev.

Files with missing lines Patch % Lines
src/language/statics/Info.re 40.00% 6 Missing ⚠️
src/language/statics/Self.re 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev    #1752      +/-   ##
==========================================
+ Coverage   49.52%   50.17%   +0.65%     
==========================================
  Files         241      231      -10     
  Lines       26676    25513    -1163     
==========================================
- Hits        13210    12801     -409     
+ Misses      13466    12712     -754     
Files with missing lines Coverage Δ
src/language/statics/Elaborator.re 81.67% <ø> (-0.39%) ⬇️
src/language/statics/Statics.re 86.99% <100.00%> (-0.32%) ⬇️
src/language/term/Pat.re 59.09% <100.00%> (-2.20%) ⬇️
src/language/statics/Info.re 45.42% <40.00%> (-3.31%) ⬇️
src/language/statics/Self.re 34.22% <0.00%> (-0.71%) ⬇️

... and 90 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@joshqwang joshqwang marked this pull request as ready for review July 10, 2025 20:17
@Negabinary
Copy link
Contributor

I'm getting a crash when I try typing

let (x,x

@joshqwang
Copy link
Contributor Author

Should be fixed now.

@Negabinary
Copy link
Contributor

I'm a little confused how the changes in statics.re work - specifically I don't understand how you managed to reuse the duplicate-label list to also do duplicate variables. Even though I don't understand it somehow almost every example I use to try and break it works including:

let (x, x=?) = ? in No error
let (x=(x, y)) = ? in No error

The one weird behaviour I could come up with is

let (x, x=(x, y)) = ? in

image

which puts the errors on the first and second x instead of the first and third.

Aside from that one issue in Statics.re I'm happy with the rest of this pr; I appreciate the bonus cleanup in elaborator/pattern!

@joshqwang
Copy link
Contributor Author

I intended initially to have duplicate variable bindings and duplicate label bindings share the same list of duplicates.

In an earlier commit, let (x, x=?) = ? in produced a DuplicateVar error and a DuplicateLabel error.

But, when I did the code cleanup in Term.re, I ended up breaking that functionality, since the function I deleted and the Term.bindings function had more differences than I realized.

I'm a little unsure what correct behavior should be here. I have a version on my machine that fixed that functionality.

Screenshot 2025-07-29 at 4 16 44 PM

But, in these case, should the labels have no error on them?

@MaxCarroll0
Copy link
Member

MaxCarroll0 commented Jul 30, 2025

I'm a little unsure what correct behavior should be here. I have a version on my machine that fixed that functionality.
...
But, in these case, should the labels have no error on them?

The x = e pattern doesn't actually bind x to anything, so the left hand side (x) should never be in a duplicate binding error (so, as you say, it should not be a duplicate label in any of your examples: there are not two labels with name x, rather a label & a variable).

And, if the right hand side (e) has duplicate variables they should be errors (e.g. the 3rd x in the 3rd example is correctly detected as an error). BUT, the 2nd x in the 2nd example should not be a duplicate variable error (only one variable x is used, the other x is a label, not a variable).

It seems like you do indeed need to distinguish duplicate labels and duplicate variables?

@joshqwang
Copy link
Contributor Author

Hopefully should be working now.
Screenshot 2025-07-31 at 1 20 24 PM

@MaxCarroll0
Copy link
Member

Looks good to me

@joshqwang joshqwang requested a review from cyrus- August 28, 2025 22:47
Copy link
Member

@cyrus- cyrus- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm other than needing a few more tests

@joshqwang joshqwang requested a review from cyrus- October 3, 2025 18:14
@dm0n3y
Copy link
Contributor

dm0n3y commented Dec 17, 2025

@cyrus- ready for review

@dm0n3y
Copy link
Contributor

dm0n3y commented Feb 13, 2026

@cyrus- resolved merge conflicts, checked that josh's example code above works, should be good to merge

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, at least not wrt dev, but there was a benign dev bug that was passing in duplicate expression-level labels into the pattern duplicates argument. benign bc the pattern duplicates arg would then later be overwritten. fixed that here while reviewing.


let get_duplicate_bindings = (pat: t) => {
let bindings = bound_vars(pat);
List.filter(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be a fn in listutil that does this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you mean the dedup fn? that returns entire list deduplicated, this returns just the duplicates.

@cyrus- cyrus- merged commit a384278 into dev Feb 17, 2026
4 checks passed
@cyrus- cyrus- deleted the duplicate-variable-checking-in-patterns branch February 17, 2026 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

Comments