Sasha Bogicevic pushed to branch wip/27323 at Glasgow Haskell Compiler / GHC
Commits:
-
15ece296
by mangoiv at 2026-10-08T15:14:56-04:00
-
c0823135
by mangoiv at 2026-10-08T15:14:56-04:00
-
f76464cf
by Zubin Duggal at 2026-10-08T15:15:39-04:00
-
2605998f
by Sasha Bogicevic at 2026-10-09T13:08:06+02:00
20 changed files:
- .gitlab-ci.yml
- + changelog.d/27845
- + changelog.d/T27323
- compiler/GHC/HsToCore/Match.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Pmc.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/HsToCore/Utils.hs
- compiler/GHC/Types/Demand.hs
- + testsuite/tests/dmdanal/should_run/T27845.hs
- + testsuite/tests/dmdanal/should_run/T27845.stdout
- + testsuite/tests/dmdanal/should_run/T27845_Lib.hs
- + testsuite/tests/dmdanal/should_run/T27845b.hs
- + testsuite/tests/dmdanal/should_run/T27845b.stdout
- + testsuite/tests/dmdanal/should_run/T27845b_Lib.hs
- testsuite/tests/dmdanal/should_run/all.T
- + testsuite/tests/pmcheck/should_compile/T27323.hs
- + testsuite/tests/pmcheck/should_compile/T27323b.hs
- testsuite/tests/pmcheck/should_compile/all.T
Changes:
| ... | ... | @@ -137,15 +137,37 @@ workflow: |
| 137 | 137 | .lint:
|
| 138 | 138 | stage: tool-lint
|
| 139 | 139 | tags:
|
| 140 | - - lint
|
|
| 141 | - before_script:
|
|
| 142 | - # Allow Git to read from the runner-owned checkout. This is needed
|
|
| 143 | - # for example by the lint-author job.
|
|
| 144 | - - git config --global --add safe.directory "$CI_PROJECT_DIR"
|
|
| 140 | + - lint-anyarch
|
|
| 141 | + image: debian:13
|
|
| 145 | 142 | rules:
|
| 146 | 143 | - *drafts-can-fail-lint
|
| 147 | 144 | - when: always
|
| 148 | 145 | |
| 146 | +.install-ghc-toolchain: &install-ghc-toolchain
|
|
| 147 | + - apt update
|
|
| 148 | + - apt install -qy build-essential curl libffi-dev libffi8 libgmp-dev libgmp10 libncurses-dev libncurses6 libtinfo6 pkg-config python3 cmake git happy alex autoconf automake python3 libgmp-dev libnuma-dev libncurses-dev
|
|
| 149 | + - curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | BOOTSTRAP_HASKELL_NONINTERACTIVE=1 BOOTSTRAP_HASKELL_MINIMAL=1 sh
|
|
| 150 | + - source /root/.ghcup/env
|
|
| 151 | + - ghcup --no-verbose install ghc --set --install-targets 'install_bin install_lib update_package_db' '9.10'
|
|
| 152 | + - ghcup --no-verbose install cabal --set
|
|
| 153 | + - ghc --info
|
|
| 154 | + - cabal --version
|
|
| 155 | + |
|
| 156 | +# linting but we need a boot toolchain
|
|
| 157 | +.lint-ghc-toolchain:
|
|
| 158 | + extends: .lint
|
|
| 159 | + before_script:
|
|
| 160 | + - *install-ghc-toolchain
|
|
| 161 | + - git config --global --add safe.directory "$CI_PROJECT_DIR"
|
|
| 162 | + |
|
| 163 | +# linting but we need python
|
|
| 164 | +.lint-python:
|
|
| 165 | + extends: .lint
|
|
| 166 | + before_script:
|
|
| 167 | + - apt update
|
|
| 168 | + - apt install -qy python3 mypy shellcheck git
|
|
| 169 | + - git config --global --add safe.directory "$CI_PROJECT_DIR"
|
|
| 170 | + |
|
| 149 | 171 | .nightly: &nightly
|
| 150 | 172 | variables:
|
| 151 | 173 | XZ_OPT: "-9"
|
| ... | ... | @@ -217,11 +239,11 @@ not-interruptible: |
| 217 | 239 | stage: not-interruptible
|
| 218 | 240 | script: "true"
|
| 219 | 241 | interruptible: false
|
| 220 | - image: "debian:13"
|
|
| 242 | + image: debian:13
|
|
| 221 | 243 | variables:
|
| 222 | 244 | GIT_STRATEGY: none
|
| 223 | 245 | tags:
|
| 224 | - - lint
|
|
| 246 | + - lint-anyarch
|
|
| 225 | 247 | rules:
|
| 226 | 248 | # - if: '$CI_COMMIT_BRANCH == "master"'
|
| 227 | 249 | # when: always
|
| ... | ... | @@ -242,7 +264,6 @@ include: '.gitlab/jobs.yaml' |
| 242 | 264 | |
| 243 | 265 | ghc-linters:
|
| 244 | 266 | stage: tool-lint
|
| 245 | - image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb13:$DOCKER_REV"
|
|
| 246 | 267 | extends: .lint-params
|
| 247 | 268 | variables:
|
| 248 | 269 | BUILD_FLAVOUR: default
|
| ... | ... | @@ -258,16 +279,11 @@ ghc-linters: |
| 258 | 279 | # Skipped if the MR has the ~"no-changelog" label.
|
| 259 | 280 | lint-changelog:
|
| 260 | 281 | stage: tool-lint
|
| 261 | - image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb13:$DOCKER_REV"
|
|
| 262 | - extends: .lint
|
|
| 282 | + extends: .lint-ghc-toolchain
|
|
| 263 | 283 | variables:
|
| 264 | 284 | CHANGELOG_EXPECT_MR: "$CI_MERGE_REQUEST_IID"
|
| 265 | 285 | GIT_DEPTH: 1
|
| 266 | 286 | GIT_SUBMODULE_STRATEGY: none
|
| 267 | - before_script:
|
|
| 268 | - - export PATH="/opt/toolchain/bin:$PATH"
|
|
| 269 | - # workaround for docker permissions
|
|
| 270 | - - sudo chown ghc:ghc -R .
|
|
| 271 | 287 | script:
|
| 272 | 288 | - .gitlab/ci.sh lint_changelog
|
| 273 | 289 | dependencies: []
|
| ... | ... | @@ -279,42 +295,30 @@ lint-changelog: |
| 279 | 295 | |
| 280 | 296 | # Run mypy Python typechecker on linter scripts.
|
| 281 | 297 | lint-linters:
|
| 282 | - image: "registry.gitlab.haskell.org/ghc/ci-images/linters:$DOCKER_REV"
|
|
| 283 | - extends: .lint
|
|
| 298 | + extends: .lint-python
|
|
| 284 | 299 | variables:
|
| 285 | 300 | GIT_DEPTH: 1
|
| 286 | 301 | GIT_SUBMODULE_STRATEGY: none
|
| 287 | - before_script:
|
|
| 288 | - # workaround for docker permissions
|
|
| 289 | - - sudo chown ghc:ghc -R .
|
|
| 290 | 302 | script:
|
| 291 | 303 | - mypy testsuite/tests/linters/regex-linters/*.py
|
| 292 | 304 | dependencies: []
|
| 293 | 305 | |
| 294 | 306 | # Check that .T files all parse by listing broken tests.
|
| 295 | 307 | lint-testsuite:
|
| 296 | - image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb13:$DOCKER_REV"
|
|
| 297 | - extends: .lint
|
|
| 308 | + extends: .lint-ghc-toolchain
|
|
| 298 | 309 | variables:
|
| 299 | 310 | GIT_DEPTH: 1
|
| 300 | 311 | GIT_SUBMODULE_STRATEGY: none
|
| 301 | - before_script:
|
|
| 302 | - # workaround for docker permissions
|
|
| 303 | - - sudo chown ghc:ghc -R .
|
|
| 304 | 312 | script:
|
| 305 | - - make -Ctestsuite list_broken TEST_HC=$GHC
|
|
| 313 | + - make -Ctestsuite list_broken TEST_HC=$(which ghc)
|
|
| 306 | 314 | dependencies: []
|
| 307 | 315 | |
| 308 | 316 | # Run mypy Python typechecker on testsuite driver
|
| 309 | 317 | typecheck-testsuite:
|
| 310 | - image: "registry.gitlab.haskell.org/ghc/ci-images/linters:$DOCKER_REV"
|
|
| 311 | - extends: .lint
|
|
| 318 | + extends: .lint-python
|
|
| 312 | 319 | variables:
|
| 313 | 320 | GIT_DEPTH: 1
|
| 314 | 321 | GIT_SUBMODULE_STRATEGY: none
|
| 315 | - before_script:
|
|
| 316 | - # workaround for docker permissions
|
|
| 317 | - - sudo chown ghc:ghc -R .
|
|
| 318 | 322 | script:
|
| 319 | 323 | - mypy testsuite/driver/runtests.py
|
| 320 | 324 | dependencies: []
|
| ... | ... | @@ -323,7 +327,6 @@ typecheck-testsuite: |
| 323 | 327 | # accommodate, e.g., haddock changes not yet upstream) but not on `master` or
|
| 324 | 328 | # Marge jobs.
|
| 325 | 329 | .lint-submods:
|
| 326 | - image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb13:$DOCKER_REV"
|
|
| 327 | 330 | extends: .lint-params
|
| 328 | 331 | variables:
|
| 329 | 332 | BUILD_FLAVOUR: default
|
| ... | ... | @@ -341,13 +344,9 @@ typecheck-testsuite: |
| 341 | 344 | # Check that commits in an MR were not authored with the identity that CI uses
|
| 342 | 345 | # when it needs to create commits itself. This only needs Git history.
|
| 343 | 346 | lint-author:
|
| 344 | - image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb13:$DOCKER_REV"
|
|
| 345 | - extends: .lint
|
|
| 347 | + extends: .lint-python
|
|
| 346 | 348 | variables:
|
| 347 | 349 | GIT_SUBMODULE_STRATEGY: none
|
| 348 | - before_script:
|
|
| 349 | - # workaround for docker permissions
|
|
| 350 | - - sudo chown ghc:ghc -R .
|
|
| 351 | 350 | script:
|
| 352 | 351 | - git fetch "$CI_MERGE_REQUEST_PROJECT_URL" $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
| 353 | 352 | - base="$(git merge-base FETCH_HEAD $CI_COMMIT_SHA)"
|
| ... | ... | @@ -425,12 +424,9 @@ lint-submods-branch: |
| 425 | 424 | |
| 426 | 425 | .lint-params:
|
| 427 | 426 | needs: []
|
| 428 | - image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb13:$DOCKER_REV"
|
|
| 429 | 427 | extends: .lint
|
| 430 | 428 | before_script:
|
| 431 | - - export PATH="/opt/toolchain/bin:$PATH"
|
|
| 432 | - # workaround for docker permissions
|
|
| 433 | - - sudo chown ghc:ghc -R .
|
|
| 429 | + - *install-ghc-toolchain
|
|
| 434 | 430 | - .gitlab/ci.sh setup
|
| 435 | 431 | after_script:
|
| 436 | 432 | - .gitlab/ci.sh save_cache
|
| ... | ... | @@ -448,18 +444,13 @@ lint-submods-branch: |
| 448 | 444 | |
| 449 | 445 | hadrian-ghc-in-ghci:
|
| 450 | 446 | stage: quick-build
|
| 447 | + extends: .lint-ghc-toolchain
|
|
| 451 | 448 | needs:
|
| 452 | 449 | - job: lint-linters
|
| 453 | 450 | - job: lint-submods
|
| 454 | 451 | optional: true
|
| 455 | - image: "registry.gitlab.haskell.org/ghc/ci-images/x86_64-linux-deb13:$DOCKER_REV"
|
|
| 456 | - before_script:
|
|
| 457 | - # workaround for docker permissions
|
|
| 458 | - - sudo chown ghc:ghc -R .
|
|
| 459 | 452 | variables:
|
| 460 | 453 | GHC_FLAGS: -Werror -Wwarn=unused-imports
|
| 461 | - tags:
|
|
| 462 | - - x86_64-linux
|
|
| 463 | 454 | script:
|
| 464 | 455 | - git clean -xdf && git submodule foreach git clean -xdf
|
| 465 | 456 | - . .gitlab/ci.sh setup
|
| ... | ... | @@ -544,6 +535,7 @@ stack-hadrian-build: |
| 544 | 535 | extends: hadrian-ghc-in-ghci
|
| 545 | 536 | stage: quick-build
|
| 546 | 537 | script:
|
| 538 | + - ghcup --no-verbose install stack --set
|
|
| 547 | 539 | - . .gitlab/ci.sh setup
|
| 548 | 540 | - . .gitlab/ci.sh configure
|
| 549 | 541 | - hadrian/build-stack --version
|
| 1 | +section: compiler
|
|
| 2 | +synopsis: Fix a bug where an argument used lazily only by a function's stable
|
|
| 3 | + unfolding could be treated as strict in its fields.
|
|
| 4 | +mrs: !16746
|
|
| 5 | +issues: #27845 |
| 1 | +section: compiler
|
|
| 2 | +synopsis: Don't report ``-XStrict``-generated bang patterns under ``-Wredundant-bang-patterns``
|
|
| 3 | +description:
|
|
| 4 | + Bangs introduced by ``-XStrict`` are no longer reported as redundant under
|
|
| 5 | + ``-Wredundant-bang-patterns``, as they are not user-written.
|
|
| 6 | +issues: #27323
|
|
| 7 | +mrs: !16395 |
| ... | ... | @@ -383,12 +383,14 @@ tidyEqnInfo :: MatchId -> EquationInfo |
| 383 | 383 | |
| 384 | 384 | tidyEqnInfo _ eqn@(EqnDone {}) = return (idDsWrapper, eqn)
|
| 385 | 385 | |
| 386 | -tidyEqnInfo v eqn@(EqnMatch { eqn_pat = (L loc pat) }) = do
|
|
| 387 | - (wrap, pat') <- tidy1 v (not . isGoodSrcSpan . locA $ loc) pat
|
|
| 386 | +tidyEqnInfo v eqn@(EqnMatch { eqn_pat = p@(L loc _) }) = do
|
|
| 387 | + (wrap, pat') <- tidyLPat v p
|
|
| 388 | 388 | return (wrap, eqn{eqn_pat = L loc pat' })
|
| 389 | 389 | |
| 390 | +tidyLPat :: MatchId -> LPat GhcTc -> DsM (DsWrapper, Pat GhcTc)
|
|
| 391 | +tidyLPat v (L loc pat) = putSrcSpanDsA loc (tidy1 v pat)
|
|
| 392 | + |
|
| 390 | 393 | tidy1 :: MatchId -- The scrutinee
|
| 391 | - -> Bool -- `True` if the pattern was generated, `False` if it was user-written
|
|
| 392 | 394 | -> Pat GhcTc -- The pattern against which it is to be matched
|
| 393 | 395 | -> DsM (DsWrapper, -- Extra bindings to do before the match
|
| 394 | 396 | Pat GhcTc) -- Equivalent pattern
|
| ... | ... | @@ -399,21 +401,22 @@ tidy1 :: MatchId -- The scrutinee |
| 399 | 401 | -- It eliminates many pattern forms (as-patterns, variable patterns,
|
| 400 | 402 | -- list patterns, etc) and returns any created bindings in the wrapper.
|
| 401 | 403 | |
| 402 | -tidy1 v g (ParPat _ pat) = tidy1 v g (unLoc pat)
|
|
| 403 | -tidy1 v g (SigPat _ pat _) = tidy1 v g (unLoc pat)
|
|
| 404 | -tidy1 _ _ (WildPat ty) = return (idDsWrapper, WildPat ty)
|
|
| 405 | -tidy1 v g (BangPat _ (L l p)) = tidy_bang_pat v g l p
|
|
| 406 | -tidy1 v g (ModifiedPat _ _ pat) = tidy1 v g (unLoc pat)
|
|
| 404 | +tidy1 v (ParPat _ pat) = tidyLPat v pat
|
|
| 405 | +tidy1 v (SigPat _ pat _) = tidyLPat v pat
|
|
| 406 | +tidy1 _ (WildPat ty) = return (idDsWrapper, WildPat ty)
|
|
| 407 | +tidy1 v (BangPat _ (L l p)) = putSrcSpanDsA l $ tidy_bang_pat v l p
|
|
| 408 | +tidy1 v (ModifiedPat _ _ pat) = tidyLPat v pat
|
|
| 407 | 409 | |
| 408 | 410 | -- case v of { x -> mr[] }
|
| 409 | 411 | -- = case v of { _ -> let x=v in mr[] }
|
| 410 | -tidy1 v _ (VarPat _ (L _ var))
|
|
| 412 | +tidy1 v (VarPat _ (L _ var))
|
|
| 411 | 413 | = return (bindMatchId var v, WildPat (idType var))
|
| 412 | 414 | |
| 413 | 415 | -- case v of { x@p -> mr[] }
|
| 414 | 416 | -- = case v of { p -> let x=v in mr[] }
|
| 415 | -tidy1 v g (AsPat _ (L _ var) pat)
|
|
| 416 | - = do { (wrap, pat') <- tidy1 v g (unLoc pat)
|
|
| 417 | +tidy1 v (AsPat _ (L _ var) pat)
|
|
| 418 | + |
|
| 419 | + = do { (wrap, pat') <- tidyLPat v pat
|
|
| 417 | 420 | ; return (bindMatchId var v . wrap, pat') }
|
| 418 | 421 | |
| 419 | 422 | {- now, here we handle lazy patterns:
|
| ... | ... | @@ -427,7 +430,7 @@ tidy1 v g (AsPat _ (L _ var) pat) |
| 427 | 430 | The case expr for v_i is just: match [v] [(p, [], \ x -> Var v_i)] any_expr
|
| 428 | 431 | -}
|
| 429 | 432 | |
| 430 | -tidy1 v _ (LazyPat _ pat)
|
|
| 433 | +tidy1 v (LazyPat _ pat)
|
|
| 431 | 434 | -- This is a convenient place to check for unlifted types under a lazy pattern.
|
| 432 | 435 | -- Doing this check during type-checking is unsatisfactory because we may
|
| 433 | 436 | -- not fully know the zonked types yet. We sure do here.
|
| ... | ... | @@ -441,14 +444,14 @@ tidy1 v _ (LazyPat _ pat) |
| 441 | 444 | ; let sel_binds = [NonRec b rhs | (b,rhs) <- sel_prs]
|
| 442 | 445 | ; return (mkCoreLets sel_binds, WildPat (matchIdType v)) }
|
| 443 | 446 | |
| 444 | -tidy1 _ _ (ListPat ty pats)
|
|
| 447 | +tidy1 _ (ListPat ty pats)
|
|
| 445 | 448 | = return (idDsWrapper, unLoc list_ConPat)
|
| 446 | 449 | where
|
| 447 | 450 | list_ConPat = foldr (\ x y -> mkPrefixConPat consDataCon [x, y] [ty])
|
| 448 | 451 | (mkNilPat ty)
|
| 449 | 452 | pats
|
| 450 | 453 | |
| 451 | -tidy1 _ _ (TuplePat tys pats boxity)
|
|
| 454 | +tidy1 _ (TuplePat tys pats boxity)
|
|
| 452 | 455 | = return (idDsWrapper, unLoc tuple_ConPat)
|
| 453 | 456 | where
|
| 454 | 457 | arity = length pats
|
| ... | ... | @@ -458,34 +461,37 @@ tidy1 _ _ (TuplePat tys pats boxity) |
| 458 | 461 | Boxed -> tys
|
| 459 | 462 | -- See Note [Unboxed tuple RuntimeRep vars] in TyCon
|
| 460 | 463 | |
| 461 | -tidy1 _ _ (SumPat tys pat alt arity)
|
|
| 464 | +tidy1 _ (SumPat tys pat alt arity)
|
|
| 462 | 465 | = return (idDsWrapper, unLoc sum_ConPat)
|
| 463 | 466 | where
|
| 464 | 467 | sum_ConPat = mkPrefixConPat (sumDataCon alt arity) [pat] (map getRuntimeRep tys ++ tys)
|
| 465 | 468 | -- See Note [Unboxed tuple RuntimeRep vars] in TyCon
|
| 466 | 469 | |
| 467 | 470 | -- LitPats: we *might* be able to replace these w/ a simpler form
|
| 468 | -tidy1 _ g (LitPat _ lit)
|
|
| 469 | - = do { unless g $
|
|
| 471 | +tidy1 _ (LitPat _ lit)
|
|
| 472 | + = do { in_gen <- inGeneratedCodeDs;
|
|
| 473 | + unless in_gen $
|
|
| 470 | 474 | warnAboutOverflowedLit lit
|
| 471 | 475 | ; return (idDsWrapper, tidyLitPat lit) }
|
| 472 | 476 | |
| 473 | 477 | -- NPats: we *might* be able to replace these w/ a simpler form
|
| 474 | -tidy1 _ g (NPat ty (L _ lit@OverLit { ol_val = v }) mb_neg eq)
|
|
| 475 | - = do { unless g $
|
|
| 478 | +tidy1 _ (NPat ty (L _ lit@OverLit { ol_val = v }) mb_neg eq)
|
|
| 479 | + = do { in_gen <- inGeneratedCodeDs;
|
|
| 480 | + unless in_gen $
|
|
| 476 | 481 | let lit' | Just _ <- mb_neg = lit{ ol_val = negateOverLitVal v }
|
| 477 | 482 | | otherwise = lit
|
| 478 | 483 | in warnAboutOverflowedOverLit lit'
|
| 479 | 484 | ; return (idDsWrapper, tidyNPat lit mb_neg eq ty) }
|
| 480 | 485 | |
| 481 | 486 | -- NPlusKPat: we may want to warn about the literals
|
| 482 | -tidy1 _ g n@(NPlusKPat _ _ (L _ lit1) lit2 _ _)
|
|
| 483 | - = do { unless g $ do
|
|
| 487 | +tidy1 _ n@(NPlusKPat _ _ (L _ lit1) lit2 _ _)
|
|
| 488 | + = do { in_gen <- inGeneratedCodeDs;
|
|
| 489 | + unless in_gen $ do
|
|
| 484 | 490 | warnAboutOverflowedOverLit lit1
|
| 485 | 491 | warnAboutOverflowedOverLit lit2
|
| 486 | 492 | ; return (idDsWrapper, n) }
|
| 487 | 493 | |
| 488 | -tidy1 _ _ (OrPat ty lpats)
|
|
| 494 | +tidy1 _ (OrPat ty lpats)
|
|
| 489 | 495 | -- See Note [Implementation of OrPatterns]. We desugar
|
| 490 | 496 | -- (1; 2; 3)
|
| 491 | 497 | -- to
|
| ... | ... | @@ -514,44 +520,44 @@ tidy1 _ _ (OrPat ty lpats) |
| 514 | 520 | single_grhs e = GRHSs emptyComments [noLocA $ GRHS noAnn [] e] (EmptyLocalBinds noExtField)
|
| 515 | 521 | |
| 516 | 522 | -- Everything else goes through unchanged...
|
| 517 | -tidy1 _ _ non_interesting_pat
|
|
| 523 | +tidy1 _ non_interesting_pat
|
|
| 518 | 524 | = return (idDsWrapper, non_interesting_pat)
|
| 519 | 525 | |
| 520 | 526 | --------------------
|
| 521 | -tidy_bang_pat :: MatchId -> Bool -> SrcSpanAnnA -> Pat GhcTc
|
|
| 527 | +tidy_bang_pat :: MatchId -> SrcSpanAnnA -> Pat GhcTc
|
|
| 522 | 528 | -> DsM (DsWrapper, Pat GhcTc)
|
| 523 | 529 | |
| 524 | 530 | -- Discard par/sig under a bang
|
| 525 | -tidy_bang_pat v g _ (ParPat _ (L l p)) = tidy_bang_pat v g l p
|
|
| 526 | -tidy_bang_pat v g _ (SigPat _ (L l p) _) = tidy_bang_pat v g l p
|
|
| 531 | +tidy_bang_pat v _ (ParPat _ (L l p)) = putSrcSpanDsA l $ tidy_bang_pat v l p
|
|
| 532 | +tidy_bang_pat v _ (SigPat _ (L l p) _) = putSrcSpanDsA l $ tidy_bang_pat v l p
|
|
| 527 | 533 | |
| 528 | 534 | -- Push the bang-pattern inwards, in the hope that
|
| 529 | 535 | -- it may disappear next time
|
| 530 | -tidy_bang_pat v g l (AsPat x v' p)
|
|
| 531 | - = tidy1 v g (AsPat x v' (L l (BangPat noExtField p)))
|
|
| 532 | -tidy_bang_pat v g l (XPat (CoPat w p t))
|
|
| 533 | - = tidy1 v g (XPat $ CoPat w (BangPat noExtField (L l p)) t)
|
|
| 534 | -tidy_bang_pat v g l (OrPat x (p:|ps)) -- push bang into first pat alt
|
|
| 535 | - = tidy1 v g (OrPat x (L l (BangPat noExtField p) :| ps))
|
|
| 536 | +tidy_bang_pat v l (AsPat x v' p)
|
|
| 537 | + = tidy1 v (AsPat x v' (L l (BangPat noExtField p)))
|
|
| 538 | +tidy_bang_pat v l (XPat (CoPat w p t))
|
|
| 539 | + = tidy1 v (XPat $ CoPat w (BangPat noExtField (L l p)) t)
|
|
| 540 | +tidy_bang_pat v l (OrPat x (p:|ps)) -- push bang into first pat alt
|
|
| 541 | + = tidy1 v (OrPat x (L l (BangPat noExtField p) :| ps))
|
|
| 536 | 542 | |
| 537 | 543 | -- Discard bang around strict pattern
|
| 538 | -tidy_bang_pat v g _ p@(LitPat {}) = tidy1 v g p
|
|
| 539 | -tidy_bang_pat v g _ p@(ListPat {}) = tidy1 v g p
|
|
| 540 | -tidy_bang_pat v g _ p@(TuplePat {}) = tidy1 v g p
|
|
| 541 | -tidy_bang_pat v g _ p@(SumPat {}) = tidy1 v g p
|
|
| 544 | +tidy_bang_pat v _ p@(LitPat {}) = tidy1 v p
|
|
| 545 | +tidy_bang_pat v _ p@(ListPat {}) = tidy1 v p
|
|
| 546 | +tidy_bang_pat v _ p@(TuplePat {}) = tidy1 v p
|
|
| 547 | +tidy_bang_pat v _ p@(SumPat {}) = tidy1 v p
|
|
| 542 | 548 | |
| 543 | 549 | -- Data/newtype constructors
|
| 544 | -tidy_bang_pat v g l p@(ConPat { pat_con = L _ (RealDataCon dc)
|
|
| 545 | - , pat_args = args
|
|
| 546 | - , pat_con_ext = ConPatTc
|
|
| 547 | - { cpt_arg_tys = arg_tys
|
|
| 548 | - }
|
|
| 549 | - })
|
|
| 550 | +tidy_bang_pat v l p@(ConPat { pat_con = L _ (RealDataCon dc)
|
|
| 551 | + , pat_args = args
|
|
| 552 | + , pat_con_ext = ConPatTc
|
|
| 553 | + { cpt_arg_tys = arg_tys
|
|
| 554 | + }
|
|
| 555 | + })
|
|
| 550 | 556 | -- Newtypes: push bang inwards (#9844)
|
| 551 | 557 | =
|
| 552 | 558 | if isNewTyCon (dataConTyCon dc)
|
| 553 | - then tidy1 v g (p { pat_args = push_bang_into_newtype_arg l (scaledThing ty) args })
|
|
| 554 | - else tidy1 v g p -- Data types: discard the bang
|
|
| 559 | + then tidy1 v (p { pat_args = push_bang_into_newtype_arg l (scaledThing ty) args })
|
|
| 560 | + else tidy1 v p -- Data types: discard the bang
|
|
| 555 | 561 | where
|
| 556 | 562 | (ty:_) = dataConInstArgTys dc arg_tys
|
| 557 | 563 | |
| ... | ... | @@ -570,7 +576,7 @@ tidy_bang_pat v g l p@(ConPat { pat_con = L _ (RealDataCon dc) |
| 570 | 576 | --
|
| 571 | 577 | -- NB: SigPatIn, ConPatIn should not happen
|
| 572 | 578 | |
| 573 | -tidy_bang_pat _ _ l p = return (idDsWrapper, BangPat noExtField (L l p))
|
|
| 579 | +tidy_bang_pat _ l p = return (idDsWrapper, BangPat noExtField (L l p))
|
|
| 574 | 580 | |
| 575 | 581 | -------------------
|
| 576 | 582 | push_bang_into_newtype_arg :: SrcSpanAnnA
|
| ... | ... | @@ -954,7 +960,7 @@ matchSinglePatVar var mb_scrut ctx pat ty match_result |
| 954 | 960 | ; ldi_nablas <-
|
| 955 | 961 | if isMatchContextPmChecked_SinglePat dflags FromSource ctx pat
|
| 956 | 962 | then addCoreScrutTmCs (maybeToList mb_scrut) [var] $
|
| 957 | - pmcPatBind (DsMatchContext ctx locn) var (unLoc pat)
|
|
| 963 | + pmcPatBind (DsMatchContext ctx locn) var pat
|
|
| 958 | 964 | else getLdiNablas
|
| 959 | 965 | |
| 960 | 966 | ; let eqn_info = EqnMatch { eqn_pat = decideBangHood dflags pat
|
| ... | ... | @@ -15,7 +15,7 @@ module GHC.HsToCore.Monad ( |
| 15 | 15 | duplicateLocalDs, newSysLocalDs, newSysLocalsDs,
|
| 16 | 16 | newSysLocalMDs, newSysLocalsMDs, newFailLocalMDs,
|
| 17 | 17 | newUniqueId, newPredVarDs, newStaticId,
|
| 18 | - getSrcSpanDs, putSrcSpanDs, putSrcSpanDsA,
|
|
| 18 | + getSrcSpanDs, inGeneratedCodeDs, putSrcSpanDs, putSrcSpanDsA,
|
|
| 19 | 19 | mkNamePprCtxDs,
|
| 20 | 20 | newUnique,
|
| 21 | 21 | UniqSupply, newUniqueSupply,
|
| ... | ... | @@ -584,6 +584,7 @@ mkDsEnvs unit_env mod rdr_env type_env fam_inst_env tcm_plugins ptc msg_var |
| 584 | 584 | , dsl_loc = real_span
|
| 585 | 585 | , dsl_nablas = Ldi initNablas
|
| 586 | 586 | , dsl_unspecables = Just emptyVarSet
|
| 587 | + , dsl_in_generated_code = False
|
|
| 587 | 588 | }
|
| 588 | 589 | in (gbl_env, lcl_env)
|
| 589 | 590 | |
| ... | ... | @@ -676,13 +677,17 @@ getSrcSpanDs :: DsM SrcSpan |
| 676 | 677 | getSrcSpanDs = do { env <- getLclEnv
|
| 677 | 678 | ; return (RealSrcSpan (dsl_loc env) Strict.Nothing) }
|
| 678 | 679 | |
| 680 | +-- | See 'dsl_in_generated_code'
|
|
| 681 | +inGeneratedCodeDs :: DsM Bool
|
|
| 682 | +inGeneratedCodeDs = dsl_in_generated_code <$> getLclEnv
|
|
| 683 | + |
|
| 679 | 684 | putSrcSpanDs :: SrcSpan -> DsM a -> DsM a
|
| 680 | 685 | putSrcSpanDs (RealSrcSpan real_span _) thing_inside
|
| 681 | - = updLclEnv (\ env -> env {dsl_loc = real_span}) thing_inside
|
|
| 686 | + = updLclEnv (\ env -> env {dsl_loc = real_span, dsl_in_generated_code = False}) thing_inside
|
|
| 682 | 687 | putSrcSpanDs UnhelpfulSpan{} thing_inside
|
| 683 | 688 | = thing_inside
|
| 684 | 689 | putSrcSpanDs GeneratedSrcSpan{} thing_inside
|
| 685 | - = thing_inside
|
|
| 690 | + = updLclEnv (\ env -> env {dsl_in_generated_code = True}) thing_inside
|
|
| 686 | 691 | |
| 687 | 692 | putSrcSpanDsA :: EpAnn ann -> DsM a -> DsM a
|
| 688 | 693 | putSrcSpanDsA loc = putSrcSpanDs (locA loc)
|
| ... | ... | @@ -104,7 +104,7 @@ whenDoingPmc no_pmc thing_inside |
| 104 | 104 | Ldi nablas -> thing_inside nablas }
|
| 105 | 105 | |
| 106 | 106 | -- | Check a pattern binding (let, where) for exhaustiveness.
|
| 107 | -pmcPatBind :: DsMatchContext -> Id -> Pat GhcTc -> DsM LdiNablas
|
|
| 107 | +pmcPatBind :: DsMatchContext -> Id -> LPat GhcTc -> DsM LdiNablas
|
|
| 108 | 108 | pmcPatBind ctxt@(DsMatchContext match_ctxt loc) var p
|
| 109 | 109 | = whenDoingPmc NoPmc $ \ !missing ->
|
| 110 | 110 | mb_discard_warnings $ do
|
| ... | ... | @@ -155,11 +155,15 @@ desugarPat x pat = case pat of |
| 155 | 155 | VarPat _ y -> pure (mkPmLetVar (unLoc y) x)
|
| 156 | 156 | ParPat _ p -> desugarLPat x p
|
| 157 | 157 | LazyPat _ _ -> pure GdEnd -- like a wildcard
|
| 158 | - BangPat _ p@(L l p') ->
|
|
| 158 | + BangPat _ p@(L l p') -> do
|
|
| 159 | 159 | -- Add the bang in front of the list, because it will happen before any
|
| 160 | 160 | -- nested stuff.
|
| 161 | + in_gen <- inGeneratedCodeDs
|
|
| 162 | + -- A bang inserted by -XStrict (decideBangHood) has no SrcInfo: it is
|
|
| 163 | + -- divergence-checked but never reported as redundant (#27323).
|
|
| 164 | + let pm_loc | in_gen = Nothing
|
|
| 165 | + | otherwise = Just (SrcInfo (L (locA l) (ppr p')))
|
|
| 161 | 166 | consGrdDag (PmBang x pm_loc) <$> desugarLPat x p
|
| 162 | - where pm_loc = Just (SrcInfo (L (locA l) (ppr p')))
|
|
| 163 | 167 | |
| 164 | 168 | -- (x@pat) ==> Desugar pat with x as match var and handle impedance
|
| 165 | 169 | -- mismatch with incoming match var
|
| ... | ... | @@ -311,7 +315,7 @@ desugarPatV pat = do |
| 311 | 315 | pure (x, grds)
|
| 312 | 316 | |
| 313 | 317 | desugarLPat :: Id -> LPat GhcTc -> DsM GrdDag
|
| 314 | -desugarLPat x = desugarPat x . unLoc
|
|
| 318 | +desugarLPat x (L loc pat) = putSrcSpanDsA loc (desugarPat x pat)
|
|
| 315 | 319 | |
| 316 | 320 | -- | 'desugarLPat', but also select and return a new match var.
|
| 317 | 321 | desugarLPatV :: LPat GhcTc -> DsM (Id, GrdDag)
|
| ... | ... | @@ -374,11 +378,11 @@ desugarConPatOut x con univ_tys ex_tvs dicts = \case |
| 374 | 378 | -- tracePm "ConPatOut" (ppr x $$ ppr con $$ ppr arg_ids)
|
| 375 | 379 | pure (con_grd `consGrdDag` arg_grds)
|
| 376 | 380 | |
| 377 | -desugarPatBind :: SrcSpan -> Id -> Pat GhcTc -> DsM (PmPatBind Pre)
|
|
| 381 | +desugarPatBind :: SrcSpan -> Id -> LPat GhcTc -> DsM (PmPatBind Pre)
|
|
| 378 | 382 | -- See 'GrdPatBind' for how this simply repurposes GrdGRHS.
|
| 379 | 383 | -- See Note [Suppress warnings in PMC desugaring]
|
| 380 | 384 | desugarPatBind loc var pat = discardWarningsDs $
|
| 381 | - PmPatBind . flip PmGRHS (SrcInfo (L loc (ppr pat))) <$> desugarPat var pat
|
|
| 385 | + PmPatBind . flip PmGRHS (SrcInfo (L loc (ppr pat))) <$> desugarLPat var pat
|
|
| 382 | 386 | |
| 383 | 387 | desugarEmptyCase :: Id -> DsM PmEmptyCase
|
| 384 | 388 | desugarEmptyCase var = pure PmEmptyCase { pe_var = var }
|
| ... | ... | @@ -650,4 +654,19 @@ user *had* written a bang: |
| 650 | 654 | + In an equation for ‘idV’: idV !v = ...
|
| 651 | 655 | |
| 652 | 656 | So we live with the duplication.
|
| 657 | + |
|
| 658 | +Note that 'decideBangHood' places the bangs it inserts at a 'generatedSrcSpan'.
|
|
| 659 | +When 'desugarLPat' enters such a span, 'putSrcSpanDs' (GHC.HsToCore.Monad)
|
|
| 660 | +records in 'dsl_in_generated_code' that we are desugaring compiler-generated
|
|
| 661 | +code. For a bang in generated code, 'desugarPat' emits a 'PmBang' with no
|
|
| 662 | +'SrcInfo': the checker still performs the divergence check (so the
|
|
| 663 | +inaccessible-RHS warning above survives), but -Wredundant-bang-patterns only
|
|
| 664 | +ever reports bangs the user actually wrote (#27323). See
|
|
| 665 | +Note [Dead bang patterns] in GHC.HsToCore.Pmc.Check.
|
|
| 666 | + |
|
| 667 | +Eventually the bangs inserted by -XStrict should become expanded patterns,
|
|
| 668 | +following Note [Handling overloaded and rebindable constructs] in
|
|
| 669 | +GHC.Rename.Expr. That would let warnings always display the original
|
|
| 670 | +user-written code, making the decideBangHood duplication described above
|
|
| 671 | +unnecessary. This is tracked as #27677.
|
|
| 653 | 672 | -} |
| ... | ... | @@ -11,7 +11,7 @@ module GHC.HsToCore.Types ( |
| 11 | 11 | DsMetaEnv, DsMetaVal(..), CompleteMatches
|
| 12 | 12 | ) where
|
| 13 | 13 | |
| 14 | -import GHC.Prelude (Int)
|
|
| 14 | +import GHC.Prelude (Bool, Int)
|
|
| 15 | 15 | |
| 16 | 16 | import Data.IORef
|
| 17 | 17 | |
| ... | ... | @@ -125,6 +125,7 @@ data DsLclEnv |
| 125 | 125 | -- ^ See Note [Desugaring non-canonical evidence]
|
| 126 | 126 | -- This field collects all un-specialisable evidence variables in scope.
|
| 127 | 127 | -- Nothing <=> don't collect this info (used for the LHS of Rules)
|
| 128 | + , dsl_in_generated_code :: Bool -- Desugaring compiler-generated or user-written code
|
|
| 128 | 129 | }
|
| 129 | 130 | |
| 130 | 131 | -- Inside [| |] brackets, the desugarer looks
|
| ... | ... | @@ -1025,6 +1025,9 @@ Specifically: |
| 1025 | 1025 | |
| 1026 | 1026 | |
| 1027 | 1027 | -- | Use -XStrict to add a ! or remove a ~
|
| 1028 | +-- The bang we insert is compiler-generated, so we put it at a generatedSrcSpan.
|
|
| 1029 | +-- The pattern-match checker uses this (via dsl_in_generated_code) to avoid reporting
|
|
| 1030 | +-- such bangs under -Wredundant-bang-patterns (#27323).
|
|
| 1028 | 1031 | -- See Note [decideBangHood]
|
| 1029 | 1032 | decideBangHood :: DynFlags
|
| 1030 | 1033 | -> LPat GhcTc -- ^ Original pattern
|
| ... | ... | @@ -1040,7 +1043,7 @@ decideBangHood dflags lpat |
| 1040 | 1043 | ParPat x p -> L l (ParPat x (go p))
|
| 1041 | 1044 | LazyPat _ lp' -> lp'
|
| 1042 | 1045 | BangPat _ _ -> lp
|
| 1043 | - _ -> L l (BangPat noExtField lp)
|
|
| 1046 | + _ -> L (noAnnSrcSpan generatedSrcSpan) (BangPat noExtField lp)
|
|
| 1044 | 1047 | |
| 1045 | 1048 | isTrueLHsExpr :: LHsExpr GhcTc -> Maybe (CoreExpr -> DsM CoreExpr)
|
| 1046 | 1049 |
| ... | ... | @@ -924,6 +924,8 @@ maxCard (Card a) (Card b) = Card ((a .&. b .&. 0b001) .|. ((a .|. b) .&. 0b110)) |
| 924 | 924 | maxDmd :: Demand -> Demand -> Demand
|
| 925 | 925 | maxDmd BotDmd dmd2 = dmd2
|
| 926 | 926 | maxDmd dmd1 BotDmd = dmd1
|
| 927 | +maxDmd AbsDmd dmd2 = dmd2
|
|
| 928 | +maxDmd dmd1 AbsDmd = dmd1
|
|
| 927 | 929 | maxDmd (n1 :* sd1) (n2 :* sd2) =
|
| 928 | 930 | maxCard n1 n2 :* maxSubDmd sd1 sd2
|
| 929 | 931 |
| 1 | +module Main where
|
|
| 2 | +import T27845_Lib (f)
|
|
| 3 | +import System.Environment (getArgs)
|
|
| 4 | + |
|
| 5 | +{-# NOINLINE mkArg #-}
|
|
| 6 | +mkArg :: Int -> Int
|
|
| 7 | +mkArg n | n < 0 = n
|
|
| 8 | + | otherwise = error ("boom " ++ show n)
|
|
| 9 | + |
|
| 10 | +main :: IO ()
|
|
| 11 | +main = do
|
|
| 12 | + n <- length <$> getArgs
|
|
| 13 | + let x = mkArg n
|
|
| 14 | + print (length (f (x, x) n)) |
| 1 | +0 |
| 1 | +module T27845_Lib where
|
|
| 2 | + |
|
| 3 | +{-# INLINABLE [2] f #-}
|
|
| 4 | +f :: a -> Int -> [a]
|
|
| 5 | +f p x = lazyUse p x ++ lazyUse p (x + 1) ++ lazyUse p (x + 2)
|
|
| 6 | + |
|
| 7 | +{-# NOINLINE lazyUse #-}
|
|
| 8 | +lazyUse :: a -> Int -> [a]
|
|
| 9 | +lazyUse p x = p `seq` replicate x p
|
|
| 10 | + |
|
| 11 | +{-# RULES "lazyUse" [1] forall p x. lazyUse p x = [] #-} |
| 1 | +module Main where
|
|
| 2 | +import T27845b_Lib (outer)
|
|
| 3 | +import System.Environment (getArgs)
|
|
| 4 | + |
|
| 5 | +{-# NOINLINE mkArg #-}
|
|
| 6 | +mkArg :: Int -> Int
|
|
| 7 | +mkArg n | n < 0 = n
|
|
| 8 | + | otherwise = error ("boom " ++ show n)
|
|
| 9 | + |
|
| 10 | +main :: IO ()
|
|
| 11 | +main = do
|
|
| 12 | + n <- length <$> getArgs
|
|
| 13 | + let x = mkArg n
|
|
| 14 | + print (length (outer (x, x) n)) |
| 1 | +0 |
| 1 | +module T27845b_Lib where
|
|
| 2 | + |
|
| 3 | +outer :: a -> Int -> [a]
|
|
| 4 | +outer a n =
|
|
| 5 | + let {-# INLINABLE [2] g #-}
|
|
| 6 | + g x = lazyUse a (x + 0) ++ lazyUse a (x + 1) ++ lazyUse a (x + 2)
|
|
| 7 | + in g n ++ g (n + 1) ++ g (n + 2)
|
|
| 8 | +{-# NOINLINE outer #-}
|
|
| 9 | + |
|
| 10 | +{-# NOINLINE lazyUse #-}
|
|
| 11 | +lazyUse :: a -> Int -> [a]
|
|
| 12 | +lazyUse p x = p `seq` replicate x p
|
|
| 13 | + |
|
| 14 | +{-# RULES "lazyUse" [1] forall p x. lazyUse p x = [] #-} |
| ... | ... | @@ -37,3 +37,5 @@ test('T25439', normal, compile_and_run, ['']) |
| 37 | 37 | test('T26748', normal, compile_and_run, [''])
|
| 38 | 38 | test('T26416', [extra_files(['M1.hs'])], multimod_compile_and_run, ['T26416','M1.hs'])
|
| 39 | 39 | test('T27626', [extra_files(['M2.hs'])], multimod_compile_and_run, ['T27626','M2.hs'])
|
| 40 | +test('T27845', [extra_files(['T27845_Lib.hs'])], multimod_compile_and_run, ['T27845','T27845_Lib.hs'])
|
|
| 41 | +test('T27845b', [extra_files(['T27845b_Lib.hs'])], multimod_compile_and_run, ['T27845b','T27845b_Lib.hs']) |
| 1 | +{-# LANGUAGE MagicHash, Strict #-}
|
|
| 2 | +{-# OPTIONS_GHC -Wredundant-bang-patterns #-}
|
|
| 3 | + |
|
| 4 | +import GHC.Prim (Int#)
|
|
| 5 | + |
|
| 6 | +idInt# :: Int# -> Int#
|
|
| 7 | +idInt# x = x
|
|
| 8 | + |
|
| 9 | +main = pure () |
| 1 | +{-# LANGUAGE Strict, MonoLocalBinds #-}
|
|
| 2 | +{-# OPTIONS_GHC -Wredundant-bang-patterns #-}
|
|
| 3 | +module T27323b where
|
|
| 4 | + |
|
| 5 | +f :: Int -> Int
|
|
| 6 | +f x = let (a, b) = (x, x) in a + b |
| ... | ... | @@ -190,4 +190,6 @@ test('T24845', [], compile, [overlapping_incomplete]) |
| 190 | 190 | test('T22652', [], compile, [overlapping_incomplete])
|
| 191 | 191 | test('T22652a', [], compile, [overlapping_incomplete])
|
| 192 | 192 | test('T24867', [], compile_fail, [overlapping_incomplete])
|
| 193 | +test('T27323', normal, compile, ['-Wredundant-bang-patterns'])
|
|
| 194 | +test('T27323b', normal, compile, ['-Wredundant-bang-patterns'])
|
|
| 193 | 195 | test('T27360', normal, compile, [overlapping_incomplete + '-g3']) |