| ... |
... |
@@ -14,6 +14,7 @@ import GHC.Core.Rules |
|
14
|
14
|
import GHC.Core.Ppr ( pprCoreBindings, pprCoreExpr )
|
|
15
|
15
|
import GHC.Core.Opt.OccurAnal ( occurAnalysePgm, occurAnalyseExpr )
|
|
16
|
16
|
import GHC.Core.Stats ( coreBindsSize, coreBindsStats, exprSize )
|
|
|
17
|
+import GHC.Core.FVs ( exprFreeVars )
|
|
17
|
18
|
import GHC.Core.Utils ( mkTicks, stripTicksTop )
|
|
18
|
19
|
import GHC.Core.Lint ( LintPassResultConfig, dumpPassResult, lintPassResult )
|
|
19
|
20
|
import GHC.Core.Opt.Simplify.Iteration ( simplTopBinds, simplExpr, simplImpRules )
|
| ... |
... |
@@ -74,7 +75,10 @@ simplifyExpr logger euc opts expr |
|
74
|
75
|
; let fam_envs = ( eps_fam_inst_env eps
|
|
75
|
76
|
, extendFamInstEnvList emptyFamInstEnv $ se_fam_inst opts
|
|
76
|
77
|
)
|
|
77
|
|
- simpl_env = mkSimplEnv (se_mode opts) fam_envs
|
|
|
78
|
+ -- See Note [Seed the in-scope set for open expressions]
|
|
|
79
|
+ simpl_env = setInScopeSet base_env
|
|
|
80
|
+ (getInScope base_env `extendInScopeSetSet` exprFreeVars expr)
|
|
|
81
|
+ base_env = mkSimplEnv (se_mode opts) fam_envs
|
|
78
|
82
|
top_env_cfg = se_top_env_cfg opts
|
|
79
|
83
|
read_eps_rules = eps_rule_base <$> eucEPS euc
|
|
80
|
84
|
read_ruleenv = updExternalPackageRules emptyRuleEnv <$> read_eps_rules
|
| ... |
... |
@@ -94,6 +98,49 @@ simplifyExpr logger euc opts expr |
|
94
|
98
|
; return expr'
|
|
95
|
99
|
}
|
|
96
|
100
|
|
|
|
101
|
+{- Note [Seed the in-scope set for open expressions]
|
|
|
102
|
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
103
|
+An invariant of the Simplifier is that the in-scope set contains all the free
|
|
|
104
|
+variables of the expression being simplified. Why? So that the Simplifier
|
|
|
105
|
+never invents a "fresh" binder that accidentally captures one of those free
|
|
|
106
|
+variables.
|
|
|
107
|
+
|
|
|
108
|
+'simplifyExpr' establishes that invariant by initialising the in-scope set with
|
|
|
109
|
+the free variables of the expression it is given. For a closed expression this
|
|
|
110
|
+adds nothing.
|
|
|
111
|
+
|
|
|
112
|
+But how can 'simplifyExpr' be handed an /open/ expression in the first place?
|
|
|
113
|
+The whole-module pipeline never does so: 'simplifyPgm' only ever simplifies
|
|
|
114
|
+closed bindings. The one caller that can is 'hscCompileCoreExpr' (in
|
|
|
115
|
+GHC.Driver.Main.Passes), which compiles a single Core expression, and is itself
|
|
|
116
|
+reached from just two places:
|
|
|
117
|
+
|
|
|
118
|
+ * GHCi, for an expression typed at the prompt, and in particular in the
|
|
|
119
|
+ debugger (see below);
|
|
|
120
|
+ * Template Haskell, when running a splice (see GHC.Tc.Gen.Splice).
|
|
|
121
|
+
|
|
|
122
|
+So this is never on the critical path for mainstream compilation.
|
|
|
123
|
+
|
|
|
124
|
+Here is how the debugger hands us an open expression (test break006). We are
|
|
|
125
|
+stopped at a breakpoint in
|
|
|
126
|
+ mymap f (x:xs) = f x : ...
|
|
|
127
|
+where the debugger knows that 'x :: Int' but not yet the result type of 'f'. So
|
|
|
128
|
+it invents a RuntimeUnk skolem 'a' and gives 'f :: Int -> a'. The user then
|
|
|
129
|
+types
|
|
|
130
|
+ let y = f x
|
|
|
131
|
+GHCi type-checks that and, to hand the result back to the interpreter (see
|
|
|
132
|
+GHC.Tc.Module.tcGhciStmts), wraps it as
|
|
|
133
|
+ returnIO @[Any] [unsafeCoerce# @LiftedRep @LiftedRep @a @Any y]
|
|
|
134
|
+in which the skolem 'a' is free.
|
|
|
135
|
+
|
|
|
136
|
+When the Simplifier instantiates that 'unsafeCoerce#', it builds a substitution
|
|
|
137
|
+mapping unsafeCoerce#'s quantified type variables to (LiftedRep, LiftedRep, a,
|
|
|
138
|
+Any), whose range therefore mentions 'a'. The in-scope set of a substitution
|
|
|
139
|
+must contain the free variables of its range (see Note [The substitution
|
|
|
140
|
+invariant] in GHC.Core.TyCo.Subst). Without the seeding above that invariant is
|
|
|
141
|
+broken, and in a compiler built with assertions substTy's sanity check fails
|
|
|
142
|
+(#17833, and its duplicate #21118). -}
|
|
|
143
|
+
|
|
97
|
144
|
simplExprGently :: SimplEnv -> CoreExpr -> SimplM CoreExpr
|
|
98
|
145
|
-- ^ Simplifies an expression by doing occurrence analysis, then simplification,
|
|
99
|
146
|
-- and repeating (twice currently), because one pass alone leaves tons of crud.
|