Skip to content
  • Matthew Pickering's avatar
    217caad1
    Implement Explicit Level Imports for Template Haskell · 217caad1
    Matthew Pickering authored
    This commit introduces the `ExplicitLevelImports` and
    `ImplicitStagePersistence` language extensions as proposed in GHC
    Proposal #682.
    
    Key Features
    ------------
    
    - `ExplicitLevelImports` adds two new import modifiers - `splice` and
      `quote` - allowing precise control over the level at which imported
      identifiers are available
    - `ImplicitStagePersistence` (enabled by default) preserves existing
      path-based cross-stage persistence behavior
    - `NoImplicitStagePersistence` disables implicit cross-stage
      persistence, requiring explicit level imports
    
    Benefits
    --------
    
    - Improved compilation performance by reducing unnecessary code generation
    - Enhanced IDE experience with faster feedback in `-fno-code` mode
    - Better dependency tracking by distinguishing compile-time and runtime dependencies
    - Foundation for future cross-compilation improvements
    
    This implementation enables the separation of modules needed at
    compile-time from those needed at runtime, allowing for more efficient
    compilation pipelines and clearer code organization in projects using
    Template Haskell.
    
    Implementation Notes
    --------------------
    
    The level which a name is availble at is stored in the 'GRE', in the normal
    GlobalRdrEnv. The function `greLevels` returns the levels which a specific GRE
    is imported at. The level information for a 'Name' is computed by `getCurrentAndBindLevel`.
    The level validity is checked by `checkCrossLevelLifting`.
    
    Instances are checked by `checkWellLevelledDFun`, which computes the level an
    instance by calling `checkWellLevelledInstanceWhat`, which sees what is
    available at by looking at the module graph.
    
    Modifications to downsweep
    --------------------------
    
    Code generation is now only enabled for modules which are needed at
    compile time.
    See the Note [-fno-code mode] for more information.
    
    Uniform error messages for level errors
    ---------------------------------------
    
    All error messages to do with levels are now reported uniformly using
    the `TcRnBadlyStaged` constructor.
    
    Error messages are uniformly reported in terms of levels.
    
    0 - top-level
    1 - quote level
    -1 - splice level
    
    The only level hard-coded into the compiler is the top-level in
    GHC.Types.ThLevelIndex.topLevelIndex.
    
    Uniformly refer to levels and stages
    ------------------------------------
    
    There was much confusion about levels vs stages in the compiler.
    A level is a semantic concept, used by the typechecker to ensure a
    program can be evaluated in a well-staged manner.
    
    A stage is an operational construct, program evaluation proceeds in
    stages.
    
    Deprecate -Wbadly-staged-types
    ------------------------------
    
    `-Wbadly-staged-types` is deprecated in favour of `-Wbadly-levelled-types`.
    
    Lift derivation changed
    -----------------------
    
    Derived lift instances will now not generate code with expression
    quotations.
    
    Before:
    
    ```
    data A = A Int deriving Lift
    
    =>
    lift (A x) = [| A $(lift x) |]
    ```
    
    After:
    
    ```
    lift (A x) = conE 'A `appE` (lift x)
    ```
    
    This is because if you attempt to derive `Lift` in a module where
    `NoImplicitStagePersistence` is enabled, you would get an infinite loop
    where a constructor was attempted to be persisted using the instance you
    are currently defining.
    
    GHC API Changes
    ---------------
    
    The ModuleGraph now contains additional information about the type of
    the edges (normal, quote or splice) between modules. This is abstracted
    using the `ModuleGraphEdge` data type.
    
    Fixes #25828
    
    -------------------------
    Metric Increase:
        MultiLayerModulesTH_Make
    -------------------------
    217caad1
    Implement Explicit Level Imports for Template Haskell
    Matthew Pickering authored
    This commit introduces the `ExplicitLevelImports` and
    `ImplicitStagePersistence` language extensions as proposed in GHC
    Proposal #682.
    
    Key Features
    ------------
    
    - `ExplicitLevelImports` adds two new import modifiers - `splice` and
      `quote` - allowing precise control over the level at which imported
      identifiers are available
    - `ImplicitStagePersistence` (enabled by default) preserves existing
      path-based cross-stage persistence behavior
    - `NoImplicitStagePersistence` disables implicit cross-stage
      persistence, requiring explicit level imports
    
    Benefits
    --------
    
    - Improved compilation performance by reducing unnecessary code generation
    - Enhanced IDE experience with faster feedback in `-fno-code` mode
    - Better dependency tracking by distinguishing compile-time and runtime dependencies
    - Foundation for future cross-compilation improvements
    
    This implementation enables the separation of modules needed at
    compile-time from those needed at runtime, allowing for more efficient
    compilation pipelines and clearer code organization in projects using
    Template Haskell.
    
    Implementation Notes
    --------------------
    
    The level which a name is availble at is stored in the 'GRE', in the normal
    GlobalRdrEnv. The function `greLevels` returns the levels which a specific GRE
    is imported at. The level information for a 'Name' is computed by `getCurrentAndBindLevel`.
    The level validity is checked by `checkCrossLevelLifting`.
    
    Instances are checked by `checkWellLevelledDFun`, which computes the level an
    instance by calling `checkWellLevelledInstanceWhat`, which sees what is
    available at by looking at the module graph.
    
    Modifications to downsweep
    --------------------------
    
    Code generation is now only enabled for modules which are needed at
    compile time.
    See the Note [-fno-code mode] for more information.
    
    Uniform error messages for level errors
    ---------------------------------------
    
    All error messages to do with levels are now reported uniformly using
    the `TcRnBadlyStaged` constructor.
    
    Error messages are uniformly reported in terms of levels.
    
    0 - top-level
    1 - quote level
    -1 - splice level
    
    The only level hard-coded into the compiler is the top-level in
    GHC.Types.ThLevelIndex.topLevelIndex.
    
    Uniformly refer to levels and stages
    ------------------------------------
    
    There was much confusion about levels vs stages in the compiler.
    A level is a semantic concept, used by the typechecker to ensure a
    program can be evaluated in a well-staged manner.
    
    A stage is an operational construct, program evaluation proceeds in
    stages.
    
    Deprecate -Wbadly-staged-types
    ------------------------------
    
    `-Wbadly-staged-types` is deprecated in favour of `-Wbadly-levelled-types`.
    
    Lift derivation changed
    -----------------------
    
    Derived lift instances will now not generate code with expression
    quotations.
    
    Before:
    
    ```
    data A = A Int deriving Lift
    
    =>
    lift (A x) = [| A $(lift x) |]
    ```
    
    After:
    
    ```
    lift (A x) = conE 'A `appE` (lift x)
    ```
    
    This is because if you attempt to derive `Lift` in a module where
    `NoImplicitStagePersistence` is enabled, you would get an infinite loop
    where a constructor was attempted to be persisted using the instance you
    are currently defining.
    
    GHC API Changes
    ---------------
    
    The ModuleGraph now contains additional information about the type of
    the edges (normal, quote or splice) between modules. This is abstracted
    using the `ModuleGraphEdge` data type.
    
    Fixes #25828
    
    -------------------------
    Metric Increase:
        MultiLayerModulesTH_Make
    -------------------------
Loading