Simon Jakobi pushed to branch wip/sjakobi/T2057 at Glasgow Haskell Compiler / GHC

Commits:

11 changed files:

Changes:

  • testsuite/tests/driver/T2057/Makefile
    ... ... @@ -9,6 +9,7 @@ PKGA2 = $(WORK)/pkgA2
    9 9
     PKGB = $(WORK)/pkgB
    
    10 10
     APP = $(WORK)/app
    
    11 11
     OUT = $(WORK)/T2057.out
    
    12
    +BASE_ID := $(shell "$(GHC_PKG)" field base id --simple-output)
    
    12 13
     
    
    13 14
     .PHONY: T2057 clean
    
    14 15
     
    
    ... ... @@ -16,31 +17,31 @@ clean:
    16 17
     	rm -rf $(WORK)
    
    17 18
     
    
    18 19
     # Dependency graph:
    
    19
    -#   pkgB is built against pkgA1.
    
    20
    -#   We then rebuild the same installed unit id (pkgA1-1) from the pkgA2 sources,
    
    21
    -#   leaving pkgB with a stale unfolding that still references pkgA1's old API.
    
    22
    -#   Compiling Main against pkgB should therefore stop at the interface error.
    
    20
    +#   pkgB is built against pkgA1, where A exports f1.
    
    21
    +#   We then rebuild the same installed unit id (pkgA-1) from the pkgA2 sources,
    
    22
    +#   where A instead exports f2.
    
    23
    +#   Reading B.hi therefore finds an unfolding for g that still refers to f1,
    
    24
    +#   and compiling Main against pkgB should stop at the interface error.
    
    23 25
     T2057: clean
    
    24
    -	@set -eu; \
    
    25
    -	BASE_ID=`'$(GHC_PKG)' field base id --simple-output`; \
    
    26
    -	mkdir -p '$(PKGA1)' '$(PKGA2)' '$(PKGB)' '$(APP)'; \
    
    27
    -	'$(GHC_PKG)' init '$(PKGDB)'; \
    
    28
    -	'$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' -this-unit-id pkgA1-1 -O -c pkgA1/A.hs -outputdir '$(PKGA1)'; \
    
    29
    -	ar q '$(PKGA1)/libHSpkgA1-1.a' '$(PKGA1)/A.o' >/dev/null 2>&1; \
    
    30
    -	sed "s|@BASE_ID@|$$BASE_ID|g" pkgA1.conf.in >'$(WORK)/pkgA1.conf'; \
    
    31
    -	'$(GHC_PKG)' --package-db '$(PKGDB)' register '$(WORK)/pkgA1.conf' >/dev/null; \
    
    32
    -	'$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' -package pkgA1 -this-unit-id pkgB-1 -O -c pkgB/B.hs -outputdir '$(PKGB)'; \
    
    33
    -	ar q '$(PKGB)/libHSpkgB-1.a' '$(PKGB)/B.o' >/dev/null 2>&1; \
    
    34
    -	sed "s|@BASE_ID@|$$BASE_ID|g" pkgB.conf.in >'$(WORK)/pkgB.conf'; \
    
    35
    -	'$(GHC_PKG)' --package-db '$(PKGDB)' register '$(WORK)/pkgB.conf' >/dev/null; \
    
    36
    -	'$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' -this-unit-id pkgA1-1 -O -c pkgA2/A.hs -outputdir '$(PKGA2)'; \
    
    37
    -	ar q '$(PKGA2)/libHSpkgA1-1.a' '$(PKGA2)/A.o' >/dev/null 2>&1; \
    
    38
    -	sed "s|@BASE_ID@|$$BASE_ID|g" pkgA2.conf.in >'$(WORK)/pkgA2.conf'; \
    
    39
    -	'$(GHC_PKG)' --package-db '$(PKGDB)' update '$(WORK)/pkgA2.conf' >/dev/null; \
    
    40
    -	status=0; \
    
    41
    -	'$(TEST_HC)' $(TEST_HC_OPTS) -v0 --make app/Main.hs -O -fforce-recomp -package-db '$(PKGDB)' -package pkgB >'$(OUT)' 2>&1 || status=$$?; \
    
    42
    -	if [ $$status -eq 0 ]; then \
    
    43
    -	  echo "expected compilation failure" >&2; \
    
    44
    -	  exit 1; \
    
    45
    -	fi; \
    
    46
    -	sed "s#`pwd`/##g" '$(OUT)' >&2
    26
    +	# Create an isolated package DB and output directories for the repro.
    
    27
    +	mkdir -p '$(PKGA1)' '$(PKGA2)' '$(PKGB)' '$(APP)'
    
    28
    +	'$(GHC_PKG)' init '$(PKGDB)'
    
    29
    +	# Build and register pkgA1, the original version of A.
    
    30
    +	'$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' -this-unit-id pkgA-1 -O -c pkgA1/A.hs -outputdir '$(PKGA1)'
    
    31
    +	ar q '$(PKGA1)/libHSpkgA-1.a' '$(PKGA1)/A.o' >/dev/null 2>&1
    
    32
    +	sed "s|@BASE_ID@|$(BASE_ID)|g" pkgA1.conf.in >'$(WORK)/pkgA1.conf'
    
    33
    +	'$(GHC_PKG)' --package-db '$(PKGDB)' register '$(WORK)/pkgA1.conf' >/dev/null
    
    34
    +	# Build and register pkgB against pkgA1 so B.hi records the unfolding of g = f1.
    
    35
    +	'$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' -package pkgA1 -this-unit-id pkgB-1 -O -c pkgB/B.hs -outputdir '$(PKGB)'
    
    36
    +	ar q '$(PKGB)/libHSpkgB-1.a' '$(PKGB)/B.o' >/dev/null 2>&1
    
    37
    +	sed "s|@BASE_ID@|$(BASE_ID)|g" pkgB.conf.in >'$(WORK)/pkgB.conf'
    
    38
    +	'$(GHC_PKG)' --package-db '$(PKGDB)' register '$(WORK)/pkgB.conf' >/dev/null
    
    39
    +	# Rebuild the same installed unit id from pkgA2, replacing f1 with f2.
    
    40
    +	'$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' -this-unit-id pkgA-1 -O -c pkgA2/A.hs -outputdir '$(PKGA2)'
    
    41
    +	ar q '$(PKGA2)/libHSpkgA-1.a' '$(PKGA2)/A.o' >/dev/null 2>&1
    
    42
    +	sed "s|@BASE_ID@|$(BASE_ID)|g" pkgA2.conf.in >'$(WORK)/pkgA2.conf'
    
    43
    +	'$(GHC_PKG)' --package-db '$(PKGDB)' update '$(WORK)/pkgA2.conf' >/dev/null
    
    44
    +	# Compiling Main against pkgB should now fail while loading the stale B.hi.
    
    45
    +	! '$(TEST_HC)' $(TEST_HC_OPTS) -v0 --make app/Main.hs -O -fforce-recomp -package-db '$(PKGDB)' -package pkgB >'$(OUT)' 2>&1 || { echo "expected compilation failure" >&2; exit 1; }
    
    46
    +	# Strip the absolute test directory prefix before comparing against T2057.stderr.
    
    47
    +	sed "s#$(CURDIR)/##g" '$(OUT)' >&2

  • testsuite/tests/driver/T2057/README.md
    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.
    
    9
    +
    
    10
    +The golden [`T2057.stderr`](T2057.stderr) captures the expected behaviour on a
    
    11
    +fixed compiler: report the missing declaration from the stale interface and
    
    12
    +then abort with `Cannot continue after interface file error`. Any linker output
    
    13
    +would be a regression.

  • testsuite/tests/driver/T2057/T2057.stderr
    1 1
     work/pkgB/B.hi
    
    2
    -Declaration for saved
    
    3
    -Unfolding of saved:
    
    4
    -  staleDependencyBinding ErrorWithoutFlag
    
    5
    -                           Can't find interface-file declaration for variable staleDependencyBinding
    
    2
    +Declaration for g
    
    3
    +Unfolding of g:
    
    4
    +  f1 ErrorWithoutFlag
    
    5
    +                           Can't find interface-file declaration for variable f1
    
    6 6
                                  Probable cause: bug in .hi-boot file, or inconsistent .hi file
    
    7 7
                                  Use -ddump-if-trace to get an idea of which file caused the error
    
    8 8
     <no location info>:
    

  • testsuite/tests/driver/T2057/all.T
    1 1
     test(
    
    2 2
       'T2057',
    
    3
    -  [ extra_files(['pkgA1', 'pkgA2', 'pkgB', 'app', 'pkgA1.conf.in', 'pkgA2.conf.in', 'pkgB.conf.in'])
    
    3
    +  [ extra_files(['pkgA1', 'pkgA2', 'pkgB', 'app', 'README.md', 'pkgA1.conf.in', 'pkgA2.conf.in', 'pkgB.conf.in'])
    
    4 4
       , when(opsys('mingw32'), skip)
    
    5 5
       , js_skip
    
    6 6
       , wasm_skip
    

  • testsuite/tests/driver/T2057/app/Main.hs
    ... ... @@ -3,4 +3,4 @@ module Main where
    3 3
     import B
    
    4 4
     
    
    5 5
     main :: IO ()
    
    6
    -main = print (saved 41)
    6
    +main = print (g 41)

  • testsuite/tests/driver/T2057/pkgA1.conf.in
    1 1
     name: pkgA1
    
    2 2
     version: 1.0
    
    3
    -id: pkgA1-1
    
    4
    -key: pkgA1-1
    
    3
    +id: pkgA-1
    
    4
    +key: pkgA-1
    
    5 5
     exposed: True
    
    6 6
     exposed-modules: A
    
    7 7
     import-dirs: ${pkgroot}/pkgA1
    
    8 8
     library-dirs: ${pkgroot}/pkgA1
    
    9 9
     dynamic-library-dirs: ${pkgroot}/pkgA1
    
    10
    -hs-libraries: HSpkgA1-1
    
    10
    +hs-libraries: HSpkgA-1
    
    11 11
     depends: @BASE_ID@

  • testsuite/tests/driver/T2057/pkgA1/A.hs
    1
    -module A (staleDependencyBinding) where
    
    1
    +module A (f1) where
    
    2 2
     
    
    3
    -{-# INLINE staleDependencyBinding #-}
    
    4
    -staleDependencyBinding :: Int -> Int
    
    5
    -staleDependencyBinding x = x + 1
    3
    +{-# INLINE f1 #-}
    
    4
    +f1 :: Int -> Int
    
    5
    +f1 x = x + 1

  • testsuite/tests/driver/T2057/pkgA2.conf.in
    1 1
     name: pkgA1
    
    2 2
     version: 1.0
    
    3
    -id: pkgA1-1
    
    4
    -key: pkgA1-1
    
    3
    +id: pkgA-1
    
    4
    +key: pkgA-1
    
    5 5
     exposed: True
    
    6 6
     exposed-modules: A
    
    7 7
     import-dirs: ${pkgroot}/pkgA2
    
    8 8
     library-dirs: ${pkgroot}/pkgA2
    
    9 9
     dynamic-library-dirs: ${pkgroot}/pkgA2
    
    10
    -hs-libraries: HSpkgA1-1
    
    10
    +hs-libraries: HSpkgA-1
    
    11 11
     depends: @BASE_ID@

  • testsuite/tests/driver/T2057/pkgA2/A.hs
    1
    -module A (replacementBinding) where
    
    1
    +module A (f2) where
    
    2 2
     
    
    3
    -replacementBinding :: Int -> Int
    
    4
    -replacementBinding x = x + 100
    3
    +f2 :: Int -> Int
    
    4
    +f2 x = x + 100

  • testsuite/tests/driver/T2057/pkgB.conf.in
    ... ... @@ -8,4 +8,4 @@ import-dirs: ${pkgroot}/pkgB
    8 8
     library-dirs: ${pkgroot}/pkgB
    
    9 9
     dynamic-library-dirs: ${pkgroot}/pkgB
    
    10 10
     hs-libraries: HSpkgB-1
    
    11
    -depends: pkgA1-1 @BASE_ID@
    11
    +depends: pkgA-1 @BASE_ID@

  • testsuite/tests/driver/T2057/pkgB/B.hs
    1
    -module B (saved) where
    
    1
    +module B (g) where
    
    2 2
     
    
    3 3
     import A
    
    4 4
     
    
    5
    -{-# INLINE saved #-}
    
    6
    -saved :: Int -> Int
    
    7
    -saved x = staleDependencyBinding x
    5
    +{-# INLINE g #-}
    
    6
    +g :: Int -> Int
    
    7
    +g x = f1 x