[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 5 commits: task: Substitute some datatypes for newtypes
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: beae879b by Rodrigo Mesquita at 2025-12-03T15:42:37+01:00 task: Substitute some datatypes for newtypes * Substitutes some data type declarations for newtype declarations * Adds comment to `LlvmConfigCache`, which must decidedly not be a newtype. Fixes #23555 - - - - - 1b88b0bc by mangoiv at 2025-12-03T18:15:08-05:00 Renamer: reinstate the template haskell level check in notFound Out-of-scope names might be caused by a staging error, as is explained by Note [Out of scope might be a staging error] in GHC.Tc.Utils.Env.hs. This logic was assumed to be dead code after 217caad1 and has thus been removed. This commit reintroduces it and thus fixes issue #26099. - - - - - 93a4d388 by Zubin Duggal at 2025-12-03T18:15:11-05:00 testlib: Optionally include the way name in the expected output file This allows us to have different outputs for different ways. - - - - - 4ed9a10a by Zubin Duggal at 2025-12-03T18:15:11-05:00 testsuite: Accept output of tests failing in ext-interp way due to differing compilation requirements Fixes #26552 - - - - - 420913f9 by Cheng Shao at 2025-12-03T18:15:12-05:00 devx: minor fixes for compile_flags.txt This patch includes minor fixes for compile_flags.txt to improve developer experience when using clangd as language server to hack on RTS C sources: - Ensure `-fPIC` is passed and `__PIC__` is defined, to be coherent with `-DDYNAMIC` and ensure the `__PIC__` guarded code paths are indexed - Add the missing `-DRtsWay` definition, otherwise a few source files like `RtsUtils.c` and `Trace.c` would produce clangd errors - - - - - 18 changed files: - compile_flags.txt - compiler/GHC/CmmToAsm/AArch64/RegInfo.hs - compiler/GHC/CmmToAsm/PPC/RegInfo.hs - compiler/GHC/Core/Map/Type.hs - compiler/GHC/Driver/LlvmConfigCache.hs - compiler/GHC/Driver/Pipeline/Phases.hs - compiler/GHC/Tc/Utils/Env.hs - testsuite/driver/testlib.py - + testsuite/tests/driver/T20696/T20696.stderr-ext-interp - testsuite/tests/driver/T20696/all.T - testsuite/tests/driver/fat-iface/all.T - + testsuite/tests/driver/fat-iface/fat012.stderr-ext-interp - + testsuite/tests/driver/fat-iface/fat015.stderr-ext-interp - + testsuite/tests/splice-imports/SI07.stderr-ext-interp - testsuite/tests/splice-imports/all.T - + testsuite/tests/th/T26099.hs - + testsuite/tests/th/T26099.stderr - testsuite/tests/th/all.T Changes: ===================================== compile_flags.txt ===================================== @@ -1,3 +1,6 @@ +-fPIC +-U__PIC__ +-D__PIC__ -Wimplicit -include rts/include/ghcversion.h @@ -27,3 +30,4 @@ rts/include/ghcversion.h -DDEBUG -DDYNAMIC -DPROFILING +-DRtsWay="rts_thr_debug_p_dyn" ===================================== compiler/GHC/CmmToAsm/AArch64/RegInfo.hs ===================================== @@ -8,7 +8,7 @@ import GHC.Cmm import GHC.Utils.Outputable -data JumpDest = DestBlockId BlockId +newtype JumpDest = DestBlockId BlockId -- Debug Instance instance Outputable JumpDest where ===================================== compiler/GHC/CmmToAsm/PPC/RegInfo.hs ===================================== @@ -27,7 +27,7 @@ import GHC.Cmm.CLabel import GHC.Types.Unique import GHC.Utils.Outputable (ppr, text, Outputable, (<>)) -data JumpDest = DestBlockId BlockId +newtype JumpDest = DestBlockId BlockId -- Debug Instance instance Outputable JumpDest where ===================================== compiler/GHC/Core/Map/Type.hs ===================================== @@ -554,7 +554,7 @@ instance Eq (DeBruijn a) => Eq (DeBruijn (Maybe a)) where -- We also need to do the same for multiplicity! Which, since multiplicities are -- encoded simply as a 'Type', amounts to have a Trie for a pair of types. Tries -- of pairs are composition. -data BndrMap a = BndrMap (TypeMapG (MaybeMap TypeMapG a)) +newtype BndrMap a = BndrMap (TypeMapG (MaybeMap TypeMapG a)) -- TODO(22292): derive instance Functor BndrMap where ===================================== compiler/GHC/Driver/LlvmConfigCache.hs ===================================== @@ -18,6 +18,8 @@ import System.IO.Unsafe -- Currently implemented with unsafe lazy IO. But it could be implemented with -- an IORef as the exposed interface is in IO. data LlvmConfigCache = LlvmConfigCache LlvmConfig +-- NB: It is crucial for this to be a datatype, not a newtype. +-- Allocations can increase across the board over 20% otherwise (see the discussion on !10708 and non-final pipelines) initLlvmConfigCache :: FilePath -> IO LlvmConfigCache initLlvmConfigCache top_dir = pure $ LlvmConfigCache (unsafePerformIO $ initLlvmConfig top_dir) ===================================== compiler/GHC/Driver/Pipeline/Phases.hs ===================================== @@ -52,4 +52,4 @@ data TPhase res where T_MergeForeign :: PipeEnv -> HscEnv -> FilePath -> [FilePath] -> TPhase FilePath -- | A wrapper around the interpretation function for phases. -data PhaseHook = PhaseHook (forall a . TPhase a -> IO a) +newtype PhaseHook = PhaseHook (forall a . TPhase a -> IO a) ===================================== compiler/GHC/Tc/Utils/Env.hs ===================================== @@ -8,6 +8,7 @@ -- in module Language.Haskell.Syntax.Extension {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MultiWayIf #-} module GHC.Tc.Utils.Env( TyThing(..), TcTyThing(..), TcId, @@ -1213,6 +1214,20 @@ pprBinders bndrs = pprWithCommas ppr bndrs notFound :: Name -> TcM TyThing notFound name = do { lcl_env <- getLclEnv + ; lvls <- getCurrentAndBindLevel name + ; if -- See Note [Out of scope might be a staging error] + | isUnboundName name -> failM -- If the name really isn't in scope + -- don't report it again (#11941) + -- the + -- the 'Nothing' case of 'getCurrentAndBindLevel' + -- currently means 'isUnboundName' but to avoid + -- introducing bugs after a refactoring of that + -- function, we check this completely independently + -- before scrutinizing lvls + | Just (_top_lvl_flag, bind_lvls, lvl@Splice {}) <- lvls + -> failWithTc (TcRnBadlyLevelled (LevelCheckSplice name Nothing) bind_lvls (thLevelIndex lvl) Nothing ErrorWithoutFlag) + | otherwise -> pure () + ; if isTermVarOrFieldNameSpace (nameNameSpace name) then -- This code path is only reachable with RequiredTypeArguments enabled @@ -1243,14 +1258,23 @@ wrongThingErr expected thing name = {- Note [Out of scope might be a staging error] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider - x = 3 - data T = MkT $(foo x) + type T = Int + foo = $(1 :: T) + +GHC currently leaves the user some liberty when it comes to using +types in a manner that is theoretically not well-staged. +E.g. if `T` here were to be a value, we would reject the program with +a staging error. Since it is a type though, we allow it for backwards +compatibility reasons. + +However, in this case, we're just in the process of renaming a splice +when trying to type check an expression involving a type, that hasn't +even been added to the (type checking) environment yet. That is, why +it is out of scope. -where 'foo' is imported from somewhere. +The reason why we cannot recognise this issue earlier is, that if we +are not actually type checking the splice, i.e. if we're only using the +name of the type (e.g. ''T), the program should be accepted. -This is really a staging error, because we can't run code involving 'x'. -But in fact the type checker processes types first, so 'x' won't even be -in the type envt when we look for it in $(foo x). So inside splices we -report something missing from the type env as a staging error. -See #5752 and #5795. +We stop and report a staging error. -} ===================================== testsuite/driver/testlib.py ===================================== @@ -1971,7 +1971,7 @@ async def do_compile(name: TestName, # of whether we expected the compilation to fail or not (successful # compilations may generate warnings). - expected_stderr_file = find_expected_file(name, 'stderr') + expected_stderr_file = find_expected_file(name, 'stderr', way) actual_stderr_file = add_suffix(name, 'comp.stderr') diff_file_name = in_testdir(add_suffix(name, 'comp.diff')) @@ -2012,7 +2012,7 @@ async def compile_cmp_asm(name: TestName, # of whether we expected the compilation to fail or not (successful # compilations may generate warnings). - expected_asm_file = find_expected_file(name, 'asm') + expected_asm_file = find_expected_file(name, 'asm', way) actual_asm_file = add_suffix(name, 's') if not await compare_outputs(way, 'asm', @@ -2036,7 +2036,7 @@ async def compile_grep_asm(name: TestName, if badResult(result): return result - expected_pat_file = find_expected_file(name, 'asm') + expected_pat_file = find_expected_file(name, 'asm', way) actual_asm_file = add_suffix(name, 's') if not grep_output(join_normalisers(normalise_errmsg), @@ -2058,7 +2058,7 @@ async def compile_grep_core(name: TestName, if badResult(result): return result - expected_pat_file = find_expected_file(name, 'substr-simpl') + expected_pat_file = find_expected_file(name, 'substr-simpl', way) actual_core_file = add_suffix(name, 'dump-simpl') if not grep_output(join_normalisers(normalise_errmsg), @@ -2097,7 +2097,7 @@ async def compile_and_run__(name: TestName, return result if compile_stderr: - expected_stderr_file = find_expected_file(name, 'ghc.stderr') + expected_stderr_file = find_expected_file(name, 'ghc.stderr', way) actual_stderr_file = add_suffix(name, 'comp.stderr') diff_file_name = in_testdir(add_suffix(name, 'comp.diff')) @@ -2556,7 +2556,7 @@ def get_compiler_flags() -> List[str]: async def stdout_ok(name: TestName, way: WayName) -> bool: actual_stdout_file = add_suffix(name, 'run.stdout') - expected_stdout_file = find_expected_file(name, 'stdout') + expected_stdout_file = find_expected_file(name, 'stdout', way) extra_norm = join_normalisers(normalise_output, getTestOpts().extra_normaliser) @@ -2583,7 +2583,7 @@ def dump_stdout( name: TestName ) -> None: async def stderr_ok(name: TestName, way: WayName) -> bool: actual_stderr_file = add_suffix(name, 'run.stderr') - expected_stderr_file = find_expected_file(name, 'stderr') + expected_stderr_file = find_expected_file(name, 'stderr', way) return await compare_outputs(way, 'stderr', join_normalisers(normalise_errmsg, getTestOpts().extra_errmsg_normaliser), \ @@ -2688,7 +2688,7 @@ async def check_hp_ok(name: TestName) -> bool: return False async def check_prof_ok(name: TestName, way: WayName) -> bool: - expected_prof_file = find_expected_file(name, 'prof.sample') + expected_prof_file = find_expected_file(name, 'prof.sample', way) expected_prof_path = in_testdir(expected_prof_file) # Check actual prof file only if we have an expected prof file to @@ -3368,18 +3368,19 @@ def in_statsdir(name: Union[Path, str], suffix: str='') -> Path: # Finding the sample output. The filename is of the form # -# <test>.stdout[-ws-<wordsize>][-<platform>|-<os>] +# <test>.stdout[-ws-<wordsize>][-<platform>|-<os>][-<way>] # -def find_expected_file(name: TestName, suff: str) -> Path: +def find_expected_file(name: TestName, suff: str, way: WayName) -> Path: basename = add_suffix(name, suff) # Override the basename if the user has specified one, this will then be # subjected to the same name mangling scheme as normal to allow platform # specific overrides to work. basename = getTestOpts().use_specs.get(suff, basename) - files = [str(basename) + ws + plat + files = [str(basename) + ws + plat + way_ext for plat in ['-' + config.platform, '-' + config.os, ''] - for ws in ['-ws-' + config.wordsize, '']] + for ws in ['-ws-' + config.wordsize, ''] + for way_ext in ['-' + way, '']] for f in files: if in_srcdir(f).exists(): ===================================== testsuite/tests/driver/T20696/T20696.stderr-ext-interp ===================================== @@ -0,0 +1,3 @@ +[1 of 3] Compiling C ( C.hs, C.o ) +[2 of 3] Compiling B ( B.hs, B.o ) +[3 of 3] Compiling A ( A.hs, A.o ) ===================================== testsuite/tests/driver/T20696/all.T ===================================== @@ -1,5 +1,4 @@ test('T20696', [extra_files(['A.hs', 'B.hs', 'C.hs']) - , expect_broken_for(26552, ['ext-interp']) , unless(ghc_dynamic(), skip)], multimod_compile, ['A', '']) test('T20696-static', [extra_files(['A.hs', 'B.hs', 'C.hs']) , when(ghc_dynamic(), skip)], multimod_compile, ['A', '']) ===================================== testsuite/tests/driver/fat-iface/all.T ===================================== @@ -9,12 +9,12 @@ test('fat010', [req_th,extra_files(['THA.hs', 'THB.hs', 'THC.hs']), copy_files], # Check linking works when using -fbyte-code-and-object-code test('fat011', [req_th, extra_files(['FatMain.hs', 'FatTH.hs', 'FatQuote.hs'])], multimod_compile, ['FatMain', '-fbyte-code-and-object-code -fprefer-byte-code']) # Check that we use interpreter rather than enable dynamic-too if needed for TH -test('fat012', [req_th, expect_broken_for(26552, ['ext-interp']), unless(ghc_dynamic(), skip), extra_files(['FatTH.hs', 'FatQuote.hs'])], multimod_compile, ['FatTH', '-fprefer-byte-code']) +test('fat012', [req_th, unless(ghc_dynamic(), skip), extra_files(['FatTH.hs', 'FatQuote.hs'])], multimod_compile, ['FatTH', '-fprefer-byte-code']) # Check that no objects are generated if using -fno-code and -fprefer-byte-code test('fat013', [req_th, req_bco, extra_files(['FatTH.hs', 'FatQuote.hs'])], multimod_compile, ['FatTH', '-fno-code -fprefer-byte-code']) # When using interpreter should not produce objects test('fat014', [req_th, extra_files(['FatTH.hs', 'FatQuote.hs']), extra_run_opts('-fno-code')], ghci_script, ['fat014.script']) -test('fat015', [req_th, expect_broken_for(26552, ['ext-interp']), unless(ghc_dynamic(), skip), extra_files(['FatQuote.hs', 'FatQuote1.hs', 'FatQuote2.hs', 'FatTH1.hs', 'FatTH2.hs', 'FatTHTop.hs'])], multimod_compile, ['FatTHTop', '-fno-code -fwrite-interface']) +test('fat015', [req_th, unless(ghc_dynamic(), skip), extra_files(['FatQuote.hs', 'FatQuote1.hs', 'FatQuote2.hs', 'FatTH1.hs', 'FatTH2.hs', 'FatTHTop.hs'])], multimod_compile, ['FatTHTop', '-fno-code -fwrite-interface']) test('T22807', [req_th, unless(ghc_dynamic(), skip), extra_files(['T22807A.hs', 'T22807B.hs'])] , makefile_test, ['T22807']) test('T22807_ghci', [req_th, unless(ghc_dynamic(), skip), extra_files(['T22807_ghci.hs'])] ===================================== testsuite/tests/driver/fat-iface/fat012.stderr-ext-interp ===================================== @@ -0,0 +1,2 @@ +[1 of 2] Compiling FatQuote ( FatQuote.hs, FatQuote.o ) +[2 of 2] Compiling FatTH ( FatTH.hs, FatTH.o ) ===================================== testsuite/tests/driver/fat-iface/fat015.stderr-ext-interp ===================================== @@ -0,0 +1,6 @@ +[1 of 6] Compiling FatQuote ( FatQuote.hs, FatQuote.o, interpreted ) +[2 of 6] Compiling FatQuote1 ( FatQuote1.hs, interpreted ) +[3 of 6] Compiling FatQuote2 ( FatQuote2.hs, FatQuote2.o ) +[4 of 6] Compiling FatTH1 ( FatTH1.hs, nothing ) +[5 of 6] Compiling FatTH2 ( FatTH2.hs, nothing ) +[6 of 6] Compiling FatTHTop ( FatTHTop.hs, nothing ) ===================================== testsuite/tests/splice-imports/SI07.stderr-ext-interp ===================================== @@ -0,0 +1,3 @@ +[1 of 3] Compiling SI05A ( SI05A.hs, SI05A.o ) +[2 of 3] Compiling SI07A ( SI07A.hs, nothing ) +[3 of 3] Compiling SI07 ( SI07.hs, nothing ) ===================================== testsuite/tests/splice-imports/all.T ===================================== @@ -9,7 +9,7 @@ test('SI03', [extra_files(["SI01A.hs"])], multimod_compile_fail, ['SI03', '-v0'] test('SI04', [extra_files(["SI01A.hs"])], multimod_compile, ['SI04', '-v0']) test('SI05', [extra_files(["SI01A.hs"])], multimod_compile_fail, ['SI05', '-v0']) test('SI06', [extra_files(["SI01A.hs"])], multimod_compile, ['SI06', '-v0']) -test('SI07', [expect_broken_for(26552, ['ext-interp']), unless(ghc_dynamic(), skip), extra_files(["SI05A.hs"])], multimod_compile, ['SI07', '-fwrite-interface -fno-code']) +test('SI07', [unless(ghc_dynamic(), skip), extra_files(["SI05A.hs"])], multimod_compile, ['SI07', '-fwrite-interface -fno-code']) # Instance tests test('SI08', [extra_files(["ClassA.hs", "InstanceA.hs"])], multimod_compile_fail, ['SI08', '-v0']) test('SI09', [extra_files(["ClassA.hs", "InstanceA.hs"])], multimod_compile, ['SI09', '-v0']) ===================================== testsuite/tests/th/T26099.hs ===================================== @@ -0,0 +1,6 @@ +{-# LANGUAGE TemplateHaskell #-} +module M where + +type T = Int + +a = $(3 :: T) ===================================== testsuite/tests/th/T26099.stderr ===================================== @@ -0,0 +1,6 @@ +T26099.hs:6:12: error: [GHC-28914] + • Level error: ‘T’ is bound at level 0 but used at level -1 + • In an expression type signature: T + In the expression: 3 :: T + In the untyped splice: $(3 :: T) + ===================================== testsuite/tests/th/all.T ===================================== @@ -642,3 +642,4 @@ test('QQInQuote', normal, compile, ['']) test('QQTopError', normal, compile_fail, ['-fdiagnostics-show-caret']) test('GadtConSigs_th_pprint1', normal, compile, ['']) test('GadtConSigs_th_dump1', normal, compile, ['-v0 -ddump-splices -dsuppress-uniques']) +test('T26099', normal, compile_fail, ['']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ceebca95e35051414945387f3677e28... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ceebca95e35051414945387f3677e28... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Marge Bot (@marge-bot)