9
9
{-# LANGUAGE FlexibleContexts #-}
10
10
{-# LANGUAGE TypeFamilies #-}
11
11
12
- module TcPatSyn ( tcInferPatSynDecl , tcCheckPatSynDecl
13
- , tcPatSynBuilderBind , tcPatSynBuilderOcc , nonBidirectionalErr
12
+ module TcPatSyn ( tcPatSynDecl , tcPatSynBuilderBind
13
+ , tcPatSynBuilderOcc , nonBidirectionalErr
14
14
) where
15
15
16
16
import GhcPrelude
@@ -53,7 +53,7 @@ import FieldLabel
53
53
import Bag
54
54
import Util
55
55
import ErrUtils
56
- import Control.Monad ( zipWithM )
56
+ import Control.Monad ( zipWithM , when )
57
57
import Data.List ( partition )
58
58
59
59
#include "HsVersions.h"
@@ -66,6 +66,58 @@ import Data.List( partition )
66
66
************************************************************************
67
67
-}
68
68
69
+ tcPatSynDecl :: PatSynBind GhcRn GhcRn
70
+ -> Maybe TcSigInfo
71
+ -> TcM (LHsBinds GhcTc , TcGblEnv )
72
+ tcPatSynDecl psb@ (PSB { psb_id = L _ name, psb_args = details }) mb_sig
73
+ = recoverM recover $
74
+ case mb_sig of
75
+ Nothing -> tcInferPatSynDecl psb
76
+ Just (TcPatSynSig tpsi) -> tcCheckPatSynDecl psb tpsi
77
+ _ -> panic " tcPatSynDecl"
78
+
79
+ where
80
+ -- See Note [Pattern synonym error recovery]
81
+ recover = do { matcher_name <- newImplicitBinder name mkMatcherOcc
82
+ ; let placeholder = AConLike $ PatSynCon $
83
+ mk_placeholder matcher_name
84
+ ; gbl_env <- tcExtendGlobalEnv [placeholder] getGblEnv
85
+ ; return (emptyBag, gbl_env) }
86
+
87
+ (_arg_names, _rec_fields, is_infix) = collectPatSynArgInfo details
88
+ mk_placeholder matcher_name
89
+ = mkPatSyn name is_infix
90
+ ([mkTyVarBinder Specified alphaTyVar], [] ) ([] , [] )
91
+ [] -- Arg tys
92
+ alphaTy
93
+ (matcher_id, True ) Nothing
94
+ [] -- Field labels
95
+ where
96
+ -- The matcher_id is used only by the desugarer, so actually
97
+ -- and error-thunk would probably do just as well here.
98
+ matcher_id = mkLocalId matcher_name $
99
+ mkSpecForAllTys [alphaTyVar] alphaTy
100
+
101
+ tcPatSynDecl (XPatSynBind {}) _ = panic " tcPatSynDecl"
102
+
103
+ {- Note [Pattern synonym error recovery]
104
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105
+ If type inference for a pattern synonym fails , we can't continue with
106
+ the rest of tc_patsyn_finish, because we may get knock-on errors, or
107
+ even a crash. E.g. from
108
+ pattern What = True :: Maybe
109
+ we get a kind error; and we must stop right away (Trac #15289).
110
+ Hence the 'when insoluble failM' in tcInferPatSyn.
111
+
112
+ But does that abort compilation entirely? No -- we can recover
113
+ and carry on, just as we do for value bindings, provided we plug in
114
+ placeholder for the pattern synonym. The goal of the placeholder
115
+ is not to cause a raft of follow-on errors. I've used the simplest
116
+ thing for now, but we might need to elaborate it a bit later. (e.g.
117
+ I've given it zero args, which may cause knock-on errors if it is
118
+ used in a pattern.) But it'll do for now.
119
+ -}
120
+
69
121
tcInferPatSynDecl :: PatSynBind GhcRn GhcRn
70
122
-> TcM (LHsBinds GhcTc , TcGblEnv )
71
123
tcInferPatSynDecl PSB { psb_id = lname@ (L _ name), psb_args = details,
@@ -76,14 +128,19 @@ tcInferPatSynDecl PSB{ psb_id = lname@(L _ name), psb_args = details,
76
128
; let (arg_names, rec_fields, is_infix) = collectPatSynArgInfo details
77
129
; (tclvl, wanted, ((lpat', args), pat_ty))
78
130
<- pushLevelAndCaptureConstraints $
79
- tcInferNoInst $ \ exp_ty ->
80
- tcPat PatSyn lpat exp_ty $
131
+ tcInferNoInst $ \ exp_ty ->
132
+ tcPat PatSyn lpat exp_ty $
81
133
mapM tcLookupId arg_names
82
134
83
135
; let named_taus = (name, pat_ty) : map (\ arg -> (getName arg, varType arg)) args
84
136
85
- ; (qtvs, req_dicts, ev_binds, _) <- simplifyInfer tclvl NoRestrictions []
86
- named_taus wanted
137
+ ; (qtvs, req_dicts, ev_binds, insoluble)
138
+ <- simplifyInfer tclvl NoRestrictions [] named_taus wanted
139
+
140
+ ; when insoluble failM
141
+ -- simplifyInfer doesn't fail if there are errors. But to avoid
142
+ -- knock-on errors, or even crashes, we want to stop here.
143
+ -- See Note [Pattern synonym error recovery]
87
144
88
145
; let (ex_tvs, prov_dicts) = tcCollectEx lpat'
89
146
ex_tv_set = mkVarSet ex_tvs
@@ -772,10 +829,15 @@ tcPatSynBuilderBind (PSB { psb_id = L loc name, psb_def = lpat
772
829
773
830
| Right match_group <- mb_match_group -- Bidirectional
774
831
= do { patsyn <- tcLookupPatSyn name
775
- ; let Just (builder_id, need_dummy_arg) = patSynBuilder patsyn
776
- -- Bidirectional, so patSynBuilder returns Just
777
-
778
- match_group' | need_dummy_arg = add_dummy_arg match_group
832
+ ; case patSynBuilder patsyn of {
833
+ Nothing -> return emptyBag ;
834
+ -- This case happens if we found a type error in the
835
+ -- pattern synonym, recovered, and put a placeholder
836
+ -- with patSynBuilder=Nothing in the environment
837
+
838
+ Just (builder_id, need_dummy_arg) -> -- Normal case
839
+ do { -- Bidirectional, so patSynBuilder returns Just
840
+ let match_group' | need_dummy_arg = add_dummy_arg match_group
779
841
| otherwise = match_group
780
842
781
843
bind = FunBind { fun_ext = placeHolderNamesTc
@@ -790,7 +852,7 @@ tcPatSynBuilderBind (PSB { psb_id = L loc name, psb_def = lpat
790
852
ppr patsyn $$ ppr builder_id <+> dcolon <+> ppr (idType builder_id)
791
853
; (builder_binds, _) <- tcPolyCheck emptyPragEnv sig (noLoc bind)
792
854
; traceTc " tcPatSynBuilderBind }" $ ppr builder_binds
793
- ; return builder_binds }
855
+ ; return builder_binds } } }
794
856
795
857
| otherwise = panic " tcPatSynBuilderBind" -- Both cases dealt with
796
858
where
0 commit comments