summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/main/GHC.hs2
-rw-r--r--compiler/main/HscMain.hs8
-rw-r--r--compiler/main/InteractiveEval.hs8
-rw-r--r--compiler/typecheck/TcBinds.hs9
-rw-r--r--compiler/typecheck/TcExpr.hs11
-rw-r--r--compiler/typecheck/TcPatSyn.hs3
-rw-r--r--compiler/typecheck/TcRnDriver.hs101
-rw-r--r--compiler/typecheck/TcSimplify.hs93
8 files changed, 162 insertions, 73 deletions
diff --git a/compiler/main/GHC.hs b/compiler/main/GHC.hs
index 40aa7dfa01..9dc68537d9 100644
--- a/compiler/main/GHC.hs
+++ b/compiler/main/GHC.hs
@@ -116,7 +116,7 @@ module GHC (
isModuleInterpreted,
-- ** Inspecting types and kinds
- exprType,
+ exprType, TcRnExprMode(..),
typeKind,
-- ** Looking up a Name
diff --git a/compiler/main/HscMain.hs b/compiler/main/HscMain.hs
index 7cbc6e711f..9c510df27b 100644
--- a/compiler/main/HscMain.hs
+++ b/compiler/main/HscMain.hs
@@ -65,7 +65,7 @@ module HscMain
, hscTcRnLookupRdrName
, hscStmt, hscStmtWithLocation, hscParsedStmt
, hscDecls, hscDeclsWithLocation
- , hscTcExpr, hscImport, hscKcType
+ , hscTcExpr, TcRnExprMode(..), hscImport, hscKcType
, hscParseExpr
, hscCompileCoreExpr
-- * Low-level exports for hooks
@@ -1609,14 +1609,14 @@ hscImport hsc_env str = runInteractiveHsc hsc_env $ do
text "parse error in import declaration"
-- | Typecheck an expression (but don't run it)
--- Returns its most general type
hscTcExpr :: HscEnv
+ -> TcRnExprMode
-> String -- ^ The expression
-> IO Type
-hscTcExpr hsc_env0 expr = runInteractiveHsc hsc_env0 $ do
+hscTcExpr hsc_env0 mode expr = runInteractiveHsc hsc_env0 $ do
hsc_env <- getHscEnv
parsed_expr <- hscParseExpr expr
- ioMsgMaybe $ tcRnExpr hsc_env parsed_expr
+ ioMsgMaybe $ tcRnExpr hsc_env mode parsed_expr
-- | Find the kind of a type
-- Currently this does *not* generalise the kinds of the type
diff --git a/compiler/main/InteractiveEval.hs b/compiler/main/InteractiveEval.hs
index 6c95dc3bcc..9877e9a0c7 100644
--- a/compiler/main/InteractiveEval.hs
+++ b/compiler/main/InteractiveEval.hs
@@ -864,10 +864,10 @@ parseThing parser dflags stmt = do
-- Getting the type of an expression
-- | Get the type of an expression
--- Returns its most general type
-exprType :: GhcMonad m => String -> m Type
-exprType expr = withSession $ \hsc_env -> do
- ty <- liftIO $ hscTcExpr hsc_env expr
+-- Returns the type as described by 'TcRnExprMode'
+exprType :: GhcMonad m => TcRnExprMode -> String -> m Type
+exprType mode expr = withSession $ \hsc_env -> do
+ ty <- liftIO $ hscTcExpr hsc_env mode expr
return $ tidyType emptyTidyEnv ty
-- -----------------------------------------------------------------------------
diff --git a/compiler/typecheck/TcBinds.hs b/compiler/typecheck/TcBinds.hs
index 7c45ac7b59..3a931cb6f6 100644
--- a/compiler/typecheck/TcBinds.hs
+++ b/compiler/typecheck/TcBinds.hs
@@ -710,15 +710,16 @@ tcPolyInfer rec_tc prag_fn tc_sig_fn mono bind_list
<- pushLevelAndCaptureConstraints $
tcMonoBinds rec_tc tc_sig_fn LetLclBndr bind_list
- ; let name_taus = [ (mbi_poly_name info, idType (mbi_mono_id info))
- | info <- mono_infos ]
- sigs = [ sig | MBI { mbi_sig = Just sig } <- mono_infos ]
+ ; let name_taus = [ (mbi_poly_name info, idType (mbi_mono_id info))
+ | info <- mono_infos ]
+ sigs = [ sig | MBI { mbi_sig = Just sig } <- mono_infos ]
+ infer_mode = if mono then ApplyMR else NoRestrictions
; mapM_ (checkOverloadedSig mono) sigs
; traceTc "simplifyInfer call" (ppr tclvl $$ ppr name_taus $$ ppr wanted)
; (qtvs, givens, ev_binds)
- <- simplifyInfer tclvl mono sigs name_taus wanted
+ <- simplifyInfer tclvl infer_mode sigs name_taus wanted
; let inferred_theta = map evVarPred givens
; exports <- checkNoErrs $
diff --git a/compiler/typecheck/TcExpr.hs b/compiler/typecheck/TcExpr.hs
index 0e3c655f76..bb3fef7349 100644
--- a/compiler/typecheck/TcExpr.hs
+++ b/compiler/typecheck/TcExpr.hs
@@ -29,7 +29,7 @@ import BasicTypes
import Inst
import TcBinds ( chooseInferredQuantifiers, tcLocalBinds )
import TcSigs ( tcUserTypeSig, tcInstSig )
-import TcSimplify ( simplifyInfer )
+import TcSimplify ( simplifyInfer, InferMode(..) )
import FamInst ( tcGetFamInstEnvs, tcLookupDataFamInst )
import FamInstEnv ( FamInstEnvs )
import RnEnv ( addUsedGRE, addNameClashErrRn
@@ -1472,10 +1472,13 @@ tcExprSig expr sig@(PartialSig { psig_name = name, sig_loc = loc })
; return (expr', sig_inst) }
-- See Note [Partial expression signatures]
; let tau = sig_inst_tau sig_inst
- mr = null (sig_inst_theta sig_inst) &&
- isNothing (sig_inst_wcx sig_inst)
+ infer_mode | null (sig_inst_theta sig_inst)
+ , isNothing (sig_inst_wcx sig_inst)
+ = ApplyMR
+ | otherwise
+ = NoRestrictions
; (qtvs, givens, ev_binds)
- <- simplifyInfer tclvl mr [sig_inst] [(name, tau)] wanted
+ <- simplifyInfer tclvl infer_mode [sig_inst] [(name, tau)] wanted
; tau <- zonkTcType tau
; let inferred_theta = map evVarPred givens
tau_tvs = tyCoVarsOfType tau
diff --git a/compiler/typecheck/TcPatSyn.hs b/compiler/typecheck/TcPatSyn.hs
index b9a6dec0a8..e19a786b1d 100644
--- a/compiler/typecheck/TcPatSyn.hs
+++ b/compiler/typecheck/TcPatSyn.hs
@@ -81,7 +81,8 @@ tcInferPatSynDecl PSB{ psb_id = lname@(L _ name), psb_args = details,
; let named_taus = (name, pat_ty) : map (\arg -> (getName arg, varType arg)) args
- ; (qtvs, req_dicts, ev_binds) <- simplifyInfer tclvl False [] named_taus wanted
+ ; (qtvs, req_dicts, ev_binds) <- simplifyInfer tclvl NoRestrictions []
+ named_taus wanted
; let ((ex_tvs, ex_vars), prov_dicts) = tcCollectEx lpat'
univ_tvs = filter (not . (`elemVarSet` ex_vars)) qtvs
diff --git a/compiler/typecheck/TcRnDriver.hs b/compiler/typecheck/TcRnDriver.hs
index 9d3bd99ab9..46d0a7b34f 100644
--- a/compiler/typecheck/TcRnDriver.hs
+++ b/compiler/typecheck/TcRnDriver.hs
@@ -13,7 +13,7 @@ https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/TypeChecker
module TcRnDriver (
#ifdef GHCI
- tcRnStmt, tcRnExpr, tcRnType,
+ tcRnStmt, tcRnExpr, TcRnExprMode(..), tcRnType,
tcRnImportDecls,
tcRnLookupRdrName,
getModuleInterface,
@@ -1972,13 +1972,17 @@ isGHCiMonad hsc_env ty
Just _ -> failWithTc $ text "Ambiguous type!"
Nothing -> failWithTc $ text ("Can't find type:" ++ ty)
--- tcRnExpr just finds the type of an expression
+-- | How should we infer a type? See Note [TcRnExprMode]
+data TcRnExprMode = TM_Inst -- ^ Instantiate the type fully (:type)
+ | TM_NoInst -- ^ Do not instantiate the type (:type +v)
+ | TM_Default -- ^ Default the type eagerly (:type +d)
+-- | tcRnExpr just finds the type of an expression
tcRnExpr :: HscEnv
+ -> TcRnExprMode
-> LHsExpr RdrName
-> IO (Messages, Maybe Type)
--- Type checks the expression and returns its most general type
-tcRnExpr hsc_env rdr_expr
+tcRnExpr hsc_env mode rdr_expr
= runTcInteractive hsc_env $
do {
@@ -1993,15 +1997,15 @@ tcRnExpr hsc_env rdr_expr
(tclvl, lie, res_ty)
<- pushLevelAndCaptureConstraints $
do { (_tc_expr, expr_ty) <- tcInferSigma rn_expr
- ; (_wrap, res_ty) <- deeplyInstantiate orig expr_ty
- -- See [Note Deeply instantiate in :type]
- ; return res_ty } ;
+ ; if inst
+ then snd <$> deeplyInstantiate orig expr_ty
+ else return expr_ty } ;
-- Generalise
((qtvs, dicts, _), lie_top) <- captureConstraints $
{-# SCC "simplifyInfer" #-}
simplifyInfer tclvl
- False {- No MR for now -}
+ infer_mode
[] {- No sig vars -}
[(fresh_it, res_ty)]
lie ;
@@ -2009,7 +2013,8 @@ tcRnExpr hsc_env rdr_expr
stWC <- tcg_static_wc <$> getGblEnv >>= readTcRef ;
-- Ignore the dictionary bindings
- _ <- simplifyInteractive (andWC stWC lie_top) ;
+ _ <- perhaps_disable_default_warnings $
+ simplifyInteractive (andWC stWC lie_top) ;
let { all_expr_ty = mkInvForAllTys qtvs (mkLamTypes dicts res_ty) } ;
ty <- zonkTcType all_expr_ty ;
@@ -2022,6 +2027,12 @@ tcRnExpr hsc_env rdr_expr
-- irrelevant
return (snd (normaliseType fam_envs Nominal ty))
}
+ where
+ -- See Note [Deeply instantiate in :type]
+ (inst, infer_mode, perhaps_disable_default_warnings) = case mode of
+ TM_Inst -> (True, NoRestrictions, id)
+ TM_NoInst -> (False, NoRestrictions, id)
+ TM_Default -> (True, EagerDefaulting, unsetWOptM Opt_WarnTypeDefaults)
--------------------------
tcRnImportDecls :: HscEnv
@@ -2038,7 +2049,6 @@ tcRnImportDecls hsc_env import_decls
zap_rdr_env gbl_env = gbl_env { tcg_rdr_env = emptyGlobalRdrEnv }
-- tcRnType just finds the kind of a type
-
tcRnType :: HscEnv
-> Bool -- Normalise the returned type
-> LHsType RdrName
@@ -2073,20 +2083,63 @@ tcRnType hsc_env normalise rdr_type
; return (ty', mkInvForAllTys kvs (typeKind ty')) }
-{- Note [Deeply instantiate in :type]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Suppose (Trac #11376)
- bar :: forall a b. Show a => a -> b -> a
-What should `:t bar @Int` show?
-
- 1. forall b. Show Int => Int -> b -> Int
- 2. forall b. Int -> b -> Int
- 3. forall {b}. Int -> b -> Int
- 4. Int -> b -> Int
-
-We choose (3), which is the effect of deeply instantiating and
-re-generalising. All the others seem deeply confusing. That is
-why we deeply instantiate here.
+{- Note [TcRnExprMode]
+~~~~~~~~~~~~~~~~~~~~~~
+How should we infer a type when a user asks for the type of an expression e
+at the GHCi prompt? We offer 3 different possibilities, described below. Each
+considers this example, with -fprint-explicit-foralls enabled:
+
+ foo :: forall a f b. (Show a, Num b, Foldable f) => a -> f b -> String
+ :type{,-spec,-def} foo @Int
+
+:type / TM_Inst
+
+ In this mode, we report the type that would be inferred if a variable
+ were assigned to expression e, without applying the monomorphism restriction.
+ This means we deeply instantiate the type and then regeneralize, as discussed
+ in #11376.
+
+ > :type foo @Int
+ forall {b} {f :: * -> *}. (Foldable f, Num b) => Int -> f b -> String
+
+ Note that the variables and constraints are reordered here, because this
+ is possible during regeneralization. Also note that the variables are
+ reported as Invisible instead of Specified.
+
+:type +v / TM_NoInst
+
+ This mode is for the benefit of users using TypeApplications. It does no
+ instantiation whatsoever, sometimes meaning that class constraints are not
+ solved.
+
+ > :type +v foo @Int
+ forall f b. (Show Int, Num b, Foldable f) => Int -> f b -> String
+
+ Note that Show Int is still reported, because the solver never got a chance
+ to see it.
+
+:type +d / TM_Default
+
+ This mode is for the benefit of users who wish to see instantiations of
+ generalized types, and in particular to instantiate Foldable and Traversable.
+ In this mode, any type variable that can be defaulted is defaulted. Because
+ GHCi uses -XExtendedDefaultRules, this means that Foldable and Traversable are
+ defaulted.
+
+ > :type +d foo @Int
+ Int -> [Integer] -> String
+
+ Note that this mode can sometimes lead to a type error, if a type variable is
+ used with a defaultable class but cannot actually be defaulted:
+
+ bar :: (Num a, Monoid a) => a -> a
+ > :type +d bar
+ ** error **
+
+ The error arises because GHC tries to default a but cannot find a concrete
+ type in the defaulting list that is both Num and Monoid. (If this list is
+ modified to include an element that is both Num and Monoid, the defaulting
+ would succeed, of course.)
Note [Kind-generalise in tcRnType]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/compiler/typecheck/TcSimplify.hs b/compiler/typecheck/TcSimplify.hs
index 594cc949b3..18adee8047 100644
--- a/compiler/typecheck/TcSimplify.hs
+++ b/compiler/typecheck/TcSimplify.hs
@@ -1,7 +1,7 @@
{-# LANGUAGE CPP #-}
module TcSimplify(
- simplifyInfer,
+ simplifyInfer, InferMode(..),
growThetaTyVars,
simplifyAmbiguityCheck,
simplifyDefault,
@@ -514,8 +514,22 @@ the let binding.
-}
+-- | How should we choose which constraints to quantify over?
+data InferMode = ApplyMR -- ^ Apply the monomorphism restriction,
+ -- never quantifying over any constraints
+ | EagerDefaulting -- ^ See Note [TcRnExprMode] in TcRnDriver,
+ -- the :type +d case; this mode refuses
+ -- to quantify over any defaultable constraint
+ | NoRestrictions -- ^ Quantify over any constraint that
+ -- satisfies TcType.pickQuantifiablePreds
+
+instance Outputable InferMode where
+ ppr ApplyMR = text "ApplyMR"
+ ppr EagerDefaulting = text "EagerDefaulting"
+ ppr NoRestrictions = text "NoRestrictions"
+
simplifyInfer :: TcLevel -- Used when generating the constraints
- -> Bool -- Apply monomorphism restriction
+ -> InferMode
-> [TcIdSigInst] -- Any signatures (possibly partial)
-> [(Name, TcTauType)] -- Variables to be generalised,
-- and their tau-types
@@ -523,7 +537,7 @@ simplifyInfer :: TcLevel -- Used when generating the constraints
-> TcM ([TcTyVar], -- Quantify over these type variables
[EvVar], -- ... and these constraints (fully zonked)
TcEvBinds) -- ... binding these evidence variables
-simplifyInfer rhs_tclvl apply_mr sigs name_taus wanteds
+simplifyInfer rhs_tclvl infer_mode sigs name_taus wanteds
| isEmptyWC wanteds
= do { gbl_tvs <- tcGetGlobalTyCoVars
; dep_vars <- zonkTcTypesAndSplitDepVars (map snd name_taus)
@@ -536,7 +550,7 @@ simplifyInfer rhs_tclvl apply_mr sigs name_taus wanteds
[ text "sigs =" <+> ppr sigs
, text "binds =" <+> ppr name_taus
, text "rhs_tclvl =" <+> ppr rhs_tclvl
- , text "apply_mr =" <+> ppr apply_mr
+ , text "infer_mode =" <+> ppr infer_mode
, text "(unzonked) wanted =" <+> ppr wanteds
]
@@ -616,7 +630,7 @@ simplifyInfer rhs_tclvl apply_mr sigs name_taus wanteds
-- Decide what type variables and constraints to quantify
-- NB: bound_theta are constraints we want to quantify over,
-- /apart from/ the psig_theta, which we always quantify over
- ; (qtvs, bound_theta) <- decideQuantification apply_mr name_taus psig_theta
+ ; (qtvs, bound_theta) <- decideQuantification infer_mode name_taus psig_theta
quant_pred_candidates
-- Promote any type variables that are free in the inferred type
@@ -763,23 +777,31 @@ including all covars -- and the quantified constraints are empty/insoluble.
-}
decideQuantification
- :: Bool -- try the MR restriction?
+ :: InferMode
-> [(Name, TcTauType)] -- Variables to be generalised
-> [PredType] -- All annotated constraints from signatures
-> [PredType] -- Candidate theta
-> TcM ( [TcTyVar] -- Quantify over these (skolems)
, [PredType] ) -- and this context (fully zonked)
-- See Note [Deciding quantification]
-decideQuantification apply_mr name_taus psig_theta candidates
+decideQuantification infer_mode name_taus psig_theta candidates
= do { gbl_tvs <- tcGetGlobalTyCoVars
; zonked_taus <- mapM TcM.zonkTcType (psig_theta ++ taus)
-- psig_theta: see Note [Quantification and partial signatures]
- ; let DV { dv_kvs = zkvs, dv_tvs = ztvs} = splitDepVarsOfTypes zonked_taus
+ ; ovl_strings <- xoptM LangExt.OverloadedStrings
+ ; let DV {dv_kvs = zkvs, dv_tvs = ztvs} = splitDepVarsOfTypes zonked_taus
(gbl_cand, quant_cand) -- gbl_cand = do not quantify me
- = case apply_mr of -- quant_cand = try to quantify me
- True -> (candidates, [])
- False -> ([], candidates)
- zonked_tkvs = dVarSetToVarSet zkvs `unionVarSet` dVarSetToVarSet ztvs
+ = case infer_mode of -- quant_cand = try to quantify me
+ ApplyMR -> (candidates, [])
+ NoRestrictions -> ([], candidates)
+ EagerDefaulting -> partition is_interactive_ct candidates
+ where
+ is_interactive_ct ct
+ | Just (cls, _) <- getClassPredTys_maybe ct
+ = isInteractiveClass ovl_strings cls
+ | otherwise
+ = False
+
eq_constraints = filter isEqPred quant_cand
constrained_tvs = tyCoVarsOfTypes gbl_cand
mono_tvs = growThetaTyVars eq_constraints $
@@ -804,7 +826,10 @@ decideQuantification apply_mr name_taus psig_theta candidates
-- Warn about the monomorphism restriction
; warn_mono <- woptM Opt_WarnMonomorphism
- ; let mr_bites = constrained_tvs `intersectsVarSet` zonked_tkvs
+ ; let mr_bites | ApplyMR <- infer_mode
+ = constrained_tvs `intersectsVarSet` tcDepVarSet dvs_plus
+ | otherwise
+ = False
; warnTc (Reason Opt_WarnMonomorphism) (warn_mono && mr_bites) $
hang (text "The Monomorphism Restriction applies to the binding"
<> plural bndrs <+> text "for" <+> pp_bndrs)
@@ -812,8 +837,9 @@ decideQuantification apply_mr name_taus psig_theta candidates
<+> if isSingleton bndrs then pp_bndrs
else text "these binders")
- ; traceTc "decideQuantification 2"
- (vcat [ text "gbl_cand:" <+> ppr gbl_cand
+ ; traceTc "decideQuantification"
+ (vcat [ text "infer_mode:" <+> ppr infer_mode
+ , text "gbl_cand:" <+> ppr gbl_cand
, text "quant_cand:" <+> ppr quant_cand
, text "gbl_tvs:" <+> ppr gbl_tvs
, text "mono_tvs:" <+> ppr mono_tvs
@@ -1676,7 +1702,7 @@ approximateWC to produce a list of candidate constraints. Then we MUST
approximateWC, to restore invariant (MetaTvInv) described in
Note [TcLevel and untouchable type variables] in TcType.
- b) Default the kind of any meta-tyyvars that are not mentioned in
+ b) Default the kind of any meta-tyvars that are not mentioned in
in the environment.
To see (b), suppose the constraint is (C ((a :: OpenKind) -> Int)), and we
@@ -1994,22 +2020,13 @@ findDefaultableGroups (default_tys, (ovl_strings, extended_defaults)) wanteds
in b1 && b2
defaultable_classes clss
- | extended_defaults = any isInteractiveClass clss
- | otherwise = all is_std_class clss && (any is_num_class clss)
-
- -- In interactive mode, or with -XExtendedDefaultRules,
- -- we default Show a to Show () to avoid graututious errors on "show []"
- isInteractiveClass cls
- = is_num_class cls || (classKey cls `elem` [showClassKey, eqClassKey
- , ordClassKey, foldableClassKey
- , traversableClassKey])
-
- is_num_class cls = isNumericClass cls || (ovl_strings && (cls `hasKey` isStringClassKey))
- -- is_num_class adds IsString to the standard numeric classes,
- -- when -foverloaded-strings is enabled
+ | extended_defaults = any (isInteractiveClass ovl_strings) clss
+ | otherwise = all is_std_class clss && (any (isNumClass ovl_strings) clss)
- is_std_class cls = isStandardClass cls || (ovl_strings && (cls `hasKey` isStringClassKey))
- -- Similarly is_std_class
+ -- is_std_class adds IsString to the standard numeric classes,
+ -- when -foverloaded-strings is enabled
+ is_std_class cls = isStandardClass cls ||
+ (ovl_strings && (cls `hasKey` isStringClassKey))
------------------------------
disambigGroup :: [Type] -- The default types
@@ -2061,6 +2078,20 @@ disambigGroup (default_ty:default_tys) group@(the_tv, wanteds)
-- With the addition of polykinded defaulting we also want to reject
-- ill-kinded defaulting attempts like (Eq []) or (Foldable Int) here.
+-- In interactive mode, or with -XExtendedDefaultRules,
+-- we default Show a to Show () to avoid graututious errors on "show []"
+isInteractiveClass :: Bool -- -XOverloadedStrings?
+ -> Class -> Bool
+isInteractiveClass ovl_strings cls
+ = isNumClass ovl_strings cls || (classKey cls `elem` interactiveClassKeys)
+
+ -- isNumClass adds IsString to the standard numeric classes,
+ -- when -foverloaded-strings is enabled
+isNumClass :: Bool -- -XOverloadedStrings?
+ -> Class -> Bool
+isNumClass ovl_strings cls
+ = isNumericClass cls || (ovl_strings && (cls `hasKey` isStringClassKey))
+
{-
Note [Avoiding spurious errors]