@@ -1,3 +1,4 @@
1+{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE NamedFieldPuns #-}
3{-# LANGUAGE NamedFieldPuns #-}
@@ -27,13 +28,16 @@ module Language.PureScript.TypeChecker.Types
28import Prelude.Compat
29import Prelude.Compat
31+import Control.Arrow (first, second, (***))
30import Control.Monad
32import Control.Monad
31import Control.Monad.Error.Class (MonadError(..))
33import Control.Monad.Error.Class (MonadError(..))
32import Control.Monad.State.Class (MonadState(..), gets)
34import Control.Monad.State.Class (MonadState(..), gets)
33import Control.Monad.Supply.Class (MonadSupply)
35import Control.Monad.Supply.Class (MonadSupply)
34import Control.Monad.Writer.Class (MonadWriter(..))
36import Control.Monad.Writer.Class (MonadWriter(..))
38+import Data.Bifunctor (bimap)
36import Data.Either (lefts, rights)
39import Data.Either (lefts, rights)
40+import Data.Functor (($>))
37import Data.List (transpose, nub, (\\), partition, delete)
41import Data.List (transpose, nub, (\\), partition, delete)
38import Data.Maybe (fromMaybe)
42import Data.Maybe (fromMaybe)
39import qualified Data.Map as M
43import qualified Data.Map as M
@@ -53,9 +57,11 @@ import Language.PureScript.TypeChecker.Rows
53import Language.PureScript.TypeChecker.Skolems
57import Language.PureScript.TypeChecker.Skolems
54import Language.PureScript.TypeChecker.Subsumption
58import Language.PureScript.TypeChecker.Subsumption
55import Language.PureScript.TypeChecker.Synonyms
59import Language.PureScript.TypeChecker.Synonyms
60+import Language.PureScript.TypeChecker.TypeSearch
56import Language.PureScript.TypeChecker.Unify
61import Language.PureScript.TypeChecker.Unify
57import Language.PureScript.Types
62import Language.PureScript.Types
59data BindingGroupType
65data BindingGroupType
60 = RecursiveBindingGroup
66 = RecursiveBindingGroup
61 | NonRecursiveBindingGroup
67 | NonRecursiveBindingGroup
@@ -70,13 +76,13 @@ typesOf
70 -> [(Ident, Expr)]
76 -> [(Ident, Expr)]
71 -> m [(Ident, (Expr, Type))]
77 -> m [(Ident, (Expr, Type))]
72typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do
78typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do
73− (tys, w) <- withoutWarnings . capturingSubstitution tidyUp $ do
79+ tys <- capturingSubstitution tidyUp $ do
74 (untyped, typed, dict, untypedDict) <- typeDictionaryForBindingGroup (Just moduleName) vals
80 (untyped, typed, dict, untypedDict) <- typeDictionaryForBindingGroup (Just moduleName) vals
75− ds1 <- parU typed $ \e -> checkTypedBindingGroupElement moduleName e dict
81+ ds1 <- parU typed $ \e -> withoutWarnings $ checkTypedBindingGroupElement moduleName e dict
76− ds2 <- forM untyped $ \e -> typeForBindingGroupElement e dict untypedDict
82+ ds2 <- forM untyped $ \e -> withoutWarnings $ typeForBindingGroupElement e dict untypedDict
77− return (map (\x -> (False, x)) ds1 ++ map (\x -> (True, x)) ds2)
83+ return (map (False, ) ds1 ++ map (True, ) ds2)
79− inferred <- forM tys $ \(shouldGeneralize, (ident, (val, ty))) -> do
85+ inferred <- forM tys $ \(shouldGeneralize, ((ident, (val, ty)), _)) -> do
80 -- Replace type class dictionary placeholders with actual dictionaries
86 -- Replace type class dictionary placeholders with actual dictionaries
81 (val', unsolved) <- replaceTypeClassDictionaries shouldGeneralize val
87 (val', unsolved) <- replaceTypeClassDictionaries shouldGeneralize val
82 -- Generalize and constrain the type
88 -- Generalize and constrain the type
@@ -96,7 +102,7 @@ typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do
96 $ CannotGeneralizeRecursiveFunction ident generalized
102 $ CannotGeneralizeRecursiveFunction ident generalized
97 -- Make sure any unsolved type constraints only use type variables which appear
103 -- Make sure any unsolved type constraints only use type variables which appear
98 -- unknown in the inferred type.
104 -- unknown in the inferred type.
99− forM_ unsolved $ \(_, con) -> do
105+ forM_ unsolved $ \(_, _, con) -> do
100 -- We need information about functional dependencies, since we allow
106 -- We need information about functional dependencies, since we allow
101 -- ambiguous types to be inferred if they can be solved by some functional
107 -- ambiguous types to be inferred if they can be solved by some functional
102 -- dependency.
108 -- dependency.
@@ -104,33 +110,56 @@ typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do
104 TypeClassData{ typeClassDependencies } <- gets (findClass . typeClasses . checkEnv)
110 TypeClassData{ typeClassDependencies } <- gets (findClass . typeClasses . checkEnv)
105 let solved = foldMap (S.fromList . fdDetermined) typeClassDependencies
111 let solved = foldMap (S.fromList . fdDetermined) typeClassDependencies
106 let constraintTypeVars = nub . foldMap (unknownsInType . fst) . filter ((`notElem` solved) . snd) $ zip (constraintArgs con) [0..]
112 let constraintTypeVars = nub . foldMap (unknownsInType . fst) . filter ((`notElem` solved) . snd) $ zip (constraintArgs con) [0..]
107− when (any (`notElem` unsolvedTypeVars) constraintTypeVars) $
113+ when (any (`notElem` unsolvedTypeVars) constraintTypeVars) $ do
108− throwError . onErrorMessages (replaceTypes currentSubst) . errorMessage $ NoInstanceFound con
114+ throwError . onErrorMessages (replaceTypes currentSubst) . errorMessage $ AmbiguousTypeVariables generalized con
110 -- Check skolem variables did not escape their scope
116 -- Check skolem variables did not escape their scope
111 skolemEscapeCheck val'
117 skolemEscapeCheck val'
112 -- Check rows do not contain duplicate labels
118 -- Check rows do not contain duplicate labels
113 checkDuplicateLabels val'
119 checkDuplicateLabels val'
114− return (ident, (foldr (Abs . Left . fst) val' unsolved, generalized))
120+ return ((ident, (foldr (Abs . Left . (\(x, _, _) -> x)) val' unsolved, generalized)), unsolved)
116 -- Show warnings here, since types in wildcards might have been solved during
122 -- Show warnings here, since types in wildcards might have been solved during
117 -- instance resolution (by functional dependencies).
123 -- instance resolution (by functional dependencies).
125+ forM_ tys $ \(shouldGeneralize, ((_, (_, _)), w)) -> do
118− finalSubst <- gets checkSubstitution
126+ let replaceTypes' = replaceTypes (checkSubstitution finalState)
127+ runTypeSearch' = runTypeSearch (guard shouldGeneralize $> foldMap snd inferred) finalState
119− escalateWarningWhen isHoleError . tell . onErrorMessages (replaceTypes finalSubst) $ w
128+ (escalateWarningWhen isHoleError . tell . onErrorMessages (runTypeSearch' . replaceTypes')) w
121− return inferred
130+ return (map fst inferred)
123 replaceTypes subst = onTypesInErrorMessage (substituteType subst)
136 replaceTypes subst = onTypesInErrorMessage (substituteType subst)
138+ -- | Run type search to complete any typed hole error messages
140+ :: Maybe [(Ident, InstanceContext, Constraint)]
141+ -- ^ Any unsolved constraints which we need to continue to satisfy
143+ -- ^ The final type checker state
146+ runTypeSearch cons st = \case
147+ ErrorMessage hints (HoleInferredType x ty y (TSBefore env)) ->
148+ let subst = checkSubstitution st
149+ searchResult = (fmap . fmap) (substituteType subst)
150+ (M.toList (typeSearch cons env st (substituteType subst ty)))
151+ in ErrorMessage hints (HoleInferredType x ty y (TSAfter searchResult))
125 -- | Generalize type vars using forall and add inferred constraints
154 -- | Generalize type vars using forall and add inferred constraints
126 generalize unsolved = varIfUnknown . constrain unsolved
155 generalize unsolved = varIfUnknown . constrain unsolved
128 -- | Add any unsolved constraints
157 -- | Add any unsolved constraints
129 constrain [] = id
158 constrain [] = id
130− constrain cs = ConstrainedType (map snd cs)
159+ constrain cs = ConstrainedType (map (\(_, _, x) -> x) cs)
132 -- Apply the substitution that was returned from runUnify to both types and (type-annotated) values
161 -- Apply the substitution that was returned from runUnify to both types and (type-annotated) values
133− tidyUp ts sub = map (\(b, (i, (val, ty))) -> (b, (i, (overTypes (substituteType sub) val, substituteType sub ty)))) ts
162+ tidyUp ts sub = map (second (first (second (overTypes (substituteType sub) *** substituteType sub)))) ts
135 isHoleError :: ErrorMessage -> Bool
164 isHoleError :: ErrorMessage -> Bool
136 isHoleError (ErrorMessage _ HoleInferredType{}) = True
165 isHoleError (ErrorMessage _ HoleInferredType{}) = True
@@ -199,19 +228,12 @@ typeForBindingGroupElement (ident, val) dict untypedDict = do
199-- | Check if a value contains a type annotation
228-- | Check if a value contains a type annotation
200isTyped :: (Ident, Expr) -> Either (Ident, Expr) (Ident, (Expr, Type, Bool))
229isTyped :: (Ident, Expr) -> Either (Ident, Expr) (Ident, (Expr, Type, Bool))
201isTyped (name, TypedValue checkType value ty) = Right (name, (value, ty, checkType))
230isTyped (name, TypedValue checkType value ty) = Right (name, (value, ty, checkType))
231+isTyped (name, PositionedValue pos c value) =
232+ bimap (second (PositionedValue pos c))
233+ (second (\(e, t, b) -> (PositionedValue pos c e, t, b)))
234+ (isTyped (name, value))
202isTyped (name, value) = Left (name, value)
235isTyped (name, value) = Left (name, value)
205−-- Map a function over type annotations appearing inside a value
207−overTypes :: (Type -> Type) -> Expr -> Expr
208−overTypes f = let (_, f', _) = everywhereOnValues id g id in f'
211− g (TypedValue checkTy val t) = TypedValue checkTy val (f t)
212− g (TypeClassDictionary c sco hints) = TypeClassDictionary (mapConstraintArgs (map f) c) sco hints
215-- | Check the kind of a type, failing if it is not of kind *.
237-- | Check the kind of a type, failing if it is not of kind *.
216checkTypeKind ::
238checkTypeKind ::
217 (MonadError MultipleErrors m) =>
239 (MonadError MultipleErrors m) =>
@@ -339,7 +361,8 @@ infer' (TypedValue checkType val ty) = do
339infer' (Hole name) = do
361infer' (Hole name) = do
340 ty <- freshType
362 ty <- freshType
341 ctx <- getLocalContext
363 ctx <- getLocalContext
342− tell . errorMessage $ HoleInferredType name ty ctx
365+ tell . errorMessage $ HoleInferredType name ty ctx (TSBefore env)
343 return $ TypedValue True (Hole name) ty
366 return $ TypedValue True (Hole name) ty
344infer' (PositionedValue pos c val) = warnAndRethrowWithPositionTC pos $ do
367infer' (PositionedValue pos c val) = warnAndRethrowWithPositionTC pos $ do
345 TypedValue t v ty <- infer' val
368 TypedValue t v ty <- infer' val
@@ -568,18 +591,14 @@ check' (Abs (Right _) _) _ = internalError "Binder was not desugared"
568check' (App f arg) ret = do
591check' (App f arg) ret = do
569 f'@(TypedValue _ _ ft) <- infer f
592 f'@(TypedValue _ _ ft) <- infer f
570 (retTy, app) <- checkFunctionApplication f' ft arg
593 (retTy, app) <- checkFunctionApplication f' ft arg
571− v' <- subsumes (Just app) retTy ret
594+ elaborate <- subsumes retTy ret
573− Nothing -> internalError "check: unable to check the subsumes relation."
574− Just app' -> return $ TypedValue True app' ret
595+ return $ TypedValue True (elaborate app) ret
575check' v@(Var var) ty = do
596check' v@(Var var) ty = do
576 checkVisibility var
597 checkVisibility var
577 repl <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< lookupVariable $ var
598 repl <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< lookupVariable $ var
578 ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty
599 ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty
579− v' <- subsumes (Just v) repl ty'
600+ elaborate <- subsumes repl ty'
581− Nothing -> internalError "check: unable to check the subsumes relation."
582− Just v'' -> return $ TypedValue True v'' ty'
601+ return $ TypedValue True (elaborate v) ty'
583check' (DeferredDictionary className tys) _ = do
602check' (DeferredDictionary className tys) _ = do
585 -- Here, we replace a placeholder for a superclass dictionary with a regular
604 -- Here, we replace a placeholder for a superclass dictionary with a regular
@@ -596,12 +615,11 @@ check' (TypedValue checkType val ty1) ty2 = do
596 checkTypeKind ty1 kind
615 checkTypeKind ty1 kind
597 ty1' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty1
616 ty1' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty1
598 ty2' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty2
617 ty2' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty2
599− val' <- subsumes (Just val) ty1' ty2'
618+ _ <- subsumes ty1' ty2'
600− case val' of
619+ val' <- if checkType
601− Nothing -> internalError "check: unable to check the subsumes relation."
603− val''' <- if checkType then withScopedTypeVars moduleName args (check val ty2') else return val
620+ then withScopedTypeVars moduleName args (check val ty2')
604− return $ TypedValue checkType val''' ty2'
622+ return $ TypedValue checkType val' ty2'
605check' (Case vals binders) ret = do
623check' (Case vals binders) ret = do
606 (vals', ts) <- instantiateForBinders vals binders
624 (vals', ts) <- instantiateForBinders vals binders
607 binders' <- checkBinders ts ret binders
625 binders' <- checkBinders ts ret binders
@@ -638,10 +656,8 @@ check' v@(Constructor c) ty = do
638 Nothing -> throwError . errorMessage . UnknownName . fmap DctorName $ c
656 Nothing -> throwError . errorMessage . UnknownName . fmap DctorName $ c
639 Just (_, _, ty1, _) -> do
657 Just (_, _, ty1, _) -> do
640 repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
658 repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
641− mv <- subsumes (Just v) repl ty
659+ elaborate <- subsumes repl ty
643− Nothing -> internalError "check: unable to check the subsumes relation."
644− Just v' -> return $ TypedValue True v' ty
660+ return $ TypedValue True (elaborate v) ty
645check' (Let ds val) ty = do
661check' (Let ds val) ty = do
646 (ds', val') <- inferLetBinding [] ds val (`check` ty)
662 (ds', val') <- inferLetBinding [] ds val (`check` ty)
647 return $ TypedValue True (Let ds' val') ty
663 return $ TypedValue True (Let ds' val') ty
@@ -654,10 +670,8 @@ check' (PositionedValue pos c val) ty = warnAndRethrowWithPositionTC pos $ do
654 return $ TypedValue t (PositionedValue pos c v) ty'
670 return $ TypedValue t (PositionedValue pos c v) ty'
655check' val ty = do
671check' val ty = do
656 TypedValue _ val' ty' <- infer val
672 TypedValue _ val' ty' <- infer val
657− mt <- subsumes (Just val') ty' ty
673+ elaborate <- subsumes ty' ty
659− Nothing -> internalError "check: unable to check the subsumes relation."
660− Just v' -> return $ TypedValue True v' ty
674+ return $ TypedValue True (elaborate val') ty
663-- Check the type of a collection of named record fields
677-- Check the type of a collection of named record fields