\section[TcBinds]{TcBinds}
\begin{code}
-module TcBinds ( tcBindsAndThen, tcTopBinds,
+module TcBinds ( tcBindsAndThen, tcTopBinds, tcMonoBinds,
tcSpecSigs, tcBindWithSigs ) where
#include "HsVersions.h"
import {-# SOURCE #-} TcMatches ( tcGRHSs, tcMatchesFun )
import {-# SOURCE #-} TcExpr ( tcExpr )
-import CmdLineOpts ( opt_NoMonomorphismRestriction )
+import CmdLineOpts ( DynFlag(Opt_NoMonomorphismRestriction) )
import HsSyn ( HsExpr(..), HsBinds(..), MonoBinds(..), Sig(..),
Match(..), HsMatchContext(..),
collectMonoBinders, andMonoBinds,
collectSigTysFromMonoBinds
)
-import RnHsSyn ( RenamedHsBinds, RenamedSig, RenamedMonoBinds )
+import RnHsSyn ( RenamedHsBinds, RenamedSig, RenamedMonoBinds,
+ RenamedTyClDecl )
import TcHsSyn ( TcMonoBinds, TcId, zonkId, mkHsLet )
import TcMonad
import Inst ( LIE, emptyLIE, mkLIE, plusLIE, InstOrigin(..),
newDicts, instToId
)
-import TcEnv ( tcExtendLocalValEnv, newLocalName )
-import TcUnify ( unifyTauTyLists, checkSigTyVars, sigCtxt )
+import TcEnv ( tcExtendLocalValEnv, tcExtendLocalValEnv2, newLocalName )
+import TcUnify ( unifyTauTyLists, checkSigTyVarsWrt, sigCtxt )
import TcSimplify ( tcSimplifyInfer, tcSimplifyInferCheck, tcSimplifyRestricted, tcSimplifyToDicts )
-import TcMonoType ( tcHsSigType, UserTypeCtxt(..),
- TcSigInfo(..), tcTySig, maybeSig, tcAddScopedTyVars
+import TcMonoType ( tcHsSigType, UserTypeCtxt(..), TcSigInfo(..),
+ tcTySig, maybeSig, tcSigPolyId, tcSigMonoId, tcAddScopedTyVars
)
import TcPat ( tcPat, tcSubPat, tcMonoPatBndr )
import TcSimplify ( bindInstsOfLocalFuns )
import TcMType ( newTyVar, newTyVarTy, newHoleTyVarTy,
- zonkTcTyVarToTyVar
+ zonkTcTyVarToTyVar, readHoleResult
)
import TcType ( mkTyVarTy, mkForAllTys, mkFunTys, tyVarsOfType,
mkPredTy, mkForAllTy, isUnLiftedType,
sigs is_rec `thenTc` \ (poly_binds, poly_lie, poly_ids) ->
-- Extend the environment to bind the new polymorphic Ids
- tcExtendLocalValEnv [(idName poly_id, poly_id) | poly_id <- poly_ids] $
+ tcExtendLocalValEnv poly_ids $
-- Build bindings and IdInfos corresponding to user pragmas
tcSpecSigs sigs `thenTc` \ (prag_binds, prag_lie) ->
binder_names = collectMonoBinders mbind
poly_ids = map mk_dummy binder_names
mk_dummy name = case maybeSig tc_ty_sigs name of
- Just (TySigInfo _ poly_id _ _ _ _ _ _) -> poly_id -- Signature
- Nothing -> mkLocalId name forall_a_a -- No signature
+ Just sig -> tcSigPolyId sig -- Signature
+ Nothing -> mkLocalId name forall_a_a -- No signature
in
returnTc (EmptyMonoBinds, emptyLIE, poly_ids)
) $
mapNF_Tc zonkId dict_ids `thenNF_Tc` \ zonked_dict_ids ->
mapNF_Tc zonkId mono_ids `thenNF_Tc` \ zonked_mono_ids ->
- -- CHECK FOR BOGUS UNLIFTED BINDINGS
- checkUnliftedBinds top_lvl is_rec real_tyvars_to_gen mbind zonked_mono_ids `thenTc_`
-
-- BUILD THE POLYMORPHIC RESULT IDs
let
exports = zipWith mk_export binder_names zonked_mono_ids
+ poly_ids = [poly_id | (_, poly_id, _) <- exports]
dict_tys = map idType zonked_dict_ids
inlines = mkNameSet [name | InlineSig True name _ loc <- inline_sigs]
where
(tyvars, poly_id) =
case maybeSig tc_ty_sigs binder_name of
- Just (TySigInfo _ sig_poly_id sig_tyvars _ _ _ _ _) ->
+ Just (TySigInfo sig_poly_id sig_tyvars _ _ _ _ _) ->
(sig_tyvars, sig_poly_id)
Nothing -> (real_tyvars_to_gen, new_poly_id)
in
traceTc (text "binding:" <+> ppr ((zonked_dict_ids, dict_binds),
- exports, [idType poly_id | (_, poly_id, _) <- exports])) `thenTc_`
+ exports, map idType poly_ids)) `thenTc_`
+
+ -- Check for an unlifted, non-overloaded group
+ -- In that case we must make extra checks
+ if any (isUnLiftedType . idType) zonked_mono_ids && null zonked_dict_ids
+ then -- Some bindings are unlifted
+ checkUnliftedBinds top_lvl is_rec real_tyvars_to_gen mbind `thenTc_`
+
+ returnTc (
+ AbsBinds [] [] exports inlines mbind',
+ lie_req, -- Do not generate even any x=y bindings
+ poly_ids
+ )
- -- BUILD RESULTS
+ else -- The normal case
returnTc (
AbsBinds real_tyvars_to_gen
zonked_dict_ids
exports
inlines
(dict_binds `andMonoBinds` mbind'),
- lie_free,
- [poly_id | (_, poly_id, _) <- exports]
+ lie_free, poly_ids
)
attachNoInlinePrag no_inlines bndr
Just prag -> bndr `setInlinePragma` prag
Nothing -> bndr
-checkUnliftedBinds top_lvl is_rec real_tyvars_to_gen mbind zonked_mono_ids
+-- Check that non-overloaded unlifted bindings are
+-- a) non-recursive,
+-- b) not top level,
+-- c) non-polymorphic
+-- d) not a multiple-binding group (more or less implied by (a))
+
+checkUnliftedBinds top_lvl is_rec real_tyvars_to_gen mbind
= ASSERT( not (any ((eqKind unliftedTypeKind) . tyVarKind) real_tyvars_to_gen) )
-- The instCantBeGeneralised stuff in tcSimplify should have
-- already raised an error if we're trying to generalise an
-- because we have more precise origin information.
-- That's why we just use an ASSERT here.
- -- Check that pattern-bound variables are not unlifted
- (if or [ (idName id `elem` pat_binders) && isUnLiftedType (idType id)
- | id <- zonked_mono_ids ] then
- addErrTc (unliftedBindErr "Pattern" mbind)
- else
- returnTc ()
- ) `thenTc_`
-
- -- Unlifted bindings must be non-recursive,
- -- not top level, non-polymorphic, and not pattern bound
- if any (isUnLiftedType . idType) zonked_mono_ids then
- checkTc (isNotTopLevel top_lvl)
- (unliftedBindErr "Top-level" mbind) `thenTc_`
- checkTc (isNonRec is_rec)
- (unliftedBindErr "Recursive" mbind) `thenTc_`
- checkTc (null real_tyvars_to_gen)
- (unliftedBindErr "Polymorphic" mbind)
- else
- returnTc ()
+ checkTc (isNotTopLevel top_lvl)
+ (unliftedBindErr "Top-level" mbind) `thenTc_`
+ checkTc (isNonRec is_rec)
+ (unliftedBindErr "Recursive" mbind) `thenTc_`
+ checkTc (single_bind mbind)
+ (unliftedBindErr "Multiple" mbind) `thenTc_`
+ checkTc (null real_tyvars_to_gen)
+ (unliftedBindErr "Polymorphic" mbind)
where
- pat_binders :: [Name]
- pat_binders = collectMonoBinders (justPatBindings mbind EmptyMonoBinds)
-
- justPatBindings bind@(PatMonoBind _ _ _) binds = bind `andMonoBinds` binds
- justPatBindings (AndMonoBinds b1 b2) binds =
- justPatBindings b1 (justPatBindings b2 binds)
- justPatBindings other_bind binds = binds
+ single_bind (PatMonoBind _ _ _) = True
+ single_bind (FunMonoBind _ _ _ _) = True
+ single_bind other = False
\end{code}
%************************************************************************
\begin{code}
-generalise binder_names mbind tau_tvs lie_req sigs
- | not is_unrestricted -- RESTRICTED CASE
- = -- Check signature contexts are empty
+generalise binder_names mbind tau_tvs lie_req sigs =
+
+ -- check for -fno-monomorphism-restriction
+ doptsTc Opt_NoMonomorphismRestriction `thenTc` \ no_MR ->
+ let is_unrestricted | no_MR = True
+ | otherwise = isUnRestrictedGroup tysig_names mbind
+ in
+
+ if not is_unrestricted then -- RESTRICTED CASE
+ -- Check signature contexts are empty
checkTc (all is_mono_sig sigs)
(restrictedBindCtxtErr binder_names) `thenTc_`
returnTc (qtvs, lie_free, binds, [])
- | null sigs -- UNRESTRICTED CASE, NO TYPE SIGS
- = tcSimplifyInfer doc tau_tvs lie_req
+ else if null sigs then -- UNRESTRICTED CASE, NO TYPE SIGS
+ tcSimplifyInfer doc tau_tvs lie_req
- | otherwise -- UNRESTRICTED CASE, WITH TYPE SIGS
- = -- CHECKING CASE: Unrestricted group, there are type signatures
+ else -- UNRESTRICTED CASE, WITH TYPE SIGS
+ -- CHECKING CASE: Unrestricted group, there are type signatures
-- Check signature contexts are empty
- checkSigsCtxts sigs `thenTc` \ (sig_avails, sig_dicts) ->
+ checkSigsCtxts sigs `thenTc` \ (sig_avails, sig_dicts) ->
-- Check that the needed dicts can be
-- expressed in terms of the signature ones
returnTc (forall_tvs, lie_free, dict_binds, sig_dicts)
where
- is_unrestricted | opt_NoMonomorphismRestriction = True
- | otherwise = isUnRestrictedGroup tysig_names mbind
-
- tysig_names = [name | (TySigInfo name _ _ _ _ _ _ _) <- sigs]
- is_mono_sig (TySigInfo _ _ _ theta _ _ _ _) = null theta
+ tysig_names = map (idName . tcSigPolyId) sigs
+ is_mono_sig (TySigInfo _ _ theta _ _ _ _) = null theta
doc = ptext SLIT("type signature(s) for") <+> pprBinders binder_names
-- We unify them because, with polymorphic recursion, their types
-- might not otherwise be related. This is a rather subtle issue.
-- ToDo: amplify
-checkSigsCtxts sigs@(TySigInfo _ id1 sig_tvs theta1 _ _ _ src_loc : other_sigs)
+checkSigsCtxts sigs@(TySigInfo id1 sig_tvs theta1 _ _ _ src_loc : other_sigs)
= tcAddSrcLoc src_loc $
mapTc_ check_one other_sigs `thenTc_`
if null theta1 then
returnTc (sig_avails, map instToId sig_dicts)
where
sig1_dict_tys = map mkPredTy theta1
- sig_meths = concat [insts | TySigInfo _ _ _ _ _ _ insts _ <- sigs]
+ sig_meths = concat [insts | TySigInfo _ _ _ _ _ insts _ <- sigs]
- check_one sig@(TySigInfo _ id _ theta _ _ _ src_loc)
+ check_one sig@(TySigInfo id _ theta _ _ _ _)
= tcAddErrCtxt (sigContextsCtxt id1 id) $
checkTc (equalLength theta theta1) sigContextsErr `thenTc_`
unifyTauTyLists sig1_dict_tys (map mkPredTy theta)
checkSigsTyVars sigs = mapTc_ check_one sigs
where
- check_one (TySigInfo _ id sig_tyvars sig_theta sig_tau _ _ src_loc)
+ check_one (TySigInfo id sig_tyvars sig_theta sig_tau _ _ src_loc)
= tcAddSrcLoc src_loc $
tcAddErrCtxt (ptext SLIT("When checking the type signature for")
<+> quotes (ppr id)) $
- tcAddErrCtxtM (sigCtxt sig_tyvars sig_theta sig_tau) $
- checkSigTyVars sig_tyvars (idFreeTyVars id)
+ tcAddErrCtxtM (sigCtxt id sig_tyvars sig_theta sig_tau) $
+ checkSigTyVarsWrt (idFreeTyVars id) sig_tyvars
\end{code}
@getTyVarsToGen@ decides what type variables to generalise over.
where
mk_bind (name, mono_id) = case maybeSig tc_ty_sigs name of
- Nothing -> (name, mono_id)
- Just (TySigInfo name poly_id _ _ _ _ _ _) -> (name, poly_id)
+ Nothing -> (name, mono_id)
+ Just sig -> (idName poly_id, poly_id)
+ where
+ poly_id = tcSigPolyId sig
tc_mb_pats EmptyMonoBinds
= returnTc (\ xve -> returnTc (EmptyMonoBinds, emptyLIE), emptyLIE, emptyBag, emptyBag, emptyLIE)
tc_mb_pats (FunMonoBind name inf matches locn)
= (case maybeSig tc_ty_sigs name of
- Just (TySigInfo _ _ _ _ _ mono_id _ _)
- -> returnNF_Tc mono_id
- Nothing -> newLocalName name `thenNF_Tc` \ bndr_name ->
- newTyVarTy openTypeKind `thenNF_Tc` \ bndr_ty ->
+ Just sig -> returnNF_Tc (tcSigMonoId sig)
+ Nothing -> newLocalName name `thenNF_Tc` \ bndr_name ->
+ newTyVarTy openTypeKind `thenNF_Tc` \ bndr_ty ->
-- NB: not a 'hole' tyvar; since there is no type
-- signature, we revert to ordinary H-M typechecking
-- which means the variable gets an inferred tau-type
- returnNF_Tc (mkLocalId bndr_name bndr_ty)
+ returnNF_Tc (mkLocalId bndr_name bndr_ty)
) `thenNF_Tc` \ bndr_id ->
let
bndr_ty = idType bndr_id
complete_it xve = tcAddSrcLoc locn $
- tcMatchesFun xve name bndr_ty matches `thenTc` \ (matches', lie) ->
+ tcMatchesFun xve name bndr_ty matches `thenTc` \ (matches', lie) ->
returnTc (FunMonoBind bndr_id inf matches' locn, lie)
in
returnTc (complete_it, emptyLIE, emptyBag, unitBag (name, bndr_id), emptyLIE)
-- so we don't have to do anything here.
tcPat tc_pat_bndr pat pat_ty `thenTc` \ (pat', lie_req, tvs, ids, lie_avail) ->
+ readHoleResult pat_ty `thenTc` \ pat_ty' ->
let
complete_it xve = tcAddSrcLoc locn $
tcAddErrCtxt (patMonoBindsCtxt bind) $
- tcExtendLocalValEnv xve $
- tcGRHSs PatBindRhs grhss pat_ty `thenTc` \ (grhss', lie) ->
+ tcExtendLocalValEnv2 xve $
+ tcGRHSs PatBindRhs grhss pat_ty' `thenTc` \ (grhss', lie) ->
returnTc (PatMonoBind pat' grhss' locn, lie)
in
returnTc (complete_it, lie_req, tvs, ids, lie_avail)
-> newLocalName name `thenNF_Tc` \ bndr_name ->
tcMonoPatBndr bndr_name pat_ty
- Just (TySigInfo _ _ _ _ _ mono_id _ _)
- -> tcAddSrcLoc (getSrcLoc name) $
- tcSubPat pat_ty (idType mono_id) `thenTc` \ (co_fn, lie) ->
- returnTc (co_fn, lie, mono_id)
+ Just sig -> tcAddSrcLoc (getSrcLoc name) $
+ tcSubPat (idType mono_id) pat_ty `thenTc` \ (co_fn, lie) ->
+ returnTc (co_fn, lie, mono_id)
+ where
+ mono_id = tcSigMonoId sig
\end{code}