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)
80 %************************************************************************
82 \subsection{Explicit lists and tuples}
84 %************************************************************************
87 tcPat pat_in@(ListPatIn pats)
88 = tcPats pats `thenTc` \ (pats', lie, tys) ->
89 newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
90 tcAddErrCtxt (patCtxt pat_in) $
91 unifyTauTyList (tyvar_ty:tys) `thenTc_`
93 returnTc (ListPat tyvar_ty pats', lie, mkListTy tyvar_ty)
95 tcPat pat_in@(TuplePatIn pats)
99 tcPats pats `thenTc` \ (pats', lie, tys) ->
101 -- Make sure we record that the tuples can only contain boxed types
102 newTyVarTys arity mkBoxedTypeKind `thenNF_Tc` \ tyvar_tys ->
104 tcAddErrCtxt (patCtxt pat_in) $
105 unifyTauTyLists tyvar_tys tys `thenTc_`
107 -- possibly do the "make all tuple-pats irrefutable" test:
109 unmangled_result = TuplePat pats'
111 -- Under flag control turn a pattern (x,y,z) into ~(x,y,z)
112 -- so that we can experiment with lazy tuple-matching.
113 -- This is a pretty odd place to make the switch, but
114 -- it was easy to do.
116 possibly_mangled_result
117 = if opt_IrrefutableTuples
118 then LazyPat unmangled_result
119 else unmangled_result
121 -- ToDo: IrrefutableEverything
123 returnTc (possibly_mangled_result, lie, mkTupleTy arity tys)
126 %************************************************************************
128 \subsection{Other constructors}
130 %************************************************************************
132 Constructor patterns are a little fun:
135 typecheck the arguments
137 look up the constructor
139 specialise its type (ignore the translation this produces)
141 check that the context produced by this specialisation is empty
143 get the arguments out of the function type produced from specialising
145 unify them with the types of the patterns
147 back substitute with the type of the result of the constructor
150 ToDo: exploit new representation of constructors to make this more
154 tcPat pat_in@(ConPatIn name pats)
155 = tcPats pats `thenTc` \ (pats', lie, tys) ->
157 tcAddErrCtxt (patCtxt pat_in) $
158 matchConArgTys name tys `thenTc` \ (con_id, data_ty) ->
160 returnTc (ConPat con_id data_ty pats',
164 tcPat pat_in@(ConOpPatIn pat1 op pat2) -- & in binary-op form...
165 = tcPat pat1 `thenTc` \ (pat1', lie1, ty1) ->
166 tcPat pat2 `thenTc` \ (pat2', lie2, ty2) ->
168 tcAddErrCtxt (patCtxt pat_in) $
169 matchConArgTys op [ty1,ty2] `thenTc` \ (con_id, data_ty) ->
171 returnTc (ConOpPat pat1' con_id pat2' data_ty,
176 %************************************************************************
180 %************************************************************************
183 tcPat pat_in@(RecPatIn name rpats)
184 = tcLookupGlobalValue name `thenNF_Tc` \ con_id ->
185 tcInstId con_id `thenNF_Tc` \ (_, _, con_tau) ->
187 -- Ignore the con_theta; overloaded constructors only
188 -- behave differently when called, not when used for
190 (_, record_ty) = splitFunTy con_tau
192 -- Con is syntactically constrained to be a data constructor
193 ASSERT( maybeToBool (maybeAppDataTyCon record_ty ) )
195 mapAndUnzipTc (do_bind record_ty) rpats `thenTc` \ (rpats', lies) ->
197 returnTc (panic "tcPat:RecPatIn:avoid type errors"{-RecPat con_id record_ty rpats',
202 do_bind expected_record_ty (field_label, rhs_pat, pun_flag)
203 = tcLookupGlobalValue field_label `thenNF_Tc` \ sel_id ->
204 tcInstId sel_id `thenNF_Tc` \ (_, _, tau) ->
206 -- Record selectors all have type
207 -- forall a1..an. T a1 .. an -> tau
208 ASSERT( maybeToBool (getFunTy_maybe tau) )
210 -- Selector must have type RecordType -> FieldType
211 Just (record_ty, field_ty) = getFunTy_maybe tau
213 tcAddErrCtxt (recordLabel field_label) (
214 unifyTauTy expected_record_ty record_ty
216 tcPat rhs_pat `thenTc` \ (rhs_pat', lie, rhs_ty) ->
217 tcAddErrCtxt (recordRhs field_label rhs_pat) (
218 unifyTauTy field_ty rhs_ty
220 returnTc ((sel_id, rhs_pat', pun_flag), lie)
223 %************************************************************************
225 \subsection{Non-overloaded literals}
227 %************************************************************************
230 tcPat (LitPatIn lit@(HsChar str))
231 = returnTc (LitPat lit charTy, emptyLIE, charTy)
233 tcPat (LitPatIn lit@(HsString str))
234 = tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ sel_id ->
235 newMethod (LiteralOrigin lit)
236 (RealId sel_id) [stringTy] `thenNF_Tc` \ (lie, eq_id) ->
238 comp_op = HsApp (HsVar eq_id) (HsLitOut lit stringTy)
240 returnTc (NPat lit stringTy comp_op, lie, stringTy)
242 tcPat (LitPatIn lit@(HsIntPrim _))
243 = returnTc (LitPat lit intPrimTy, emptyLIE, intPrimTy)
244 tcPat (LitPatIn lit@(HsCharPrim _))
245 = returnTc (LitPat lit charPrimTy, emptyLIE, charPrimTy)
246 tcPat (LitPatIn lit@(HsStringPrim _))
247 = returnTc (LitPat lit addrPrimTy, emptyLIE, addrPrimTy)
248 tcPat (LitPatIn lit@(HsFloatPrim _))
249 = returnTc (LitPat lit floatPrimTy, emptyLIE, floatPrimTy)
250 tcPat (LitPatIn lit@(HsDoublePrim _))
251 = returnTc (LitPat lit doublePrimTy, emptyLIE, doublePrimTy)
254 %************************************************************************
256 \subsection{Overloaded patterns: int literals and \tr{n+k} patterns}
258 %************************************************************************
261 tcPat (LitPatIn lit@(HsInt i))
262 = newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
263 newOverloadedLit origin
264 (OverloadedIntegral i) tyvar_ty `thenNF_Tc` \ (lie1, over_lit_id) ->
266 tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ eq_sel_id ->
267 newMethod origin (RealId eq_sel_id) [tyvar_ty] `thenNF_Tc` \ (lie2, eq_id) ->
269 returnTc (NPat lit tyvar_ty (HsApp (HsVar eq_id)
270 (HsVar over_lit_id)),
274 origin = LiteralOrigin lit
276 tcPat (LitPatIn lit@(HsFrac f))
277 = newTyVarTy mkBoxedTypeKind `thenNF_Tc` \ tyvar_ty ->
278 newOverloadedLit origin
279 (OverloadedFractional f) tyvar_ty `thenNF_Tc` \ (lie1, over_lit_id) ->
281 tcLookupGlobalValueByKey eqClassOpKey `thenNF_Tc` \ eq_sel_id ->
282 newMethod origin (RealId eq_sel_id) [tyvar_ty] `thenNF_Tc` \ (lie2, eq_id) ->
284 returnTc (NPat lit tyvar_ty (HsApp (HsVar eq_id)
285 (HsVar over_lit_id)),
289 origin = LiteralOrigin lit
291 tcPat (LitPatIn lit@(HsLitLit s))
292 = error "tcPat: can't handle ``literal-literal'' patterns"
295 %************************************************************************
297 \subsection{Lists of patterns}
299 %************************************************************************
302 tcPats :: [RenamedPat] -> TcM s ([TcPat s], LIE s, [TcType s])
304 tcPats [] = returnTc ([], emptyLIE, [])
307 = tcPat pat `thenTc` \ (pat', lie, ty) ->
308 tcPats pats `thenTc` \ (pats', lie', tys) ->
310 returnTc (pat':pats', plusLIE lie lie', ty:tys)
313 @matchConArgTys@ grabs the signature of the data constructor, and
314 unifies the actual args against the expected ones.
317 matchConArgTys :: RnName -> [TcType s] -> TcM s (Id, TcType s)
319 matchConArgTys con arg_tys
320 = tcLookupGlobalValue con `thenNF_Tc` \ con_id ->
321 tcInstId con_id `thenNF_Tc` \ (_, _, con_tau) ->
322 -- Ignore the con_theta; overloaded constructors only
323 -- behave differently when called, not when used for
326 (con_args, con_result) = splitFunTy con_tau
327 con_arity = length con_args
328 no_of_args = length arg_tys
330 checkTc (con_arity == no_of_args)
331 (arityErr "Constructor" con_id con_arity no_of_args) `thenTc_`
333 unifyTauTyLists arg_tys con_args `thenTc_`
334 returnTc (con_id, con_result)
338 % =================================================
343 patCtxt pat sty = ppHang (ppStr "In the pattern:") 4 (ppr sty pat)
345 recordLabel field_label sty
346 = ppHang (ppBesides [ppStr "When matching record field", ppr sty field_label])
347 4 (ppBesides [ppStr "with its immediately enclosing constructor"])
349 recordRhs field_label pat sty
350 = ppHang (ppStr "In the record field pattern")
351 4 (ppSep [ppr sty field_label, ppStr "=", ppr sty pat])