compiler: re-engineer the treatment of rebindable if
-
Review changes -
-
Download -
Patches
-
Plain diff
The commit message has a pretty good summary:
Executing on the plan described in #17582, this patch changes the way if expressions are handled in the compiler in the presence of rebindable syntax. We get rid of the SyntaxExpr field of HsIf and instead, when rebindable syntax is on, we rewrite the HsIf node to the appropriate sequence of applications of the local
ifThenElse
function.In order to be able to report good error messages, with expressions as they were written by the user (and not as desugared by the renamer), we make use of TTG extensions to extend GhcRn expression ASTs with an
HsExpansion
construct, which keeps track of a source (GhcPs) expression and the desugared (GhcRn) expression that it gives rise to. This way, we can typecheck the latter while reporting the former in error messages.In order to discard the error context lines that arise from typechecking the desugared expressions (because they talk about expressions that the user has not written), we turn
ErrCtx
into more than a synonym and add a special "expansion context" construct. When such a context is pushed, only other expansion contexts can be added on top. Since onlyHsExpansion
constructs give rise to such contexts, it is enough to restrict subsequent context lines to only mention the original expressions.
The current state however isn't perfect (hence the WIP in the title). The reference output for the rebindable11
test that I am adding contains the error messages produced by 8.6.5, and my branch fails to give the same error message on the last example, with nested if
s (a4
below).
ifThenElse :: Bool -> () -> () -> Int
ifThenElse cond b1 b2 = 0
...
a4 = if (if 'a' then () else ()) == 10 then () else ()
The expected error message:
rebindable11.hs:12:13: error:
• Couldn't match expected type ‘Bool’
with actual type ‘GHC.Types.Char’
• In the expression: 'a'
In the first argument of ‘(==)’, namely ‘(if 'a' then () else ())’
In the expression: (if 'a' then () else ()) == 10
The diff:
$ diff <(ghc -c testsuite/tests/rebindable/rebindable11.hs |& cat) <(_build/stage1/bin/ghc -c testsuite/tests/rebindable/rebindable11.hs |& cat)
37d36
< In the first argument of ‘(==)’, namely ‘(if 'a' then () else ())’
38a38,39
> In the expression:
> if (if 'a' then () else ()) == 10 then () else ()
Once this is figured out, I'll implement a similar change for HsCmdIf
and add more expressions to the test.
Merge request reports
- version 227ab2de4c
- version 2149e645a2
- version 20ac663050
- version 1978abcfac
- version 18b2c88bb9
- version 1768e8a05a
- version 16992e8923
- version 15a779f7a9
- version 1499edec67
- version 13a44e0df9
- version 1229de956f
- version 1163c78c5b
- version 10e81f8f44
- version 9b069ad70
- version 8a7bd5968
- version 7f3848276
- version 604b12f40
- version 510fc58eb
- version 4c0903cfa
- version 32e42f94c
- version 2aa666922
- version 13d5c4b42
- master (base)
- latest version2e5170d31 commit,
- version 227ab2de4c5 commits,
- version 2149e645a24 commits,
- version 20ac6630503 commits,
- version 1978abcfac1 commit,
- version 18b2c88bb93 commits,
- version 1768e8a05a3 commits,
- version 16992e89234 commits,
- version 15a779f7a93 commits,
- version 1499edec672 commits,
- version 13a44e0df92 commits,
- version 1229de956f2 commits,
- version 1163c78c5b1 commit,
- version 10e81f8f441 commit,
- version 9b069ad701 commit,
- version 8a7bd59681 commit,
- version 7f38482761 commit,
- version 604b12f401 commit,
- version 510fc58eb1 commit,
- version 4c0903cfa1 commit,
- version 32e42f94c1 commit,
- version 2aa6669222 commits,
- version 13d5c4b421 commit,
- Side-by-side
- Inline