mirrored from https://gitlab.haskell.org/ghc/ghc.git
/
Module.hs
3156 lines (2730 loc) · 133 KB
/
Module.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
{-# LANGUAGE CPP #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NondecreasingIndentation #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiWayIf #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
{-
(c) The University of Glasgow 2006
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-}
-- | Typechecking a whole module
--
-- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/type-checker
module GHC.Tc.Module (
tcRnStmt, tcRnExpr, TcRnExprMode(..), tcRnType,
tcRnImportDecls,
tcRnLookupRdrName,
getModuleInterface,
tcRnDeclsi,
isGHCiMonad,
runTcInteractive, -- Used by GHC API clients (#8878)
tcRnLookupName,
tcRnGetInfo,
tcRnModule, tcRnModuleTcRnM,
tcTopSrcDecls,
rnTopSrcDecls,
checkBootDecl, checkHiBootIface',
findExtraSigImports,
implicitRequirements,
checkUnit,
mergeSignatures,
tcRnMergeSignatures,
instantiateSignature,
tcRnInstantiateSignature,
loadUnqualIfaces,
-- More private...
badReexportedBootThing,
checkBootDeclM,
missingBootThing,
getRenamedStuff, RenamedStuff
) where
import GHC.Prelude
import GHC.Driver.Env
import GHC.Driver.Plugins
import GHC.Driver.Session
import GHC.Tc.Errors.Hole.FitTypes ( HoleFitPluginR (..) )
import GHC.Tc.Errors.Types
import {-# SOURCE #-} GHC.Tc.Gen.Splice ( finishTH, runRemoteModFinalizers )
import GHC.Tc.Gen.HsType
import GHC.Tc.Validity( checkValidType )
import GHC.Tc.Gen.Match
import GHC.Tc.Utils.Unify( checkConstraints, tcSubTypeSigma )
import GHC.Tc.Utils.Zonk
import GHC.Tc.Gen.Expr
import GHC.Tc.Gen.App( tcInferSigma )
import GHC.Tc.Utils.Monad
import GHC.Tc.Gen.Export
import GHC.Tc.Types.Evidence
import GHC.Tc.Types.Constraint
import GHC.Tc.Types.Origin
import GHC.Tc.Instance.Family
import GHC.Tc.Gen.Annotation
import GHC.Tc.Gen.Bind
import GHC.Tc.Gen.Default
import GHC.Tc.Utils.Env
import GHC.Tc.Gen.Rule
import GHC.Tc.Gen.Foreign
import GHC.Tc.TyCl.Class ( ClassScopedTVEnv )
import GHC.Tc.TyCl.Instance
import GHC.Tc.Utils.TcMType
import GHC.Tc.Utils.TcType
import GHC.Tc.Utils.Instantiate (tcGetInsts)
import GHC.Tc.Solver
import GHC.Tc.TyCl
import GHC.Tc.Instance.Typeable ( mkTypeableBinds )
import GHC.Tc.Utils.Backpack
import GHC.Rename.Splice ( rnTopSpliceDecls, traceSplice, SpliceInfo(..) )
import GHC.Rename.HsType
import GHC.Rename.Expr
import GHC.Rename.Utils ( HsDocContext(..) )
import GHC.Rename.Fixity ( lookupFixityRn )
import GHC.Rename.Names
import GHC.Rename.Env
import GHC.Rename.Module
import GHC.Iface.Syntax ( ShowSub(..), showToHeader )
import GHC.Iface.Type ( ShowForAllFlag(..) )
import GHC.Iface.Env ( externaliseName )
import GHC.Iface.Make ( coAxiomToIfaceDecl )
import GHC.Iface.Load
import GHC.Builtin.Types ( unitTy, mkListTy )
import GHC.Builtin.Names
import GHC.Builtin.Utils
import GHC.Hs
import GHC.Hs.Dump
import GHC.Core.PatSyn ( pprPatSynType )
import GHC.Core.Predicate ( classMethodTy )
import GHC.Core.FVs ( orphNamesOfFamInst )
import GHC.Core.InstEnv
import GHC.Core.TyCon
import GHC.Core.ConLike
import GHC.Core.DataCon
import GHC.Core.Type
import GHC.Core.Class
import GHC.Core.Coercion.Axiom
import GHC.Core.Unify( RoughMatchTc(..) )
import GHC.Core.FamInstEnv
( FamInst, pprFamInst, famInstsRepTyCons
, famInstEnvElts, extendFamInstEnvList, normaliseType )
import GHC.Parser.Header ( mkPrelImports )
import GHC.IfaceToCore
import GHC.Runtime.Context
import GHC.Utils.Error
import GHC.Utils.Outputable as Outputable
import GHC.Utils.Panic
import GHC.Utils.Panic.Plain
import GHC.Utils.Misc
import GHC.Utils.Logger
import GHC.Types.Error
import GHC.Types.Name.Reader
import GHC.Types.Fixity.Env
import GHC.Types.Id as Id
import GHC.Types.Id.Info( IdDetails(..) )
import GHC.Types.Var.Env
import GHC.Types.TypeEnv
import GHC.Types.Unique.FM
import GHC.Types.Name
import GHC.Types.Name.Env
import GHC.Types.Name.Set
import GHC.Types.Avail
import GHC.Types.Basic hiding( SuccessFlag(..) )
import GHC.Types.Annotations
import GHC.Types.SrcLoc
import GHC.Types.SourceText
import GHC.Types.SourceFile
import GHC.Types.TyThing.Ppr ( pprTyThingInContext )
import qualified GHC.LanguageExtensions as LangExt
import GHC.Unit.External
import GHC.Unit.Types
import GHC.Unit.State
import GHC.Unit.Home
import GHC.Unit.Module
import GHC.Unit.Module.Warnings
import GHC.Unit.Module.ModSummary
import GHC.Unit.Module.ModIface
import GHC.Unit.Module.ModDetails
import GHC.Unit.Module.Deps
import GHC.Data.FastString
import GHC.Data.Maybe
import GHC.Data.List.SetOps
import GHC.Data.Bag
import qualified GHC.Data.BooleanFormula as BF
import Data.List ( sortBy, sort )
import Data.Ord
import Data.Data ( Data )
import qualified Data.Set as S
import Control.DeepSeq
import Control.Monad
{-
************************************************************************
* *
Typecheck and rename a module
* *
************************************************************************
-}
-- | Top level entry point for typechecker and renamer
tcRnModule :: HscEnv
-> ModSummary
-> Bool -- True <=> save renamed syntax
-> HsParsedModule
-> IO (Messages TcRnMessage, Maybe TcGblEnv)
tcRnModule hsc_env mod_sum save_rn_syntax
parsedModule@HsParsedModule {hpm_module= L loc this_module}
| RealSrcSpan real_loc _ <- loc
= withTiming logger dflags
(text "Renamer/typechecker"<+>brackets (ppr this_mod))
(const ()) $
initTc hsc_env hsc_src save_rn_syntax this_mod real_loc $
withTcPlugins hsc_env $ withHoleFitPlugins hsc_env $
tcRnModuleTcRnM hsc_env mod_sum parsedModule pair
| otherwise
= return (err_msg `addMessage` emptyMessages, Nothing)
where
hsc_src = ms_hsc_src mod_sum
dflags = hsc_dflags hsc_env
logger = hsc_logger hsc_env
home_unit = hsc_home_unit hsc_env
err_msg = mkPlainErrorMsgEnvelope loc $
TcRnUnknownMessage $ mkPlainError noHints $
text "Module does not have a RealSrcSpan:" <+> ppr this_mod
pair :: (Module, SrcSpan)
pair@(this_mod,_)
| Just (L mod_loc mod) <- hsmodName this_module
= (mkHomeModule home_unit mod, mod_loc)
| otherwise -- 'module M where' is omitted
= (mkHomeModule home_unit mAIN_NAME, srcLocSpan (srcSpanStart loc))
tcRnModuleTcRnM :: HscEnv
-> ModSummary
-> HsParsedModule
-> (Module, SrcSpan)
-> TcRn TcGblEnv
-- Factored out separately from tcRnModule so that a Core plugin can
-- call the type checker directly
tcRnModuleTcRnM hsc_env mod_sum
(HsParsedModule {
hpm_module =
(L loc (HsModule _ _ maybe_mod export_ies
import_decls local_decls mod_deprec
maybe_doc_hdr)),
hpm_src_files = src_files
})
(this_mod, prel_imp_loc)
= setSrcSpan loc $
do { let { explicit_mod_hdr = isJust maybe_mod
; hsc_src = ms_hsc_src mod_sum }
; -- Load the hi-boot interface for this module, if any
-- We do this now so that the boot_names can be passed
-- to tcTyAndClassDecls, because the boot_names are
-- automatically considered to be loop breakers
tcg_env <- getGblEnv
; boot_info <- tcHiBootIface hsc_src this_mod
; setGblEnv (tcg_env { tcg_self_boot = boot_info })
$ do
{ -- Deal with imports; first add implicit prelude
implicit_prelude <- xoptM LangExt.ImplicitPrelude
; let { prel_imports = mkPrelImports (moduleName this_mod) prel_imp_loc
implicit_prelude import_decls }
; when (notNull prel_imports) $
addDiagnostic (WarningWithFlag Opt_WarnImplicitPrelude) (implicitPreludeWarn)
; -- TODO This is a little skeevy; maybe handle a bit more directly
let { simplifyImport (L _ idecl) =
( fmap sl_fs (ideclPkgQual idecl) , ideclName idecl)
}
; raw_sig_imports <- liftIO
$ findExtraSigImports hsc_env hsc_src
(moduleName this_mod)
; raw_req_imports <- liftIO
$ implicitRequirements hsc_env
(map simplifyImport (prel_imports
++ import_decls))
; let { mkImport (Nothing, L _ mod_name) = noLocA
$ (simpleImportDecl mod_name)
{ ideclHiding = Just (False, noLocA [])}
; mkImport _ = panic "mkImport" }
; let { all_imports = prel_imports ++ import_decls
++ map mkImport (raw_sig_imports ++ raw_req_imports) }
; -- OK now finally rename the imports
tcg_env <- {-# SCC "tcRnImports" #-}
tcRnImports hsc_env all_imports
; -- Don't need to rename the Haddock documentation,
-- it's not parsed by GHC anymore.
-- Make sure to do this before 'tcRnSrcDecls', because we need the
-- module header when we're splicing TH, since it can be accessed via
-- 'getDoc'.
tcg_env <- return (tcg_env
{ tcg_doc_hdr = maybe_doc_hdr })
; -- If the whole module is warned about or deprecated
-- (via mod_deprec) record that in tcg_warns. If we do thereby add
-- a WarnAll, it will override any subsequent deprecations added to tcg_warns
let { tcg_env1 = case mod_deprec of
Just (L _ txt) ->
tcg_env {tcg_warns = WarnAll txt}
Nothing -> tcg_env
}
; setGblEnv tcg_env1
$ do { -- Rename and type check the declarations
traceRn "rn1a" empty
; tcg_env <- if isHsBootOrSig hsc_src
then do {
; tcg_env <- tcRnHsBootDecls hsc_src local_decls
; traceRn "rn4a: before exports" empty
; tcg_env <- setGblEnv tcg_env $
rnExports explicit_mod_hdr export_ies
; traceRn "rn4b: after exports" empty
; return tcg_env
}
else {-# SCC "tcRnSrcDecls" #-}
tcRnSrcDecls explicit_mod_hdr export_ies local_decls
; whenM (goptM Opt_DoCoreLinting) $
lintGblEnv (hsc_logger hsc_env) (hsc_dflags hsc_env) tcg_env
; setGblEnv tcg_env
$ do { -- Compare hi-boot iface (if any) with the real thing
-- Must be done after processing the exports
tcg_env <- checkHiBootIface tcg_env boot_info
; -- The new type env is already available to stuff
-- slurped from interface files, via
-- GHC.Tc.Utils.Env.setGlobalTypeEnv. It's important that this
-- includes the stuff in checkHiBootIface,
-- because the latter might add new bindings for
-- boot_dfuns, which may be mentioned in imported
-- unfoldings.
-- Report unused names
-- Do this /after/ typeinference, so that when reporting
-- a function with no type signature we can give the
-- inferred type
reportUnusedNames tcg_env hsc_src
; -- add extra source files to tcg_dependent_files
addDependentFiles src_files
-- Ensure plugins run with the same tcg_env that we pass in
; setGblEnv tcg_env
$ do { tcg_env <- runTypecheckerPlugin mod_sum tcg_env
; -- Dump output and return
tcDump tcg_env
; return tcg_env
}
}
}
}
}
implicitPreludeWarn :: SDoc
implicitPreludeWarn
= text "Module `Prelude' implicitly imported"
{-
************************************************************************
* *
Import declarations
* *
************************************************************************
-}
tcRnImports :: HscEnv -> [LImportDecl GhcPs] -> TcM TcGblEnv
tcRnImports hsc_env import_decls
= do { (rn_imports, rdr_env, imports, hpc_info) <- rnImports import_decls ;
; this_mod <- getModule
; let { dep_mods :: ModuleNameEnv ModuleNameWithIsBoot
; dep_mods = imp_direct_dep_mods imports
-- We want instance declarations from all home-package
-- modules below this one, including boot modules, except
-- ourselves. The 'except ourselves' is so that we don't
-- get the instances from this module's hs-boot file. This
-- filtering also ensures that we don't see instances from
-- modules batch (@--make@) compiled before this one, but
-- which are not below this one.
; (home_insts, home_fam_insts) = hptInstancesBelow hsc_env (moduleName this_mod) (eltsUFM dep_mods)
} ;
-- Record boot-file info in the EPS, so that it's
-- visible to loadHiBootInterface in tcRnSrcDecls,
-- and any other incrementally-performed imports
; when (isOneShot (ghcMode (hsc_dflags hsc_env))) $ do {
updateEps_ $ \eps -> eps { eps_is_boot = imp_boot_mods imports }
}
-- Update the gbl env
; updGblEnv ( \ gbl ->
gbl {
tcg_rdr_env = tcg_rdr_env gbl `plusGlobalRdrEnv` rdr_env,
tcg_imports = tcg_imports gbl `plusImportAvails` imports,
tcg_rn_imports = rn_imports,
tcg_inst_env = extendInstEnvList (tcg_inst_env gbl) home_insts,
tcg_fam_inst_env = extendFamInstEnvList (tcg_fam_inst_env gbl)
home_fam_insts,
tcg_hpc = hpc_info
}) $ do {
; traceRn "rn1" (ppr (imp_direct_dep_mods imports))
-- Fail if there are any errors so far
-- The error printing (if needed) takes advantage
-- of the tcg_env we have now set
-- ; traceIf (text "rdr_env: " <+> ppr rdr_env)
; failIfErrsM
-- Load any orphan-module (including orphan family
-- instance-module) interfaces, so that their rules and
-- instance decls will be found. But filter out a
-- self hs-boot: these instances will be checked when
-- we define them locally.
-- (We don't need to load non-orphan family instance
-- modules until we either try to use the instances they
-- define, or define our own family instances, at which
-- point we need to check them for consistency.)
; loadModuleInterfaces (text "Loading orphan modules")
(filter (/= this_mod) (imp_orphs imports))
-- Check type-family consistency between imports.
-- See Note [The type family instance consistency story]
; traceRn "rn1: checking family instance consistency {" empty
; let { dir_imp_mods = moduleEnvKeys
. imp_mods
$ imports }
; checkFamInstConsistency dir_imp_mods
; traceRn "rn1: } checking family instance consistency" empty
; getGblEnv } }
{-
************************************************************************
* *
Type-checking the top level of a module
* *
************************************************************************
-}
tcRnSrcDecls :: Bool -- False => no 'module M(..) where' header at all
-> Maybe (LocatedL [LIE GhcPs])
-> [LHsDecl GhcPs] -- Declarations
-> TcM TcGblEnv
tcRnSrcDecls explicit_mod_hdr export_ies decls
= do { -- Do all the declarations
; (tcg_env, tcl_env, lie) <- tc_rn_src_decls decls
------ Simplify constraints ---------
--
-- We do this after checkMainType, so that we use the type
-- info that checkMainType adds
--
-- We do it with both global and local env in scope:
-- * the global env exposes the instances to simplifyTop,
-- and affects how names are rendered in error messages
-- * the local env exposes the local Ids to simplifyTop,
-- so that we get better error messages (monomorphism restriction)
; new_ev_binds <- {-# SCC "simplifyTop" #-}
setEnvs (tcg_env, tcl_env) $
do { lie_main <- checkMainType tcg_env
; simplifyTop (lie `andWC` lie_main) }
-- Emit Typeable bindings
; tcg_env <- setGblEnv tcg_env $
mkTypeableBinds
; traceTc "Tc9" empty
-- Zonk the final code. This must be done last.
-- Even simplifyTop may do some unification.
-- This pass also warns about missing type signatures
; (id_env, ev_binds', binds', fords', imp_specs', rules')
<- zonkTcGblEnv new_ev_binds tcg_env
--------- Run finalizers --------------
-- Finalizers must run after constraints are simplified, lest types
-- might not be complete when using reify (see #12777).
-- and also after we zonk the first time because we run typed splices
-- in the zonker which gives rise to the finalisers.
; let -- init_tcg_env:
-- * Remove accumulated bindings, rules and so on from
-- TcGblEnv. They are now in ev_binds', binds', etc.
-- * Add the zonked Ids from the value bindings to tcg_type_env
-- Up to now these Ids are only in tcl_env's type-envt
init_tcg_env = tcg_env { tcg_binds = emptyBag
, tcg_ev_binds = emptyBag
, tcg_imp_specs = []
, tcg_rules = []
, tcg_fords = []
, tcg_type_env = tcg_type_env tcg_env
`plusTypeEnv` id_env }
; (tcg_env, tcl_env) <- setGblEnv init_tcg_env
run_th_modfinalizers
; finishTH
; traceTc "Tc11" empty
--------- Deal with the exports ----------
-- Can't be done earlier, because the export list must "see"
-- the declarations created by the finalizers
; tcg_env <- setEnvs (tcg_env, tcl_env) $
rnExports explicit_mod_hdr export_ies
--------- Emit the ':Main.main = runMainIO main' declaration ----------
-- Do this /after/ rnExports, so that it can consult
-- the tcg_exports created by rnExports
; (tcg_env, main_ev_binds)
<- setEnvs (tcg_env, tcl_env) $
do { (tcg_env, lie) <- captureTopConstraints $
checkMain explicit_mod_hdr export_ies
; ev_binds <- simplifyTop lie
; return (tcg_env, ev_binds) }
---------- Final zonking ---------------
-- Zonk the new bindings arising from running the finalisers,
-- and main. This won't give rise to any more finalisers as you
-- can't nest finalisers inside finalisers.
; (id_env_mf, ev_binds_mf, binds_mf, fords_mf, imp_specs_mf, rules_mf)
<- zonkTcGblEnv main_ev_binds tcg_env
; let { !final_type_env = tcg_type_env tcg_env
`plusTypeEnv` id_env_mf
-- Add the zonked Ids from the value bindings (they were in tcl_env)
-- Force !final_type_env, lest we retain an old reference
-- to the previous tcg_env
; tcg_env' = tcg_env
{ tcg_binds = binds' `unionBags` binds_mf
, tcg_ev_binds = ev_binds' `unionBags` ev_binds_mf
, tcg_imp_specs = imp_specs' ++ imp_specs_mf
, tcg_rules = rules' ++ rules_mf
, tcg_fords = fords' ++ fords_mf } } ;
; setGlobalTypeEnv tcg_env' final_type_env
}
zonkTcGblEnv :: Bag EvBind -> TcGblEnv
-> TcM (TypeEnv, Bag EvBind, LHsBinds GhcTc,
[LForeignDecl GhcTc], [LTcSpecPrag], [LRuleDecl GhcTc])
zonkTcGblEnv ev_binds tcg_env@(TcGblEnv { tcg_binds = binds
, tcg_ev_binds = cur_ev_binds
, tcg_imp_specs = imp_specs
, tcg_rules = rules
, tcg_fords = fords })
= {-# SCC "zonkTopDecls" #-}
setGblEnv tcg_env $ -- This sets the GlobalRdrEnv which is used when rendering
-- error messages during zonking (notably levity errors)
do { failIfErrsM -- Don't zonk if there have been errors
-- It's a waste of time; and we may get debug warnings
-- about strangely-typed TyCons!
; let all_ev_binds = cur_ev_binds `unionBags` ev_binds
; zonkTopDecls all_ev_binds binds rules imp_specs fords }
-- | Runs TH finalizers and renames and typechecks the top-level declarations
-- that they could introduce.
run_th_modfinalizers :: TcM (TcGblEnv, TcLclEnv)
run_th_modfinalizers = do
th_modfinalizers_var <- fmap tcg_th_modfinalizers getGblEnv
th_modfinalizers <- readTcRef th_modfinalizers_var
if null th_modfinalizers
then getEnvs
else do
writeTcRef th_modfinalizers_var []
let run_finalizer (lcl_env, f) =
setLclEnv lcl_env (runRemoteModFinalizers f)
(_, lie_th) <- captureTopConstraints $
mapM_ run_finalizer th_modfinalizers
-- Finalizers can add top-level declarations with addTopDecls, so
-- we have to run tc_rn_src_decls to get them
(tcg_env, tcl_env, lie_top_decls) <- tc_rn_src_decls []
setEnvs (tcg_env, tcl_env) $ do
-- Subsequent rounds of finalizers run after any new constraints are
-- simplified, or some types might not be complete when using reify
-- (see #12777).
new_ev_binds <- {-# SCC "simplifyTop2" #-}
simplifyTop (lie_th `andWC` lie_top_decls)
addTopEvBinds new_ev_binds run_th_modfinalizers
-- addTopDecls can add declarations which add new finalizers.
tc_rn_src_decls :: [LHsDecl GhcPs]
-> TcM (TcGblEnv, TcLclEnv, WantedConstraints)
-- Loops around dealing with each top level inter-splice group
-- in turn, until it's dealt with the entire module
-- Never emits constraints; calls captureTopConstraints internally
tc_rn_src_decls ds
= {-# SCC "tc_rn_src_decls" #-}
do { (first_group, group_tail) <- findSplice ds
-- If ds is [] we get ([], Nothing)
-- Deal with decls up to, but not including, the first splice
; (tcg_env, rn_decls) <- rnTopSrcDecls first_group
-- rnTopSrcDecls fails if there are any errors
-- Get TH-generated top-level declarations and make sure they don't
-- contain any splices since we don't handle that at the moment
--
-- The plumbing here is a bit odd: see #10853
; th_topdecls_var <- fmap tcg_th_topdecls getGblEnv
; th_ds <- readTcRef th_topdecls_var
; writeTcRef th_topdecls_var []
; (tcg_env, rn_decls) <-
if null th_ds
then return (tcg_env, rn_decls)
else do { (th_group, th_group_tail) <- findSplice th_ds
; case th_group_tail of
{ Nothing -> return ()
; Just (SpliceDecl _ (L loc _) _, _) ->
setSrcSpanA loc
$ addErr (text
("Declaration splices are not "
++ "permitted inside top-level "
++ "declarations added with addTopDecls"))
}
-- Rename TH-generated top-level declarations
; (tcg_env, th_rn_decls) <- setGblEnv tcg_env
$ rnTopSrcDecls th_group
-- Dump generated top-level declarations
; let msg = "top-level declarations added with addTopDecls"
; traceSplice
$ SpliceInfo { spliceDescription = msg
, spliceIsDecl = True
, spliceSource = Nothing
, spliceGenerated = ppr th_rn_decls }
; return (tcg_env, appendGroups rn_decls th_rn_decls)
}
-- Type check all declarations
-- NB: set the env **before** captureTopConstraints so that error messages
-- get reported w.r.t. the right GlobalRdrEnv. It is for this reason that
-- the captureTopConstraints must go here, not in tcRnSrcDecls.
; ((tcg_env, tcl_env), lie1) <- setGblEnv tcg_env $
captureTopConstraints $
tcTopSrcDecls rn_decls
-- If there is no splice, we're nearly done
; setEnvs (tcg_env, tcl_env) $
case group_tail of
{ Nothing -> return (tcg_env, tcl_env, lie1)
-- If there's a splice, we must carry on
; Just (SpliceDecl _ (L _ splice) _, rest_ds) ->
do {
-- We need to simplify any constraints from the previous declaration
-- group, or else we might reify metavariables, as in #16980.
; ev_binds1 <- simplifyTop lie1
-- Rename the splice expression, and get its supporting decls
; (spliced_decls, splice_fvs) <- rnTopSpliceDecls splice
-- Glue them on the front of the remaining decls and loop
; setGblEnv (tcg_env `addTcgDUs` usesOnly splice_fvs) $
addTopEvBinds ev_binds1 $
tc_rn_src_decls (spliced_decls ++ rest_ds)
}
}
}
{-
************************************************************************
* *
Compiling hs-boot source files, and
comparing the hi-boot interface with the real thing
* *
************************************************************************
-}
tcRnHsBootDecls :: HscSource -> [LHsDecl GhcPs] -> TcM TcGblEnv
tcRnHsBootDecls hsc_src decls
= do { (first_group, group_tail) <- findSplice decls
-- Rename the declarations
; (tcg_env, HsGroup { hs_tyclds = tycl_decls
, hs_derivds = deriv_decls
, hs_fords = for_decls
, hs_defds = def_decls
, hs_ruleds = rule_decls
, hs_annds = _
, hs_valds = XValBindsLR (NValBinds val_binds val_sigs) })
<- rnTopSrcDecls first_group
-- The empty list is for extra dependencies coming from .hs-boot files
-- See Note [Extra dependencies from .hs-boot files] in GHC.Rename.Module
; (gbl_env, lie) <- setGblEnv tcg_env $ captureTopConstraints $ do {
-- NB: setGblEnv **before** captureTopConstraints so that
-- if the latter reports errors, it knows what's in scope
-- Check for illegal declarations
; case group_tail of
Just (SpliceDecl _ d _, _) -> badBootDecl hsc_src "splice" d
Nothing -> return ()
; mapM_ (badBootDecl hsc_src "foreign") for_decls
; mapM_ (badBootDecl hsc_src "default") def_decls
; mapM_ (badBootDecl hsc_src "rule") rule_decls
-- Typecheck type/class/instance decls
; traceTc "Tc2 (boot)" empty
; (tcg_env, inst_infos, _deriv_binds, _class_scoped_tv_env)
<- tcTyClsInstDecls tycl_decls deriv_decls val_binds
; setGblEnv tcg_env $ do {
-- Emit Typeable bindings
; tcg_env <- mkTypeableBinds
; setGblEnv tcg_env $ do {
-- Typecheck value declarations
; traceTc "Tc5" empty
; val_ids <- tcHsBootSigs val_binds val_sigs
-- Wrap up
-- No simplification or zonking to do
; traceTc "Tc7a" empty
; gbl_env <- getGblEnv
-- Make the final type-env
-- Include the dfun_ids so that their type sigs
-- are written into the interface file.
; let { type_env0 = tcg_type_env gbl_env
; type_env1 = extendTypeEnvWithIds type_env0 val_ids
; type_env2 = extendTypeEnvWithIds type_env1 dfun_ids
; dfun_ids = map iDFunId inst_infos
}
; setGlobalTypeEnv gbl_env type_env2
}}}
; traceTc "boot" (ppr lie); return gbl_env }
badBootDecl :: HscSource -> String -> LocatedA decl -> TcM ()
badBootDecl hsc_src what (L loc _)
= addErrAt (locA loc) (char 'A' <+> text what
<+> text "declaration is not (currently) allowed in a"
<+> (case hsc_src of
HsBootFile -> text "hs-boot"
HsigFile -> text "hsig"
_ -> panic "badBootDecl: should be an hsig or hs-boot file")
<+> text "file")
{-
Once we've typechecked the body of the module, we want to compare what
we've found (gathered in a TypeEnv) with the hi-boot details (if any).
-}
checkHiBootIface :: TcGblEnv -> SelfBootInfo -> TcM TcGblEnv
-- Compare the hi-boot file for this module (if there is one)
-- with the type environment we've just come up with
-- In the common case where there is no hi-boot file, the list
-- of boot_names is empty.
checkHiBootIface tcg_env boot_info
| NoSelfBoot <- boot_info -- Common case
= return tcg_env
| HsBootFile <- tcg_src tcg_env -- Current module is already a hs-boot file!
= return tcg_env
| SelfBoot { sb_mds = boot_details } <- boot_info
, TcGblEnv { tcg_binds = binds
, tcg_insts = local_insts
, tcg_type_env = local_type_env
, tcg_exports = local_exports } <- tcg_env
= do { -- This code is tricky, see Note [DFun knot-tying]
; dfun_prs <- checkHiBootIface' local_insts local_type_env
local_exports boot_details
-- Now add the boot-dfun bindings $fxblah = $fblah
-- to (a) the type envt, and (b) the top-level bindings
; let boot_dfuns = map fst dfun_prs
type_env' = extendTypeEnvWithIds local_type_env boot_dfuns
dfun_binds = listToBag [ mkVarBind boot_dfun (nlHsVar dfun)
| (boot_dfun, dfun) <- dfun_prs ]
tcg_env_w_binds
= tcg_env { tcg_binds = binds `unionBags` dfun_binds }
; type_env' `seq`
-- Why the seq? Without, we will put a TypeEnv thunk in
-- tcg_type_env_var. That thunk will eventually get
-- forced if we are typechecking interfaces, but that
-- is no good if we are trying to typecheck the very
-- DFun we were going to put in.
-- TODO: Maybe setGlobalTypeEnv should be strict.
setGlobalTypeEnv tcg_env_w_binds type_env' }
#if __GLASGOW_HASKELL__ <= 810
| otherwise = panic "checkHiBootIface: unreachable code"
#endif
{- Note [DFun impedance matching]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We return a list of "impedance-matching" bindings for the dfuns
defined in the hs-boot file, such as
$fxEqT = $fEqT
We need these because the module and hi-boot file might differ in
the name it chose for the dfun: the name of a dfun is not
uniquely determined by its type; there might be multiple dfuns
which, individually, would map to the same name (in which case
we have to disambiguate them.) There's no way for the hi file
to know exactly what disambiguation to use... without looking
at the hi-boot file itself.
In fact, the names will always differ because we always pick names
prefixed with "$fx" for boot dfuns, and "$f" for real dfuns
(so that this impedance matching is always possible).
Note [DFun knot-tying]
~~~~~~~~~~~~~~~~~~~~~~
The 'SelfBootInfo' that is fed into 'checkHiBootIface' comes from
typechecking the hi-boot file that we are presently implementing.
Suppose we are typechecking the module A: when we typecheck the
hi-boot file, whenever we see an identifier A.T, we knot-tie this
identifier to the *local* type environment (via if_rec_types.) The
contract then is that we don't *look* at 'SelfBootInfo' until we've
finished typechecking the module and updated the type environment with
the new tycons and ids.
This most works well, but there is one problem: DFuns! We do not want
to look at the mb_insts of the ModDetails in SelfBootInfo, because a
dfun in one of those ClsInsts is gotten (in GHC.IfaceToCore.tcIfaceInst) by a
(lazily evaluated) lookup in the if_rec_types. We could extend the
type env, do a setGloblaTypeEnv etc; but that all seems very indirect.
It is much more directly simply to extract the DFunIds from the
md_types of the SelfBootInfo.
See #4003, #16038 for why we need to take care here.
-}
checkHiBootIface' :: [ClsInst] -> TypeEnv -> [AvailInfo]
-> ModDetails -> TcM [(Id, Id)]
-- Variant which doesn't require a full TcGblEnv; you could get the
-- local components from another ModDetails.
checkHiBootIface'
local_insts local_type_env local_exports
(ModDetails { md_types = boot_type_env
, md_fam_insts = boot_fam_insts
, md_exports = boot_exports })
= do { traceTc "checkHiBootIface" $ vcat
[ ppr boot_type_env, ppr boot_exports]
-- Check the exports of the boot module, one by one
; mapM_ check_export boot_exports
-- Check for no family instances
; unless (null boot_fam_insts) $
panic ("GHC.Tc.Module.checkHiBootIface: Cannot handle family " ++
"instances in boot files yet...")
-- FIXME: Why? The actual comparison is not hard, but what would
-- be the equivalent to the dfun bindings returned for class
-- instances? We can't easily equate tycons...
-- Check instance declarations
-- and generate an impedance-matching binding
; mb_dfun_prs <- mapM check_cls_inst boot_dfuns
; failIfErrsM
; return (catMaybes mb_dfun_prs) }
where
boot_dfun_names = map idName boot_dfuns
boot_dfuns = filter isDFunId $ typeEnvIds boot_type_env
-- NB: boot_dfuns is /not/ defined thus: map instanceDFunId md_insts
-- We don't want to look at md_insts!
-- Why not? See Note [DFun knot-tying]
check_export boot_avail -- boot_avail is exported by the boot iface
| name `elem` boot_dfun_names = return ()
-- Check that the actual module exports the same thing
| not (null missing_names)
= addErrAt (nameSrcSpan (head missing_names))
(missingBootThing True (head missing_names) "exported by")
-- If the boot module does not *define* the thing, we are done
-- (it simply re-exports it, and names match, so nothing further to do)
| isNothing mb_boot_thing = return ()
-- Check that the actual module also defines the thing, and
-- then compare the definitions
| Just real_thing <- lookupTypeEnv local_type_env name,
Just boot_thing <- mb_boot_thing
= checkBootDeclM True boot_thing real_thing
| otherwise
= addErrTc (missingBootThing True name "defined in")
where
name = availName boot_avail
mb_boot_thing = lookupTypeEnv boot_type_env name
missing_names = case lookupNameEnv local_export_env name of
Nothing -> [name]
Just avail -> availNames boot_avail `minusList` availNames avail
local_export_env :: NameEnv AvailInfo
local_export_env = availsToNameEnv local_exports
check_cls_inst :: DFunId -> TcM (Maybe (Id, Id))
-- Returns a pair of the boot dfun in terms of the equivalent
-- real dfun. Delicate (like checkBootDecl) because it depends
-- on the types lining up precisely even to the ordering of
-- the type variables in the foralls.
check_cls_inst boot_dfun
| (real_dfun : _) <- find_real_dfun boot_dfun
, let local_boot_dfun = Id.mkExportedVanillaId
(idName boot_dfun) (idType real_dfun)
= return (Just (local_boot_dfun, real_dfun))
-- Two tricky points here:
--
-- * The local_boot_fun should have a Name from the /boot-file/,
-- but type from the dfun defined in /this module/.
-- That ensures that the TyCon etc inside the type are
-- the ones defined in this module, not the ones gotten
-- from the hi-boot file, which may have a lot less info
-- (#8743, comment:10).
--
-- * The DFunIds from boot_details are /GlobalIds/, because
-- they come from typechecking M.hi-boot.
-- But all bindings in this module should be for /LocalIds/,
-- otherwise dependency analysis fails (#16038). This
-- is another reason for using mkExportedVanillaId, rather
-- that modifying boot_dfun, to make local_boot_fun.
| otherwise
= setSrcSpan (nameSrcSpan (getName boot_dfun)) $
do { traceTc "check_cls_inst" $ vcat
[ text "local_insts" <+>
vcat (map (ppr . idType . instanceDFunId) local_insts)
, text "boot_dfun_ty" <+> ppr (idType boot_dfun) ]
; addErrTc (instMisMatch boot_dfun)
; return Nothing }
find_real_dfun :: DFunId -> [DFunId]
find_real_dfun boot_dfun
= [dfun | inst <- local_insts
, let dfun = instanceDFunId inst
, idType dfun `eqType` boot_dfun_ty ]
where
boot_dfun_ty = idType boot_dfun
-- In general, to perform these checks we have to
-- compare the TyThing from the .hi-boot file to the TyThing
-- in the current source file. We must be careful to allow alpha-renaming
-- where appropriate, and also the boot declaration is allowed to omit
-- constructors and class methods.
--
-- See rnfail055 for a good test of this stuff.
-- | Compares two things for equivalence between boot-file and normal code,
-- reporting an error if they don't match up.
checkBootDeclM :: Bool -- ^ True <=> an hs-boot file (could also be a sig)
-> TyThing -> TyThing -> TcM ()
checkBootDeclM is_boot boot_thing real_thing
= whenIsJust (checkBootDecl is_boot boot_thing real_thing) $ \ err ->
addErrAt span
(bootMisMatch is_boot err real_thing boot_thing)
where
-- Here we use the span of the boot thing or, if it doesn't have a sensible
-- span, that of the real thing,
span
| let span = nameSrcSpan (getName boot_thing)
, isGoodSrcSpan span
= span
| otherwise
= nameSrcSpan (getName real_thing)
-- | Compares the two things for equivalence between boot-file and normal
-- code. Returns @Nothing@ on success or @Just "some helpful info for user"@
-- failure. If the difference will be apparent to the user, @Just empty@ is
-- perfectly suitable.
checkBootDecl :: Bool -> TyThing -> TyThing -> Maybe SDoc
checkBootDecl _ (AnId id1) (AnId id2)
= assert (id1 == id2) $
check (idType id1 `eqType` idType id2)
(text "The two types are different")
checkBootDecl is_boot (ATyCon tc1) (ATyCon tc2)
= checkBootTyCon is_boot tc1 tc2
checkBootDecl _ (AConLike (RealDataCon dc1)) (AConLike (RealDataCon _))
= pprPanic "checkBootDecl" (ppr dc1)
checkBootDecl _ _ _ = Just empty -- probably shouldn't happen
-- | Combines two potential error messages
andThenCheck :: Maybe SDoc -> Maybe SDoc -> Maybe SDoc
Nothing `andThenCheck` msg = msg
msg `andThenCheck` Nothing = msg
Just d1 `andThenCheck` Just d2 = Just (d1 $$ d2)
infixr 0 `andThenCheck`
-- | If the test in the first parameter is True, succeed with @Nothing@;
-- otherwise, return the provided check
checkUnless :: Bool -> Maybe SDoc -> Maybe SDoc
checkUnless True _ = Nothing
checkUnless False k = k
-- | Run the check provided for every pair of elements in the lists.
-- The provided SDoc should name the element type, in the plural.