2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[TcPat]{Typechecking patterns}
7 #include "HsVersions.h"
9 module TcPat ( tcPat ) where
13 import HsSyn ( InPat(..), OutPat(..), HsExpr(..), HsLit(..),
14 Match, HsBinds, Qual, PolyType,
15 ArithSeqInfo, Stmt, Fake )
16 import RnHsSyn ( RenamedPat(..) )
17 import TcHsSyn ( TcPat(..), TcIdOcc(..) )
20 import Inst ( Inst, OverloadedLit(..), InstOrigin(..),
21 emptyLIE, plusLIE, plusLIEs, LIE(..),
22 newMethod, newOverloadedLit
24 import TcEnv ( tcLookupGlobalValue, tcLookupGlobalValueByKey,
25 tcLookupLocalValueOK )
26 import TcType ( TcType(..), TcMaybe, tcInstType, newTyVarTy, newTyVarTys, tcInstId )
27 import Unify ( unifyTauTy, unifyTauTyList, unifyTauTyLists )
30 import CmdLineOpts ( opt_IrrefutableTuples )
31 import Id ( GenId, idType )
32 import Kind ( Kind, mkBoxedTypeKind, mkTypeKind )
33 import Maybes ( maybeToBool )
34 import PprType ( GenType, GenTyVar )
35 import PrelInfo ( charPrimTy, intPrimTy, floatPrimTy,
36 doublePrimTy, charTy, stringTy, mkListTy,
37 mkTupleTy, addrTy, addrPrimTy )
39 import RnHsSyn ( RnName{-instance Outputable-} )
40 import Type ( splitFunTy, splitRhoTy, splitSigmaTy, mkTyVarTys,
41 getFunTy_maybe, maybeAppDataTyCon,
44 import TyVar ( GenTyVar )
45 import Unique ( Unique, eqClassOpKey )
46 import Util ( assertPanic, panic{-ToDo:rm-} )
50 tcPat :: RenamedPat -> TcM s (TcPat s, LIE s, TcType s)
53 %************************************************************************
55 \subsection{Variables, wildcards, lazy pats, as-pats}
57 %************************************************************************
61 = tcLookupLocalValueOK "tcPat1" name `thenNF_Tc` \ id ->
62 returnTc (VarPat (TcId id), emptyLIE, idType id)
65 = tcPat pat `thenTc` \ (pat', lie, ty) ->
66 returnTc (LazyPat pat', lie, ty)
68 tcPat pat_in@(AsPatIn name pat)
69 = tcLookupLocalValueOK "tcPat2" name `thenNF_Tc` \ id ->
70 tcPat pat `thenTc` \ (pat', lie, ty) ->
71 tcAddErrCtxt (patCtxt pat_in) $
72 unifyTauTy (idType id) ty `thenTc_`
73 returnTc (AsPat (TcId id) pat', lie, ty)
76 = newTyVarTy mkTypeKind `thenNF_Tc` \ tyvar_ty ->
77 returnTc (WildPat tyvar_ty, emptyLIE, tyvar_ty)
79 tcPat (ParPatIn parend_pat)
83 %************************************************************************
85 \subsection{Explicit lists and tuples}
87 %************************************************************************
90 tcPat pat_in@(ListPatIn pats)
91 = tcPats pats `thenTc` \ (pats', lie, tys) ->
92 newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
93 tcAddErrCtxt (patCtxt pat_in) $
94 unifyTauTyList (tyvar_ty:tys) `thenTc_`
96 returnTc (ListPat tyvar_ty pats', lie, mkListTy tyvar_ty)
98 tcPat pat_in@(TuplePatIn pats)
102 tcPats pats `thenTc` \ (pats', lie, tys) ->
104 -- Make sure we record that the tuples can only contain boxed types
105 newTyVarTys arity mkBoxedTypeKind `thenNF_Tc` \ tyvar_tys ->
107 tcAddErrCtxt (patCtxt pat_in) $
108 unifyTauTyLists tyvar_tys tys `thenTc_`
110 -- possibly do the "make all tuple-pats irrefutable" test:
112 unmangled_result = TuplePat pats'
114 -- Under flag control turn a pattern (x,y,z) into ~(x,y,z)
115 -- so that we can experiment with lazy tuple-matching.
116 -- This is a pretty odd place to make the switch, but
117 -- it was easy to do.
119 possibly_mangled_result
120 = if opt_IrrefutableTuples
121 then LazyPat unmangled_result
122 else unmangled_result
124 -- ToDo: IrrefutableEverything
126 returnTc (possibly_mangled_result, lie, mkTupleTy arity tys)
129 %************************************************************************
131 \subsection{Other constructors}
133 %************************************************************************
135 Constructor patterns are a little fun:
138 typecheck the arguments
140 look up the constructor
142 specialise its type (ignore the translation this produces)
144 check that the context produced by this specialisation is empty
146 get the arguments out of the function type produced from specialising
148 unify them with the types of the patterns
150 back substitute with the type of the result of the constructor
153 ToDo: exploit new representation of constructors to make this more
157 tcPat pat_in@(ConPatIn name pats)
158 = tcPats pats `thenTc` \ (pats', lie, tys) ->
160 tcAddErrCtxt (patCtxt pat_in) $
161 matchConArgTys name tys `thenTc` \ (con_id, data_ty) ->
163 returnTc (ConPat con_id data_ty pats',
167 tcPat pat_in@(ConOpPatIn pat1 op pat2) -- & in binary-op form...
168 = tcPat pat1 `thenTc` \ (pat1', lie1, ty1) ->
169 tcPat pat2 `thenTc` \ (pat2', lie2, ty2) ->
171 tcAddErrCtxt (patCtxt pat_in) $
172 matchConArgTys op [ty1,ty2] `thenTc` \ (con_id, data_ty) ->
174 returnTc (ConOpPat pat1' con_id pat2' data_ty,
179 %************************************************************************
183 %************************************************************************
186 tcPat pat_in@(RecPatIn name rpats)
187 = tcLookupGlobalValue name `thenNF_Tc` \ con_id ->
188 tcInstId con_id `thenNF_Tc` \ (_, _, con_tau) ->
190 -- Ignore the con_theta; overloaded constructors only
191 -- behave differently when called, not when used for
193 (_, record_ty) = splitFunTy con_tau
195 -- Con is syntactically constrained to be a data constructor
196 ASSERT( maybeToBool (maybeAppDataTyCon record_ty ) )
198 mapAndUnzipTc (do_bind record_ty) rpats `thenTc` \ (rpats', lies) ->
200 returnTc (panic "tcPat:RecPatIn:avoid type errors"{-RecPat con_id record_ty rpats',
205 do_bind expected_record_ty (field_label, rhs_pat, pun_flag)
206 = tcLookupGlobalValue field_label `thenNF_Tc` \ sel_id ->
207 tcInstId sel_id `thenNF_Tc` \ (_, _, tau) ->
209 -- Record selectors all have type
210 -- forall a1..an. T a1 .. an -> tau
211 ASSERT( maybeToBool (getFunTy_maybe tau) )
213 -- Selector must have type RecordType -> FieldType
214 Just (record_ty, field_ty) = getFunTy_maybe tau
216 tcAddErrCtxt (recordLabel field_label) (
217 unifyTauTy expected_record_ty record_ty
219 tcPat rhs_pat `thenTc` \ (rhs_pat', lie, rhs_ty) ->
220 tcAddErrCtxt (recordRhs field_label rhs_pat) (
221 unifyTauTy field_ty rhs_ty
223 returnTc ((sel_id, rhs_pat', pun_flag), lie)
226 %************************************************************************
228 \subsection{Non-overloaded literals}
230 %************************************************************************
233 tcPat (LitPatIn lit@(HsChar str))
234 = returnTc (LitPat lit charTy, emptyLIE, charTy)
236 tcPat (LitPatIn lit@(HsString str))
237 = tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ sel_id ->
238 newMethod (LiteralOrigin lit)
239 (RealId sel_id) [stringTy] `thenNF_Tc` \ (lie, eq_id) ->
241 comp_op = HsApp (HsVar eq_id) (HsLitOut lit stringTy)
243 returnTc (NPat lit stringTy comp_op, lie, stringTy)
245 tcPat (LitPatIn lit@(HsIntPrim _))
246 = returnTc (LitPat lit intPrimTy, emptyLIE, intPrimTy)
247 tcPat (LitPatIn lit@(HsCharPrim _))
248 = returnTc (LitPat lit charPrimTy, emptyLIE, charPrimTy)
249 tcPat (LitPatIn lit@(HsStringPrim _))
250 = returnTc (LitPat lit addrPrimTy, emptyLIE, addrPrimTy)
251 tcPat (LitPatIn lit@(HsFloatPrim _))
252 = returnTc (LitPat lit floatPrimTy, emptyLIE, floatPrimTy)
253 tcPat (LitPatIn lit@(HsDoublePrim _))
254 = returnTc (LitPat lit doublePrimTy, emptyLIE, doublePrimTy)
257 %************************************************************************
259 \subsection{Overloaded patterns: int literals and \tr{n+k} patterns}
261 %************************************************************************
264 tcPat (LitPatIn lit@(HsInt i))
265 = newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
266 newOverloadedLit origin
267 (OverloadedIntegral i) tyvar_ty `thenNF_Tc` \ (lie1, over_lit_id) ->
269 tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ eq_sel_id ->
270 newMethod origin (RealId eq_sel_id) [tyvar_ty] `thenNF_Tc` \ (lie2, eq_id) ->
272 returnTc (NPat lit tyvar_ty (HsApp (HsVar eq_id)
273 (HsVar over_lit_id)),
277 origin = LiteralOrigin lit
279 tcPat (LitPatIn lit@(HsFrac f))
280 = newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
281 newOverloadedLit origin
282 (OverloadedFractional f) tyvar_ty `thenNF_Tc` \ (lie1, over_lit_id) ->
284 tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ eq_sel_id ->
285 newMethod origin (RealId eq_sel_id) [tyvar_ty] `thenNF_Tc` \ (lie2, eq_id) ->
287 returnTc (NPat lit tyvar_ty (HsApp (HsVar eq_id)
288 (HsVar over_lit_id)),
292 origin = LiteralOrigin lit
294 tcPat (LitPatIn lit@(HsLitLit s))
295 = error "tcPat: can't handle ``literal-literal'' patterns"
298 %************************************************************************
300 \subsection{Lists of patterns}
302 %************************************************************************
305 tcPats :: [RenamedPat] -> TcM s ([TcPat s], LIE s, [TcType s])
307 tcPats [] = returnTc ([], emptyLIE, [])
310 = tcPat pat `thenTc` \ (pat', lie, ty) ->
311 tcPats pats `thenTc` \ (pats', lie', tys) ->
313 returnTc (pat':pats', plusLIE lie lie', ty:tys)
316 @matchConArgTys@ grabs the signature of the data constructor, and
317 unifies the actual args against the expected ones.
320 matchConArgTys :: RnName -> [TcType s] -> TcM s (Id, TcType s)
322 matchConArgTys con arg_tys
323 = tcLookupGlobalValue con `thenNF_Tc` \ con_id ->
324 tcInstId con_id `thenNF_Tc` \ (_, _, con_tau) ->
325 -- Ignore the con_theta; overloaded constructors only
326 -- behave differently when called, not when used for
329 (con_args, con_result) = splitFunTy con_tau
330 con_arity = length con_args
331 no_of_args = length arg_tys
333 checkTc (con_arity == no_of_args)
334 (arityErr "Constructor" con_id con_arity no_of_args) `thenTc_`
336 unifyTauTyLists arg_tys con_args `thenTc_`
337 returnTc (con_id, con_result)
341 % =================================================
346 patCtxt pat sty = ppHang (ppStr "In the pattern:") 4 (ppr sty pat)
348 recordLabel field_label sty
349 = ppHang (ppBesides [ppStr "When matching record field", ppr sty field_label])
350 4 (ppBesides [ppStr "with its immediately enclosing constructor"])
352 recordRhs field_label pat sty
353 = ppHang (ppStr "In the record field pattern")
354 4 (ppSep [ppr sty field_label, ppStr "=", ppr sty pat])