Simon Jakobi pushed to branch wip/sjakobi/T2057 at Glasgow Haskell Compiler / GHC
Commits:
-
e894fe64
by Simon Jakobi at 2026-03-09T02:03:45+01:00
12 changed files:
- + testsuite/tests/driver/T2057/.gitignore
- + testsuite/tests/driver/T2057/Makefile
- + testsuite/tests/driver/T2057/README.md
- + testsuite/tests/driver/T2057/T2057.stderr
- + testsuite/tests/driver/T2057/all.T
- + testsuite/tests/driver/T2057/app/Main.hs
- + testsuite/tests/driver/T2057/pkgA1.conf.in
- + testsuite/tests/driver/T2057/pkgA1/A.hs
- + testsuite/tests/driver/T2057/pkgA2.conf.in
- + testsuite/tests/driver/T2057/pkgA2/A.hs
- + testsuite/tests/driver/T2057/pkgB.conf.in
- + testsuite/tests/driver/T2057/pkgB/B.hs
Changes:
| 1 | +work/ |
| 1 | +TOP=../../..
|
|
| 2 | +include $(TOP)/mk/boilerplate.mk
|
|
| 3 | +include $(TOP)/mk/test.mk
|
|
| 4 | + |
|
| 5 | +WORK = work
|
|
| 6 | +PKGDB = $(WORK)/pkgdb
|
|
| 7 | +PKGA1 = $(WORK)/pkgA1
|
|
| 8 | +PKGA2 = $(WORK)/pkgA2
|
|
| 9 | +PKGB = $(WORK)/pkgB
|
|
| 10 | +APP = $(WORK)/app
|
|
| 11 | +OUT = $(WORK)/T2057.out
|
|
| 12 | +BASE_ID := $(shell "$(GHC_PKG)" field base id --simple-output)
|
|
| 13 | + |
|
| 14 | +.PHONY: T2057 clean
|
|
| 15 | + |
|
| 16 | +clean:
|
|
| 17 | + rm -rf $(WORK)
|
|
| 18 | + |
|
| 19 | +# Dependency graph:
|
|
| 20 | +# pkgB is built against pkgA1, where A exports f1.
|
|
| 21 | +# We then rebuild the same installed unit id (pkgA) from the pkgA2 sources,
|
|
| 22 | +# where A instead exports f2. Reading B.hi therefore finds an unfolding for g
|
|
| 23 | +# that still refers to f1, and compiling Main against pkgB should stop at the
|
|
| 24 | +# interface error.
|
|
| 25 | +T2057: clean
|
|
| 26 | + |
|
| 27 | + # Create an isolated package DB and output directories for the repro.
|
|
| 28 | + mkdir -p '$(PKGA1)' '$(PKGA2)' '$(PKGB)' '$(APP)'
|
|
| 29 | + '$(GHC_PKG)' init '$(PKGDB)'
|
|
| 30 | + |
|
| 31 | + # Build and register pkgA1, the original version of A.
|
|
| 32 | + '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' \
|
|
| 33 | + -this-unit-id pkgA -O -c pkgA1/A.hs -outputdir '$(PKGA1)'
|
|
| 34 | + ar q '$(PKGA1)/libHSpkgA.a' '$(PKGA1)/A.o' >/dev/null 2>&1
|
|
| 35 | + sed "s|@BASE_ID@|$(BASE_ID)|g" pkgA1.conf.in >'$(WORK)/pkgA1.conf'
|
|
| 36 | + '$(GHC_PKG)' --package-db '$(PKGDB)' register '$(WORK)/pkgA1.conf' >/dev/null
|
|
| 37 | + |
|
| 38 | + # Build and register pkgB against pkgA1 so B.hi records the unfolding of g = f1.
|
|
| 39 | + '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' \
|
|
| 40 | + -package pkgA1 -this-unit-id pkgB -O -c pkgB/B.hs \
|
|
| 41 | + -outputdir '$(PKGB)'
|
|
| 42 | + ar q '$(PKGB)/libHSpkgB.a' '$(PKGB)/B.o' >/dev/null 2>&1
|
|
| 43 | + sed "s|@BASE_ID@|$(BASE_ID)|g" pkgB.conf.in >'$(WORK)/pkgB.conf'
|
|
| 44 | + '$(GHC_PKG)' --package-db '$(PKGDB)' register '$(WORK)/pkgB.conf' >/dev/null
|
|
| 45 | + |
|
| 46 | + # Rebuild the same installed unit id from pkgA2, replacing f1 with f2.
|
|
| 47 | + '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' \
|
|
| 48 | + -this-unit-id pkgA -O -c pkgA2/A.hs -outputdir '$(PKGA2)'
|
|
| 49 | + ar q '$(PKGA2)/libHSpkgA.a' '$(PKGA2)/A.o' >/dev/null 2>&1
|
|
| 50 | + sed "s|@BASE_ID@|$(BASE_ID)|g" pkgA2.conf.in >'$(WORK)/pkgA2.conf'
|
|
| 51 | + '$(GHC_PKG)' --package-db '$(PKGDB)' update '$(WORK)/pkgA2.conf' >/dev/null
|
|
| 52 | + |
|
| 53 | + # Compiling Main against pkgB should now fail while loading the stale B.hi.
|
|
| 54 | + ! '$(TEST_HC)' $(TEST_HC_OPTS) -v0 --make app/Main.hs \
|
|
| 55 | + -O -fforce-recomp -package-db '$(PKGDB)' -package pkgB \
|
|
| 56 | + >'$(OUT)' 2>&1 || { echo "expected compilation failure" >&2; exit 1; }
|
|
| 57 | + |
|
| 58 | + # Strip the absolute test directory prefix before comparing against T2057.stderr.
|
|
| 59 | + sed "s#$(CURDIR)/##g" '$(OUT)' >&2 |
| 1 | +`T2057` checks that GHC stops after an interface-file error instead of
|
|
| 2 | +continuing into the linker.
|
|
| 3 | + |
|
| 4 | +The test constructs a stale package dependency on purpose. `pkgB` is compiled
|
|
| 5 | +against one version of package `A`, then the same unit id is replaced by an
|
|
| 6 | +incompatible build of `A`. When `Main` imports `B`, GHC has to read `B.hi`,
|
|
| 7 | +finds an unfolding that still mentions the old `A`, and should fail while
|
|
| 8 | +loading interfaces. |
| 1 | +work/pkgB/B.hi
|
|
| 2 | +Declaration for g
|
|
| 3 | +Unfolding of g:
|
|
| 4 | + f1 ErrorWithoutFlag
|
|
| 5 | + Can't find interface-file declaration for variable f1
|
|
| 6 | + Probable cause: bug in .hi-boot file, or inconsistent .hi file
|
|
| 7 | + Use -ddump-if-trace to get an idea of which file caused the error
|
|
| 8 | +<no location info>:
|
|
| 9 | + Cannot continue after interface file error |
| 1 | +test(
|
|
| 2 | + 'T2057',
|
|
| 3 | + [ extra_files(['pkgA1', 'pkgA2', 'pkgB', 'app', 'README.md', 'pkgA1.conf.in', 'pkgA2.conf.in', 'pkgB.conf.in'])
|
|
| 4 | + , when(opsys('mingw32'), skip)
|
|
| 5 | + , js_skip
|
|
| 6 | + , wasm_skip
|
|
| 7 | + , ignore_stdout
|
|
| 8 | + ],
|
|
| 9 | + makefile_test,
|
|
| 10 | + []
|
|
| 11 | +) |
| 1 | +module Main where
|
|
| 2 | + |
|
| 3 | +import B
|
|
| 4 | + |
|
| 5 | +main :: IO ()
|
|
| 6 | +main = print (g 41) |
| 1 | +name: pkgA1
|
|
| 2 | +version: 1.0
|
|
| 3 | +id: pkgA
|
|
| 4 | +key: pkgA
|
|
| 5 | +exposed: True
|
|
| 6 | +exposed-modules: A
|
|
| 7 | +import-dirs: ${pkgroot}/pkgA1
|
|
| 8 | +library-dirs: ${pkgroot}/pkgA1
|
|
| 9 | +dynamic-library-dirs: ${pkgroot}/pkgA1
|
|
| 10 | +hs-libraries: HSpkgA
|
|
| 11 | +depends: @BASE_ID@ |
| 1 | +module A (f1) where
|
|
| 2 | + |
|
| 3 | +{-# INLINE f1 #-}
|
|
| 4 | +f1 :: Int -> Int
|
|
| 5 | +f1 x = x + 1 |
| 1 | +name: pkgA1
|
|
| 2 | +version: 1.0
|
|
| 3 | +id: pkgA
|
|
| 4 | +key: pkgA
|
|
| 5 | +exposed: True
|
|
| 6 | +exposed-modules: A
|
|
| 7 | +import-dirs: ${pkgroot}/pkgA2
|
|
| 8 | +library-dirs: ${pkgroot}/pkgA2
|
|
| 9 | +dynamic-library-dirs: ${pkgroot}/pkgA2
|
|
| 10 | +hs-libraries: HSpkgA
|
|
| 11 | +depends: @BASE_ID@ |
| 1 | +module A (f2) where
|
|
| 2 | + |
|
| 3 | +f2 :: Int -> Int
|
|
| 4 | +f2 x = x + 100 |
| 1 | +name: pkgB
|
|
| 2 | +version: 1.0
|
|
| 3 | +id: pkgB
|
|
| 4 | +key: pkgB
|
|
| 5 | +exposed: True
|
|
| 6 | +exposed-modules: B
|
|
| 7 | +import-dirs: ${pkgroot}/pkgB
|
|
| 8 | +library-dirs: ${pkgroot}/pkgB
|
|
| 9 | +dynamic-library-dirs: ${pkgroot}/pkgB
|
|
| 10 | +hs-libraries: HSpkgB
|
|
| 11 | +depends: pkgA @BASE_ID@ |
| 1 | +module B (g) where
|
|
| 2 | + |
|
| 3 | +import A
|
|
| 4 | + |
|
| 5 | +{-# INLINE g #-}
|
|
| 6 | +g :: Int -> Int
|
|
| 7 | +g x = f1 x |