This ended up being a bit more complicated than I expected.
It appears that the pattern match desugaring produces code that is all right. However, what it generates can look something like:
scrut = ...
match scrut with
C x y z ->
...
let
scrut = ...
match scrut with ...
result
scrut
So, the second scrut binding is supposed to be out of scope by the last occurrence. But then the scopes get flattened, and the second binding was capturing the last scrut occurrence.
So, this is the issue I actually fixed, because you could manually write code like this and trigger the same problem (although I guess it would be unlikely). The pattern desugaring does have freshness checks, and they seemed to work on some variations I tried (e.g. if the 'whole pattern' variable for the first match occurs in a case in the second match), so I think it doesn't introduce variable captures on its own. It was just this flattening issue.
This ended up being a bit more complicated than I expected.
It appears that the pattern match desugaring produces code that is all right. However, what it generates can look something like:
So, the second
scrut
binding is supposed to be out of scope by the last occurrence. But then the scopes get flattened, and the second binding was capturing the lastscrut
occurrence.So, this is the issue I actually fixed, because you could manually write code like this and trigger the same problem (although I guess it would be unlikely). The pattern desugaring does have freshness checks, and they seemed to work on some variations I tried (e.g. if the 'whole pattern' variable for the first match occurs in a case in the second match), so I think it doesn't introduce variable captures on its own. It was just this flattening issue.
Fixes #5419