obsidiansystems / obelisk

Functional reactive web and mobile applications, with batteries included.
https://reflex-frp.org
BSD 3-Clause "New" or "Revised" License
956 stars 105 forks source link

Invalid `default-extensions` break `ob run` in very confusing way #483

Open alexfmpe opened 5 years ago

alexfmpe commented 5 years ago

Adding a non-existent extension (e.g. typo) to default-extensions makes it so that only module extensions are active. For instance, starting with the obelisk skeleton

    , mtl
    , text
  default-extensions:
+   GeneralisedNewtypeDeriving
    TypeFamilies
    PolyKinds
   exposed-modules:

causes ob run to error with

common/src/Common/Route.hs:49:1: error:
    • Illegal family instance for ‘Data.Constraint.Extras.ConstraintsFor’
        (Use TypeFamilies to allow indexed type families)
    • In the type instance declaration for ‘Data.Constraint.Extras.ConstraintsFor’
      In the instance declaration for
        ‘Data.Constraint.Extras.ArgDict c_aaX5 FrontendRoute’
   |
49 | concat <$> mapM deriveRouteComponent
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
common/src/Common/Route.hs:49:1: error:
    • Illegal family instance for ‘Data.Constraint.Extras.ConstraintsFor’
        (Use TypeFamilies to allow indexed type families)
    • In the type instance declaration for ‘Data.Constraint.Extras.ConstraintsFor’
      In the instance declaration for
        ‘Data.Constraint.Extras.ArgDict c_aaX3 BackendRoute’
   |
49 | concat <$> mapM deriveRouteComponent
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...

The error only becomes apparent when nix-build -A ghc.common fails with

Setup: The package common-0.1 requires the following language extensions which
are not supported by ghc-8.4.3: GeneralisedNewtypeDeriving

because the British spelling is only available on 8.6.

matthewbauer commented 4 years ago

Is ob run perhaps just not showing the Setup errors here? I would expect it actually hits them just as any cabal command would.

alexfmpe commented 4 years ago

Seems like this now leads to an infinite reload cycle

    , mtl
    , text
+ default-extensions:
+  x
  exposed-modules:
(...)

Reloading...
  /run/user/1000/ghc24799_0/ghc_35.hspp

/run/user/1000/ghc24799_0/ghc_40.hspp:1:14: error:
    Cannot parse LANGUAGE pragma
    Expecting comma-separated list of language options,
    each starting with a capital letter
      E.g. {-# LANGUAGE TemplateHaskell, GADTs #-}
  |
1 | {-# LANGUAGE x #-}
  |              ^

Reloading...
  /run/user/1000/ghc24799_0/ghc_40.hspp

/run/user/1000/ghc24799_0/ghc_45.hspp:1:14: error:
    Cannot parse LANGUAGE pragma
    Expecting comma-separated list of language options,
    each starting with a capital letter
      E.g. {-# LANGUAGE TemplateHaskell, GADTs #-}
  |
1 | {-# LANGUAGE x #-}
  |              ^

Reloading...
  /run/user/1000/ghc24799_0/ghc_45.hspp

(...)
ohri-anurag commented 2 years ago

@alexfmpe Any idea how we can fix this issue? I can reproduce the issue as per your comment above, the infinite reload cycle still exists...

alexfmpe commented 2 years ago

We inject cabal extensions in their package modules so that multiple packages can exist in ob run even though ghci itself doesn't distinguish packages and would just mash all extensions together.

It looks like we also do this with unknown extensions https://github.com/obsidiansystems/obelisk/blob/master/lib/command/src/Obelisk/Command/Preprocessor.hs#L81 which is why the LANGUAGE x ends up in source.

I don't see why that would trigger an infinite cycle though. Looking at the weird .hspp filenames I wonder if there's some sanity checking happening after the preprocessor runs but before it's combined with normal source

alexfmpe commented 2 years ago

I'm also not sure if we should let unknown extensions through. Even without the inifinite cycle it seems like a typo there would lead to a confusing error message