diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2022-06-28 15:06:16 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2022-07-09 11:12:34 -0400 |
commit | 460505345e500eb902da9737c75c077d5fc5ef66 (patch) | |
tree | f0da97e593dbcced8bd4abf1d71ba7840d665ced /compiler/GHC | |
parent | fc183c9026284ebd70dfd0a0a6682b9b7a96a676 (diff) | |
download | haskell-460505345e500eb902da9737c75c077d5fc5ef66.tar.gz |
Fix a scoping bug in the Specialiser
In the call to `specLookupRule` in `already_covered`, in `specCalls`,
we need an in-scope set that includes the free vars of the arguments.
But we simply were not guaranteeing that: did not include the
`rule_bndrs`.
Easily fixed. I'm not sure how how this bug has lain for quite
so long without biting us.
Fixes #21828.
Diffstat (limited to 'compiler/GHC')
-rw-r--r-- | compiler/GHC/Core/Opt/Specialise.hs | 34 | ||||
-rw-r--r-- | compiler/GHC/Core/Rules.hs | 2 |
2 files changed, 19 insertions, 17 deletions
diff --git a/compiler/GHC/Core/Opt/Specialise.hs b/compiler/GHC/Core/Opt/Specialise.hs index c256ac3d55..ab72537005 100644 --- a/compiler/GHC/Core/Opt/Specialise.hs +++ b/compiler/GHC/Core/Opt/Specialise.hs @@ -1158,9 +1158,10 @@ specExpr env (Let bind body) rewriteClassOps :: SpecEnv -> InExpr -> [OutExpr] -> (InExpr, [OutExpr]) rewriteClassOps env (Var f) args | isClassOpId f -- If we see `op_sel $fCInt`, we rewrite to `$copInt` - , Just (rule, expr) <- specLookupRule env f args (idCoreRules f) + , Just (rule, expr) <- -- pprTrace "rewriteClassOps" (ppr f $$ ppr args $$ ppr (se_subst env)) $ + specLookupRule env f args (idCoreRules f) , let rest_args = drop (ruleArity rule) args -- See Note [Extra args in the target] - -- , pprTrace "class op rewritten" (ppr f <+> ppr args $$ ppr expr <+> ppr rest_args) True +-- , pprTrace "class op rewritten" (ppr f <+> ppr args $$ ppr expr <+> ppr rest_args) True , (fun, args) <- collectArgs expr = rewriteClassOps env fun (args++rest_args) rewriteClassOps _ fun args = (fun, args) @@ -1490,10 +1491,9 @@ specCalls spec_imp env dict_binds existing_rules calls_for_me fn rhs -- Bring into scope the binders from the floated dicts env_with_dict_bndrs = bringFloatedDictsIntoScope env dict_binds - already_covered :: [CoreRule] -> [CoreExpr] -> Bool - already_covered new_rules args -- Note [Specialisations already covered] - = isJust (specLookupRule env_with_dict_bndrs fn args - (new_rules ++ existing_rules)) + already_covered :: SpecEnv -> [CoreRule] -> [CoreExpr] -> Bool + already_covered env new_rules args -- Note [Specialisations already covered] + = isJust (specLookupRule env fn args (new_rules ++ existing_rules)) -- NB: we look both in the new_rules (generated by this invocation -- of specCalls), and in existing_rules (passed in to specCalls) @@ -1515,21 +1515,22 @@ specCalls spec_imp env dict_binds existing_rules calls_for_me fn rhs , spec_bndrs1, dx_binds, spec_args) <- specHeader env_with_dict_bndrs rhs_bndrs all_call_args --- ; pprTrace "spec_call" (vcat [ text "fun: " <+> ppr fn --- , text "call info: " <+> ppr _ci --- , text "useful: " <+> ppr useful --- , text "rule_bndrs:" <+> ppr rule_bndrs --- , text "lhs_args: " <+> ppr rule_lhs_args --- , text "spec_bndrs:" <+> ppr spec_bndrs1 --- , text "spec_args: " <+> ppr spec_args --- , text "dx_binds: " <+> ppr dx_binds --- , text "rhs_env2: " <+> ppr (se_subst rhs_env2) +-- ; pprTrace "spec_call" (vcat [ text "fun: " <+> ppr fn +-- , text "call info: " <+> ppr _ci +-- , text "useful: " <+> ppr useful +-- , text "rule_bndrs:" <+> ppr rule_bndrs +-- , text "lhs_args: " <+> ppr rule_lhs_args +-- , text "spec_bndrs1:" <+> ppr spec_bndrs1 -- , text "leftover_bndrs:" <+> pprIds leftover_bndrs +-- , text "spec_args: " <+> ppr spec_args +-- , text "dx_binds: " <+> ppr dx_binds +-- , text "rhs_body" <+> ppr rhs_body +-- , text "rhs_env2: " <+> ppr (se_subst rhs_env2) -- , ppr dx_binds ]) $ -- return () ; if not useful -- No useful specialisation - || already_covered rules_acc rule_lhs_args + || already_covered rhs_env2 rules_acc rule_lhs_args then return spec_acc else do { -- Run the specialiser on the specialised RHS @@ -1633,6 +1634,7 @@ specCalls spec_imp env dict_binds existing_rules calls_for_me fn rhs ) } } -- Convenience function for invoking lookupRule from Specialise +-- The SpecEnv's InScopeSet should include all the Vars in the [CoreExpr] specLookupRule :: SpecEnv -> Id -> [CoreExpr] -> [CoreRule] -> Maybe (CoreRule, CoreExpr) specLookupRule env fn args rules = lookupRule ropts (in_scope, realIdUnfolding) (const True) fn args rules diff --git a/compiler/GHC/Core/Rules.hs b/compiler/GHC/Core/Rules.hs index 451d1ac5c1..444ed1e50b 100644 --- a/compiler/GHC/Core/Rules.hs +++ b/compiler/GHC/Core/Rules.hs @@ -395,7 +395,7 @@ lookupRule :: RuleOpts -> InScopeEnv -- See Note [Extra args in the target] -- See comments on matchRule lookupRule opts rule_env@(in_scope,_) is_active fn args rules - = -- pprTrace "matchRules" (ppr fn <+> ppr args $$ ppr rules ) $ + = -- pprTrace "lookupRule" (ppr fn <+> ppr args $$ ppr rules $$ ppr in_scope) $ case go [] rules of [] -> Nothing (m:ms) -> Just (findBest in_scope (fn,args') m ms) |