Imported ids without signatures are still inferred.
[ghc.git] / compiler / typecheck / TcForeign.hs
1 {-
2 (c) The University of Glasgow 2006
3 (c) The AQUA Project, Glasgow University, 1998
4
5 \section[TcForeign]{Typechecking \tr{foreign} declarations}
6
7 A foreign declaration is used to either give an externally
8 implemented function a Haskell type (and calling interface) or
9 give a Haskell function an external calling interface. Either way,
10 the range of argument and result types these functions can accommodate
11 is restricted to what the outside world understands (read C), and this
12 module checks to see if a foreign declaration has got a legal type.
13 -}
14
15 {-# LANGUAGE CPP #-}
16
17 module TcForeign
18 ( tcForeignImports
19 , tcForeignExports
20
21 -- Low-level exports for hooks
22 , isForeignImport, isForeignExport
23 , tcFImport, tcFExport
24 , tcForeignImports'
25 , tcCheckFIType, checkCTarget, checkForeignArgs, checkForeignRes
26 , normaliseFfiType
27 , nonIOok, mustBeIO
28 , checkSafe, noCheckSafe
29 , tcForeignExports'
30 , tcCheckFEType
31 ) where
32
33 #include "HsVersions.h"
34
35 import HsSyn
36
37 import TcRnMonad
38 import TcHsType
39 import TcExpr
40 import TcEnv
41
42 import FamInst
43 import FamInstEnv
44 import Coercion
45 import Type
46 import TypeRep
47 import ForeignCall
48 import ErrUtils
49 import Id
50 import Name
51 import RdrName
52 import DataCon
53 import TyCon
54 import TcType
55 import PrelNames
56 import DynFlags
57 import Outputable
58 import Platform
59 import SrcLoc
60 import Bag
61 import FastString
62 import Hooks
63
64 import Control.Monad
65
66 -- Defines a binding
67 isForeignImport :: LForeignDecl name -> Bool
68 isForeignImport (L _ (ForeignImport _ _ _ _)) = True
69 isForeignImport _ = False
70
71 -- Exports a binding
72 isForeignExport :: LForeignDecl name -> Bool
73 isForeignExport (L _ (ForeignExport _ _ _ _)) = True
74 isForeignExport _ = False
75
76 {-
77 Note [Don't recur in normaliseFfiType']
78 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79 normaliseFfiType' is the workhorse for normalising a type used in a foreign
80 declaration. If we have
81
82 newtype Age = MkAge Int
83
84 we want to see that Age -> IO () is the same as Int -> IO (). But, we don't
85 need to recur on any type parameters, because no paramaterized types (with
86 interesting parameters) are marshalable! The full list of marshalable types
87 is in the body of boxedMarshalableTyCon in TcType. The only members of that
88 list not at kind * are Ptr, FunPtr, and StablePtr, all of which get marshaled
89 the same way regardless of type parameter. So, no need to recur into
90 parameters.
91
92 Similarly, we don't need to look in AppTy's, because nothing headed by
93 an AppTy will be marshalable.
94
95 Note [FFI type roles]
96 ~~~~~~~~~~~~~~~~~~~~~
97 The 'go' helper function within normaliseFfiType' always produces
98 representational coercions. But, in the "children_only" case, we need to
99 use these coercions in a TyConAppCo. Accordingly, the roles on the coercions
100 must be twiddled to match the expectation of the enclosing TyCon. However,
101 we cannot easily go from an R coercion to an N one, so we forbid N roles
102 on FFI type constructors. Currently, only two such type constructors exist:
103 IO and FunPtr. Thus, this is not an onerous burden.
104
105 If we ever want to lift this restriction, we would need to make 'go' take
106 the target role as a parameter. This wouldn't be hard, but it's a complication
107 not yet necessary and so is not yet implemented.
108 -}
109
110 -- normaliseFfiType takes the type from an FFI declaration, and
111 -- evaluates any type synonyms, type functions, and newtypes. However,
112 -- we are only allowed to look through newtypes if the constructor is
113 -- in scope. We return a bag of all the newtype constructors thus found.
114 -- Always returns a Representational coercion
115 normaliseFfiType :: Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
116 normaliseFfiType ty
117 = do fam_envs <- tcGetFamInstEnvs
118 normaliseFfiType' fam_envs ty
119
120 normaliseFfiType' :: FamInstEnvs -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
121 normaliseFfiType' env ty0 = go initRecTc ty0
122 where
123 go :: RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
124 go rec_nts ty | Just ty' <- coreView ty -- Expand synonyms
125 = go rec_nts ty'
126
127 go rec_nts ty@(TyConApp tc tys)
128 -- We don't want to look through the IO newtype, even if it is
129 -- in scope, so we have a special case for it:
130 | tc_key `elem` [ioTyConKey, funPtrTyConKey]
131 -- These *must not* have nominal roles on their parameters!
132 -- See Note [FFI type roles]
133 = children_only
134
135 | isNewTyCon tc -- Expand newtypes
136 , Just rec_nts' <- checkRecTc rec_nts tc
137 -- See Note [Expanding newtypes] in TyCon.hs
138 -- We can't just use isRecursiveTyCon; sometimes recursion is ok:
139 -- newtype T = T (Ptr T)
140 -- Here, we don't reject the type for being recursive.
141 -- If this is a recursive newtype then it will normally
142 -- be rejected later as not being a valid FFI type.
143 = do { rdr_env <- getGlobalRdrEnv
144 ; case checkNewtypeFFI rdr_env tc of
145 Nothing -> nothing
146 Just gre -> do { (co', ty', gres) <- go rec_nts' nt_rhs
147 ; return (mkTransCo nt_co co', ty', gre `consBag` gres) } }
148
149 | isFamilyTyCon tc -- Expand open tycons
150 , (co, ty) <- normaliseTcApp env Representational tc tys
151 , not (isReflCo co)
152 = do (co', ty', gres) <- go rec_nts ty
153 return (mkTransCo co co', ty', gres)
154
155 | otherwise
156 = nothing -- see Note [Don't recur in normaliseFfiType']
157 where
158 tc_key = getUnique tc
159 children_only
160 = do xs <- mapM (go rec_nts) tys
161 let (cos, tys', gres) = unzip3 xs
162 -- the (repeat Representational) is because 'go' always
163 -- returns R coercions
164 cos' = zipWith3 downgradeRole (tyConRoles tc)
165 (repeat Representational) cos
166 return ( mkTyConAppCo Representational tc cos'
167 , mkTyConApp tc tys', unionManyBags gres)
168 nt_co = mkUnbranchedAxInstCo Representational (newTyConCo tc) tys
169 nt_rhs = newTyConInstRhs tc tys
170 nothing = return (Refl Representational ty, ty, emptyBag)
171
172 go rec_nts (FunTy ty1 ty2)
173 = do (coi1,nty1,gres1) <- go rec_nts ty1
174 (coi2,nty2,gres2) <- go rec_nts ty2
175 return (mkFunCo Representational coi1 coi2, mkFunTy nty1 nty2, gres1 `unionBags` gres2)
176
177 go rec_nts (ForAllTy tyvar ty1)
178 = do (coi,nty1,gres1) <- go rec_nts ty1
179 return (mkForAllCo tyvar coi, ForAllTy tyvar nty1, gres1)
180
181 go _ ty@(TyVarTy {}) = return (Refl Representational ty, ty, emptyBag)
182 go _ ty@(LitTy {}) = return (Refl Representational ty, ty, emptyBag)
183 go _ ty@(AppTy {}) = return (Refl Representational ty, ty, emptyBag)
184 -- See Note [Don't recur in normaliseFfiType']
185
186 checkNewtypeFFI :: GlobalRdrEnv -> TyCon -> Maybe GlobalRdrElt
187 checkNewtypeFFI rdr_env tc
188 | Just con <- tyConSingleDataCon_maybe tc
189 , [gre] <- lookupGRE_Name rdr_env (dataConName con)
190 = Just gre -- See Note [Newtype constructor usage in foreign declarations]
191 | otherwise
192 = Nothing
193
194 {-
195 Note [Newtype constructor usage in foreign declarations]
196 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
197 GHC automatically "unwraps" newtype constructors in foreign import/export
198 declarations. In effect that means that a newtype data constructor is
199 used even though it is not mentioned expclitly in the source, so we don't
200 want to report it as "defined but not used" or "imported but not used".
201 eg newtype D = MkD Int
202 foreign import foo :: D -> IO ()
203 Here 'MkD' us used. See Trac #7408.
204
205 GHC also expands type functions during this process, so it's not enough
206 just to look at the free variables of the declaration.
207 eg type instance F Bool = D
208 foreign import bar :: F Bool -> IO ()
209 Here again 'MkD' is used.
210
211 So we really have wait until the type checker to decide what is used.
212 That's why tcForeignImports and tecForeignExports return a (Bag GRE)
213 for the newtype constructors they see. Then TcRnDriver can add them
214 to the module's usages.
215
216
217 ************************************************************************
218 * *
219 \subsection{Imports}
220 * *
221 ************************************************************************
222 -}
223
224 tcForeignImports :: [LForeignDecl Name] -> TcM ([Id], [LForeignDecl Id], Bag GlobalRdrElt)
225 tcForeignImports decls
226 = getHooked tcForeignImportsHook tcForeignImports' >>= ($ decls)
227
228 tcForeignImports' :: [LForeignDecl Name] -> TcM ([Id], [LForeignDecl Id], Bag GlobalRdrElt)
229 -- For the (Bag GlobalRdrElt) result,
230 -- see Note [Newtype constructor usage in foreign declarations]
231 tcForeignImports' decls
232 = do { (ids, decls, gres) <- mapAndUnzip3M tcFImport $
233 filter isForeignImport decls
234 ; return (ids, decls, unionManyBags gres) }
235
236 tcFImport :: LForeignDecl Name -> TcM (Id, LForeignDecl Id, Bag GlobalRdrElt)
237 tcFImport (L dloc fo@(ForeignImport (L nloc nm) hs_ty _ imp_decl))
238 = setSrcSpan dloc $ addErrCtxt (foreignDeclCtxt fo) $
239 do { sig_ty <- tcHsSigType (ForSigCtxt nm) hs_ty
240 ; (norm_co, norm_sig_ty, gres) <- normaliseFfiType sig_ty
241 ; let
242 -- Drop the foralls before inspecting the
243 -- structure of the foreign type.
244 (_, t_ty) = tcSplitForAllTys norm_sig_ty
245 (arg_tys, res_ty) = tcSplitFunTys t_ty
246 id = mkLocalId nm sig_ty HasSigId
247 -- Use a LocalId to obey the invariant that locally-defined
248 -- things are LocalIds. However, it does not need zonking,
249 -- (so TcHsSyn.zonkForeignExports ignores it).
250
251 ; imp_decl' <- tcCheckFIType arg_tys res_ty imp_decl
252 -- Can't use sig_ty here because sig_ty :: Type and
253 -- we need HsType Id hence the undefined
254 ; let fi_decl = ForeignImport (L nloc id) undefined (mkSymCo norm_co) imp_decl'
255 ; return (id, L dloc fi_decl, gres) }
256 tcFImport d = pprPanic "tcFImport" (ppr d)
257
258 -- ------------ Checking types for foreign import ----------------------
259
260 tcCheckFIType :: [Type] -> Type -> ForeignImport -> TcM ForeignImport
261
262 tcCheckFIType arg_tys res_ty (CImport (L lc cconv) safety mh l@(CLabel _) src)
263 -- Foreign import label
264 = do checkCg checkCOrAsmOrLlvmOrInterp
265 -- NB check res_ty not sig_ty!
266 -- In case sig_ty is (forall a. ForeignPtr a)
267 check (isFFILabelTy (mkFunTys arg_tys res_ty)) (illegalForeignTyErr Outputable.empty)
268 cconv' <- checkCConv cconv
269 return (CImport (L lc cconv') safety mh l src)
270
271 tcCheckFIType arg_tys res_ty (CImport (L lc cconv) safety mh CWrapper src) = do
272 -- Foreign wrapper (former f.e.d.)
273 -- The type must be of the form ft -> IO (FunPtr ft), where ft is a valid
274 -- foreign type. For legacy reasons ft -> IO (Ptr ft) is accepted, too.
275 -- The use of the latter form is DEPRECATED, though.
276 checkCg checkCOrAsmOrLlvmOrInterp
277 cconv' <- checkCConv cconv
278 case arg_tys of
279 [arg1_ty] -> do checkForeignArgs isFFIExternalTy arg1_tys
280 checkForeignRes nonIOok checkSafe isFFIExportResultTy res1_ty
281 checkForeignRes mustBeIO checkSafe (isFFIDynTy arg1_ty) res_ty
282 where
283 (arg1_tys, res1_ty) = tcSplitFunTys arg1_ty
284 _ -> addErrTc (illegalForeignTyErr Outputable.empty (ptext (sLit "One argument expected")))
285 return (CImport (L lc cconv') safety mh CWrapper src)
286
287 tcCheckFIType arg_tys res_ty idecl@(CImport (L lc cconv) (L ls safety) mh
288 (CFunction target) src)
289 | isDynamicTarget target = do -- Foreign import dynamic
290 checkCg checkCOrAsmOrLlvmOrInterp
291 cconv' <- checkCConv cconv
292 case arg_tys of -- The first arg must be Ptr or FunPtr
293 [] ->
294 addErrTc (illegalForeignTyErr Outputable.empty (ptext (sLit "At least one argument expected")))
295 (arg1_ty:arg_tys) -> do
296 dflags <- getDynFlags
297 let curried_res_ty = foldr FunTy res_ty arg_tys
298 check (isFFIDynTy curried_res_ty arg1_ty)
299 (illegalForeignTyErr argument)
300 checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys
301 checkForeignRes nonIOok checkSafe (isFFIImportResultTy dflags) res_ty
302 return $ CImport (L lc cconv') (L ls safety) mh (CFunction target) src
303 | cconv == PrimCallConv = do
304 dflags <- getDynFlags
305 checkTc (xopt Opt_GHCForeignImportPrim dflags)
306 (text "Use GHCForeignImportPrim to allow `foreign import prim'.")
307 checkCg checkCOrAsmOrLlvmOrInterp
308 checkCTarget target
309 checkTc (playSafe safety)
310 (text "The safe/unsafe annotation should not be used with `foreign import prim'.")
311 checkForeignArgs (isFFIPrimArgumentTy dflags) arg_tys
312 -- prim import result is more liberal, allows (#,,#)
313 checkForeignRes nonIOok checkSafe (isFFIPrimResultTy dflags) res_ty
314 return idecl
315 | otherwise = do -- Normal foreign import
316 checkCg checkCOrAsmOrLlvmOrInterp
317 cconv' <- checkCConv cconv
318 checkCTarget target
319 dflags <- getDynFlags
320 checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys
321 checkForeignRes nonIOok checkSafe (isFFIImportResultTy dflags) res_ty
322 checkMissingAmpersand dflags arg_tys res_ty
323 case target of
324 StaticTarget _ _ _ False
325 | not (null arg_tys) ->
326 addErrTc (text "`value' imports cannot have function types")
327 _ -> return ()
328 return $ CImport (L lc cconv') (L ls safety) mh (CFunction target) src
329
330
331 -- This makes a convenient place to check
332 -- that the C identifier is valid for C
333 checkCTarget :: CCallTarget -> TcM ()
334 checkCTarget (StaticTarget _ str _ _) = do
335 checkCg checkCOrAsmOrLlvmOrInterp
336 checkTc (isCLabelString str) (badCName str)
337
338 checkCTarget DynamicTarget = panic "checkCTarget DynamicTarget"
339
340
341 checkMissingAmpersand :: DynFlags -> [Type] -> Type -> TcM ()
342 checkMissingAmpersand dflags arg_tys res_ty
343 | null arg_tys && isFunPtrTy res_ty &&
344 wopt Opt_WarnDodgyForeignImports dflags
345 = addWarn (ptext (sLit "possible missing & in foreign import of FunPtr"))
346 | otherwise
347 = return ()
348
349 {-
350 ************************************************************************
351 * *
352 \subsection{Exports}
353 * *
354 ************************************************************************
355 -}
356
357 tcForeignExports :: [LForeignDecl Name]
358 -> TcM (LHsBinds TcId, [LForeignDecl TcId], Bag GlobalRdrElt)
359 tcForeignExports decls =
360 getHooked tcForeignExportsHook tcForeignExports' >>= ($ decls)
361
362 tcForeignExports' :: [LForeignDecl Name]
363 -> TcM (LHsBinds TcId, [LForeignDecl TcId], Bag GlobalRdrElt)
364 -- For the (Bag GlobalRdrElt) result,
365 -- see Note [Newtype constructor usage in foreign declarations]
366 tcForeignExports' decls
367 = foldlM combine (emptyLHsBinds, [], emptyBag) (filter isForeignExport decls)
368 where
369 combine (binds, fs, gres1) (L loc fe) = do
370 (b, f, gres2) <- setSrcSpan loc (tcFExport fe)
371 return (b `consBag` binds, L loc f : fs, gres1 `unionBags` gres2)
372
373 tcFExport :: ForeignDecl Name -> TcM (LHsBind Id, ForeignDecl Id, Bag GlobalRdrElt)
374 tcFExport fo@(ForeignExport (L loc nm) hs_ty _ spec)
375 = addErrCtxt (foreignDeclCtxt fo) $ do
376
377 sig_ty <- tcHsSigType (ForSigCtxt nm) hs_ty
378 rhs <- tcPolyExpr (nlHsVar nm) sig_ty
379
380 (norm_co, norm_sig_ty, gres) <- normaliseFfiType sig_ty
381
382 spec' <- tcCheckFEType norm_sig_ty spec
383
384 -- we're exporting a function, but at a type possibly more
385 -- constrained than its declared/inferred type. Hence the need
386 -- to create a local binding which will call the exported function
387 -- at a particular type (and, maybe, overloading).
388
389
390 -- We need to give a name to the new top-level binding that
391 -- is *stable* (i.e. the compiler won't change it later),
392 -- because this name will be referred to by the C code stub.
393 id <- mkStableIdFromName nm sig_ty loc mkForeignExportOcc
394 return (mkVarBind id rhs, ForeignExport (L loc id) undefined norm_co spec', gres)
395 tcFExport d = pprPanic "tcFExport" (ppr d)
396
397 -- ------------ Checking argument types for foreign export ----------------------
398
399 tcCheckFEType :: Type -> ForeignExport -> TcM ForeignExport
400 tcCheckFEType sig_ty (CExport (L l (CExportStatic esrc str cconv)) src) = do
401 checkCg checkCOrAsmOrLlvm
402 checkTc (isCLabelString str) (badCName str)
403 cconv' <- checkCConv cconv
404 checkForeignArgs isFFIExternalTy arg_tys
405 checkForeignRes nonIOok noCheckSafe isFFIExportResultTy res_ty
406 return (CExport (L l (CExportStatic esrc str cconv')) src)
407 where
408 -- Drop the foralls before inspecting n
409 -- the structure of the foreign type.
410 (_, t_ty) = tcSplitForAllTys sig_ty
411 (arg_tys, res_ty) = tcSplitFunTys t_ty
412
413 {-
414 ************************************************************************
415 * *
416 \subsection{Miscellaneous}
417 * *
418 ************************************************************************
419 -}
420
421 ------------ Checking argument types for foreign import ----------------------
422 checkForeignArgs :: (Type -> Validity) -> [Type] -> TcM ()
423 checkForeignArgs pred tys = mapM_ go tys
424 where
425 go ty = check (pred ty) (illegalForeignTyErr argument)
426
427 ------------ Checking result types for foreign calls ----------------------
428 -- | Check that the type has the form
429 -- (IO t) or (t) , and that t satisfies the given predicate.
430 -- When calling this function, any newtype wrappers (should) have been
431 -- already dealt with by normaliseFfiType.
432 --
433 -- We also check that the Safe Haskell condition of FFI imports having
434 -- results in the IO monad holds.
435 --
436 checkForeignRes :: Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
437 checkForeignRes non_io_result_ok check_safe pred_res_ty ty
438 | Just (_, res_ty) <- tcSplitIOType_maybe ty
439 = -- Got an IO result type, that's always fine!
440 check (pred_res_ty res_ty) (illegalForeignTyErr result)
441
442 -- Case for non-IO result type with FFI Import
443 | not non_io_result_ok
444 = addErrTc $ illegalForeignTyErr result (ptext (sLit "IO result type expected"))
445
446 | otherwise
447 = do { dflags <- getDynFlags
448 ; case pred_res_ty ty of
449 -- Handle normal typecheck fail, we want to handle this first and
450 -- only report safe haskell errors if the normal type check is OK.
451 NotValid msg -> addErrTc $ illegalForeignTyErr result msg
452
453 -- handle safe infer fail
454 _ | check_safe && safeInferOn dflags
455 -> recordUnsafeInfer emptyBag
456
457 -- handle safe language typecheck fail
458 _ | check_safe && safeLanguageOn dflags
459 -> addErrTc (illegalForeignTyErr result safeHsErr)
460
461 -- sucess! non-IO return is fine
462 _ -> return () }
463 where
464 safeHsErr = ptext $ sLit "Safe Haskell is on, all FFI imports must be in the IO monad"
465
466 nonIOok, mustBeIO :: Bool
467 nonIOok = True
468 mustBeIO = False
469
470 checkSafe, noCheckSafe :: Bool
471 checkSafe = True
472 noCheckSafe = False
473
474 -- Checking a supported backend is in use
475
476 checkCOrAsmOrLlvm :: HscTarget -> Validity
477 checkCOrAsmOrLlvm HscC = IsValid
478 checkCOrAsmOrLlvm HscAsm = IsValid
479 checkCOrAsmOrLlvm HscLlvm = IsValid
480 checkCOrAsmOrLlvm _
481 = NotValid (text "requires unregisterised, llvm (-fllvm) or native code generation (-fasm)")
482
483 checkCOrAsmOrLlvmOrInterp :: HscTarget -> Validity
484 checkCOrAsmOrLlvmOrInterp HscC = IsValid
485 checkCOrAsmOrLlvmOrInterp HscAsm = IsValid
486 checkCOrAsmOrLlvmOrInterp HscLlvm = IsValid
487 checkCOrAsmOrLlvmOrInterp HscInterpreted = IsValid
488 checkCOrAsmOrLlvmOrInterp _
489 = NotValid (text "requires interpreted, unregisterised, llvm or native code generation")
490
491 checkCg :: (HscTarget -> Validity) -> TcM ()
492 checkCg check = do
493 dflags <- getDynFlags
494 let target = hscTarget dflags
495 case target of
496 HscNothing -> return ()
497 _ ->
498 case check target of
499 IsValid -> return ()
500 NotValid err -> addErrTc (text "Illegal foreign declaration:" <+> err)
501
502 -- Calling conventions
503
504 checkCConv :: CCallConv -> TcM CCallConv
505 checkCConv CCallConv = return CCallConv
506 checkCConv CApiConv = return CApiConv
507 checkCConv StdCallConv = do dflags <- getDynFlags
508 let platform = targetPlatform dflags
509 if platformArch platform == ArchX86
510 then return StdCallConv
511 else do -- This is a warning, not an error. see #3336
512 when (wopt Opt_WarnUnsupportedCallingConventions dflags) $
513 addWarnTc (text "the 'stdcall' calling convention is unsupported on this platform," $$ text "treating as ccall")
514 return CCallConv
515 checkCConv PrimCallConv = do addErrTc (text "The `prim' calling convention can only be used with `foreign import'")
516 return PrimCallConv
517 checkCConv JavaScriptCallConv = do dflags <- getDynFlags
518 if platformArch (targetPlatform dflags) == ArchJavaScript
519 then return JavaScriptCallConv
520 else do addErrTc (text "The `javascript' calling convention is unsupported on this platform")
521 return JavaScriptCallConv
522
523 -- Warnings
524
525 check :: Validity -> (MsgDoc -> MsgDoc) -> TcM ()
526 check IsValid _ = return ()
527 check (NotValid doc) err_fn = addErrTc (err_fn doc)
528
529 illegalForeignTyErr :: SDoc -> SDoc -> SDoc
530 illegalForeignTyErr arg_or_res extra
531 = hang msg 2 extra
532 where
533 msg = hsep [ ptext (sLit "Unacceptable"), arg_or_res
534 , ptext (sLit "type in foreign declaration:")]
535
536 -- Used for 'arg_or_res' argument to illegalForeignTyErr
537 argument, result :: SDoc
538 argument = text "argument"
539 result = text "result"
540
541 badCName :: CLabelString -> MsgDoc
542 badCName target
543 = sep [quotes (ppr target) <+> ptext (sLit "is not a valid C identifier")]
544
545 foreignDeclCtxt :: ForeignDecl Name -> SDoc
546 foreignDeclCtxt fo
547 = hang (ptext (sLit "When checking declaration:"))
548 2 (ppr fo)