-
-tcInterfaceSigs unf_env (SigD (IfaceSig name ty id_infos src_loc) : rest)
- = tcAddSrcLoc src_loc (
- tcAddErrCtxt (ifaceSigCtxt name) (
- tcHsType ty `thenTc` \ sigma_ty ->
- tcIdInfo unf_env name sigma_ty noIdInfo id_infos `thenTc` \ id_info ->
- returnTc (mkImportedId name sigma_ty id_info)
- )) `thenTc` \ sig_id ->
- tcInterfaceSigs unf_env rest `thenTc` \ sig_ids ->
- returnTc (sig_id : sig_ids)
-
-tcInterfaceSigs unf_env (other_decl : rest) = tcInterfaceSigs unf_env rest
-
-tcInterfaceSigs unf_env [] = returnTc []
+tcInterfaceSigs decls = fixM (tc_interface_sigs decls)
+ -- We tie a knot so that the Ids read out of interfaces are in scope
+ -- when we read their pragmas.
+ -- What we rely on is that pragmas are typechecked lazily; if
+ -- any type errors are found (ie there's an inconsistency)
+ -- we silently discard the pragma
+ --
+ -- We used to have a much bigger loop (in TcRnDriver), so that the
+ -- interface pragmas could mention variables bound in this module
+ -- (by mutual recn), but
+ -- (a) the knot is tiresomely big, and
+ -- (b) it black-holes when we have Template Haskell
+ --
+ -- For (b) consider: f = $(...h....)
+ -- where h is imported, and calls f via an hi-boot file.
+ -- This is bad! But it is not seen as a staging error, because h
+ -- is indeed imported. We don't want the type-checker to black-hole
+ -- when simplifying and compiling the splice!
+ --
+ -- Simple solution: discard any unfolding that mentions a variable
+ -- bound in this module (and hence not yet processed).
+ -- The discarding happens when forkM finds a type error.
+
+tc_interface_sigs decls unf_env
+ = sequenceM [do_one d | d@(IfaceSig {}) <- decls] `thenM` \ sig_ids ->
+ tcExtendGlobalValEnv sig_ids getGblEnv
+ -- Return the extended environment
+ where
+ in_scope_vars = typeEnvIds (tcg_type_env unf_env)
+ -- When we have hi-boot files, an unfolding might refer to
+ -- something defined in this module, so we must build a
+ -- suitable in-scope set. This thunk will only be poked
+ -- if -dcore-lint is on.
+
+ do_one IfaceSig {tcdName = name, tcdType = ty,
+ tcdIdInfo = id_infos, tcdLoc = src_loc}
+ = addSrcLoc src_loc $
+ addErrCtxt (ifaceSigCtxt name) $
+ tcIfaceType ty `thenM` \ sigma_ty ->
+ tcIdInfo unf_env in_scope_vars name
+ sigma_ty id_infos `thenM` \ id_info ->
+ returnM (mkVanillaGlobal name sigma_ty id_info)