git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #1406 from purescript/421
031e5c5Phil Freeman
examples/failing/438.purs+1−1
@@ -1,4 +1,4 @@
1−-- @shouldFailWith NoInstanceFound
1+-- @shouldFailWith PossiblyInfiniteInstance
2
2
3-- See issue 438 for details: this test is mainly here to test that code like
3-- See issue 438 for details: this test is mainly here to test that code like
4-- this doesn't cause the compiler to loop.
4-- this doesn't cause the compiler to loop.
examples/passing/Superclasses2.purs → examples/failing/Superclasses5.pursrenamed+2
@@ -1,3 +1,5 @@
1+-- @shouldFailWith NoInstanceFound
2+
1module Main where
3module Main where
2
4
3import Prelude
5import Prelude
src/Language/PureScript/AST/Declarations.hs+1−1
@@ -386,7 +386,7 @@ data Expr
386 -- at superclass implementations when searching for a dictionary, the type class name and
386 -- at superclass implementations when searching for a dictionary, the type class name and
387 -- instance type, and the type class dictionaries in scope.
387 -- instance type, and the type class dictionaries in scope.
388 --
388 --
389− | TypeClassDictionary Bool Constraint (M.Map (Maybe ModuleName) (M.Map (Qualified ProperName) (M.Map (Qualified Ident) TypeClassDictionaryInScope)))
389+ | TypeClassDictionary Constraint (M.Map (Maybe ModuleName) (M.Map (Qualified ProperName) (M.Map (Qualified Ident) TypeClassDictionaryInScope)))
390 -- |
390 -- |
391 -- A typeclass dictionary accessor, the implementation is left unspecified until CoreFn desugaring.
391 -- A typeclass dictionary accessor, the implementation is left unspecified until CoreFn desugaring.
392 --
392 --
src/Language/PureScript/AST/Traversals.hs+1−1
@@ -396,7 +396,7 @@ accumTypes f = everythingOnValues mappend forDecls forValues (const mempty) (con
396 forDecls (TypeDeclaration _ ty) = f ty
396 forDecls (TypeDeclaration _ ty) = f ty
397 forDecls _ = mempty
397 forDecls _ = mempty
398
398
399− forValues (TypeClassDictionary _ (_, cs) _) = mconcat (map f cs)
399+ forValues (TypeClassDictionary (_, cs) _) = mconcat (map f cs)
400 forValues (SuperClassDictionary _ tys) = mconcat (map f tys)
400 forValues (SuperClassDictionary _ tys) = mconcat (map f tys)
401 forValues (TypedValue _ _ ty) = f ty
401 forValues (TypedValue _ _ ty) = f ty
402 forValues _ = mempty
402 forValues _ = mempty
src/Language/PureScript/Docs/ParseAndDesugar.hs+1−1
@@ -11,7 +11,7 @@ import Control.Monad
11import Control.Applicative
11import Control.Applicative
12
12
13import Control.Monad.Trans.Except
13import Control.Monad.Trans.Except
14−import Control.Monad.Writer.Strict (WriterT(), runWriterT)
14+import Control.Monad.Writer.Strict (runWriterT)
15import Control.Monad.Error.Class (MonadError(..))
15import Control.Monad.Error.Class (MonadError(..))
16import Control.Monad.IO.Class (MonadIO(..))
16import Control.Monad.IO.Class (MonadIO(..))
17
17
src/Language/PureScript/Errors.hs+6−16
@@ -40,7 +40,6 @@ import Language.PureScript.Pretty
40import Language.PureScript.Types
40import Language.PureScript.Types
41import Language.PureScript.Names
41import Language.PureScript.Names
42import Language.PureScript.Kinds
42import Language.PureScript.Kinds
43−import Language.PureScript.TypeClassDictionaries
44
43
45import qualified Text.PrettyPrint.Boxes as Box
44import qualified Text.PrettyPrint.Boxes as Box
46
45
@@ -108,8 +107,9 @@ data SimpleErrorMessage
108 | TypesDoNotUnify Type Type
107 | TypesDoNotUnify Type Type
109 | KindsDoNotUnify Kind Kind
108 | KindsDoNotUnify Kind Kind
110 | ConstrainedTypeUnified Type Type
109 | ConstrainedTypeUnified Type Type
111− | OverlappingInstances (Qualified ProperName) [Type] [DictionaryValue]
110+ | OverlappingInstances (Qualified ProperName) [Type] [Qualified Ident]
112 | NoInstanceFound (Qualified ProperName) [Type]
111 | NoInstanceFound (Qualified ProperName) [Type]
112+ | PossiblyInfiniteInstance (Qualified ProperName) [Type]
113 | CannotDerive (Qualified ProperName) [Type]
113 | CannotDerive (Qualified ProperName) [Type]
114 | CannotFindDerivingType ProperName
114 | CannotFindDerivingType ProperName
115 | DuplicateLabel String (Maybe Expr)
115 | DuplicateLabel String (Maybe Expr)
@@ -233,6 +233,7 @@ errorCode em = case unwrapErrorMessage em of
233 ConstrainedTypeUnified{} -> "ConstrainedTypeUnified"
233 ConstrainedTypeUnified{} -> "ConstrainedTypeUnified"
234 OverlappingInstances{} -> "OverlappingInstances"
234 OverlappingInstances{} -> "OverlappingInstances"
235 NoInstanceFound{} -> "NoInstanceFound"
235 NoInstanceFound{} -> "NoInstanceFound"
236+ PossiblyInfiniteInstance{} -> "PossiblyInfiniteInstance"
236 CannotDerive{} -> "CannotDerive"
237 CannotDerive{} -> "CannotDerive"
237 CannotFindDerivingType{} -> "CannotFindDerivingType"
238 CannotFindDerivingType{} -> "CannotFindDerivingType"
238 DuplicateLabel{} -> "DuplicateLabel"
239 DuplicateLabel{} -> "DuplicateLabel"
@@ -544,10 +545,12 @@ prettyPrintSingleError full level e = prettyPrintErrorMessage <$> onTypesInError
544 ]
545 ]
545 goSimple (OverlappingInstances nm ts ds) =
546 goSimple (OverlappingInstances nm ts ds) =
546 paras [ line $ "Overlapping instances found for " ++ show nm ++ " " ++ unwords (map prettyPrintTypeAtom ts) ++ ":"
547 paras [ line $ "Overlapping instances found for " ++ show nm ++ " " ++ unwords (map prettyPrintTypeAtom ts) ++ ":"
547− , paras $ map prettyPrintDictionaryValue ds
548+ , line $ intercalate ", " (map show ds)
548 ]
549 ]
549 goSimple (NoInstanceFound nm ts) =
550 goSimple (NoInstanceFound nm ts) =
550 line $ "No instance found for " ++ show nm ++ " " ++ unwords (map prettyPrintTypeAtom ts)
551 line $ "No instance found for " ++ show nm ++ " " ++ unwords (map prettyPrintTypeAtom ts)
552+ goSimple (PossiblyInfiniteInstance nm ts) =
553+ line $ "Instance for " ++ show nm ++ " " ++ unwords (map prettyPrintTypeAtom ts) ++ " is possibly infinite."
551 goSimple (CannotDerive nm ts) =
554 goSimple (CannotDerive nm ts) =
552 line $ "Cannot derive " ++ show nm ++ " instance for " ++ unwords (map prettyPrintTypeAtom ts)
555 line $ "Cannot derive " ++ show nm ++ " instance for " ++ unwords (map prettyPrintTypeAtom ts)
553 goSimple (CannotFindDerivingType nm) =
556 goSimple (CannotFindDerivingType nm) =
@@ -736,19 +739,6 @@ prettyPrintSingleError full level e = prettyPrintErrorMessage <$> onTypesInError
736 indent :: Box.Box -> Box.Box
739 indent :: Box.Box -> Box.Box
737 indent = Box.moveRight 2
740 indent = Box.moveRight 2
738
741
739− -- |
740− -- Render a DictionaryValue fit for human consumption in error messages
741− --
742− prettyPrintDictionaryValue :: DictionaryValue -> Box.Box
743− prettyPrintDictionaryValue (LocalDictionaryValue _) = line "Dictionary in scope"
744− prettyPrintDictionaryValue (GlobalDictionaryValue nm) = line (show nm)
745− prettyPrintDictionaryValue (DependentDictionaryValue nm args) = paras [ line $ (show nm) ++ " via"
746− , indent $ paras $ map prettyPrintDictionaryValue args
747− ]
748− prettyPrintDictionaryValue (SubclassDictionaryValue sup nm _) = paras [ line $ (show nm) ++ " via superclass"
749− , indent $ prettyPrintDictionaryValue sup
750− ]
751−
752 -- |
742 -- |
753 -- Pretty print and export declaration
743 -- Pretty print and export declaration
754 --
744 --
src/Language/PureScript/Pretty/Values.hs+1−1
@@ -74,7 +74,7 @@ literals = mkPattern' match
74 ]
74 ]
75 match (OperatorSection op (Right val)) = return $ "(" ++ prettyPrintValue op ++ " " ++ prettyPrintValue val ++ ")"
75 match (OperatorSection op (Right val)) = return $ "(" ++ prettyPrintValue op ++ " " ++ prettyPrintValue val ++ ")"
76 match (OperatorSection op (Left val)) = return $ "(" ++ prettyPrintValue val ++ " " ++ prettyPrintValue op ++ ")"
76 match (OperatorSection op (Left val)) = return $ "(" ++ prettyPrintValue val ++ " " ++ prettyPrintValue op ++ ")"
77− match (TypeClassDictionary _ (name, tys) _) = return $ "<<dict " ++ show name ++ " " ++ unwords (map prettyPrintTypeAtom tys) ++ ">>"
77+ match (TypeClassDictionary (name, tys) _) = return $ "<<dict " ++ show name ++ " " ++ unwords (map prettyPrintTypeAtom tys) ++ ">>"
78 match (SuperClassDictionary name _) = return $ "<<superclass dict " ++ show name ++ ">>"
78 match (SuperClassDictionary name _) = return $ "<<superclass dict " ++ show name ++ ">>"
79 match (TypedValue _ val _) = prettyPrintValue' val
79 match (TypedValue _ val _) = prettyPrintValue' val
80 match (PositionedValue _ _ val) = prettyPrintValue' val
80 match (PositionedValue _ _ val) = prettyPrintValue' val
src/Language/PureScript/TypeChecker.hs+5−13
@@ -130,7 +130,7 @@ checkTypeSynonyms = void . replaceAllTypeSynonyms
130-- * Process module imports
130-- * Process module imports
131--
131--
132typeCheckAll :: Maybe ModuleName -> ModuleName -> [DeclarationRef] -> [Declaration] -> Check [Declaration]
132typeCheckAll :: Maybe ModuleName -> ModuleName -> [DeclarationRef] -> [Declaration] -> Check [Declaration]
133−typeCheckAll mainModuleName moduleName exps ds = mapM go ds <* mapM_ checkOrphanFixities ds
133+typeCheckAll mainModuleName moduleName _ ds = mapM go ds <* mapM_ checkOrphanFixities ds
134 where
134 where
135 go :: Declaration -> Check Declaration
135 go :: Declaration -> Check Declaration
136 go (DataDeclaration dtype name args dctors) = do
136 go (DataDeclaration dtype name args dctors) = do
@@ -236,16 +236,16 @@ typeCheckAll mainModuleName moduleName exps ds = mapM go ds <* mapM_ checkOrphan
236 mapM_ (checkTypeClassInstance moduleName) tys
236 mapM_ (checkTypeClassInstance moduleName) tys
237 forM_ deps $ mapM_ (checkTypeClassInstance moduleName) . snd
237 forM_ deps $ mapM_ (checkTypeClassInstance moduleName) . snd
238 checkOrphanInstance moduleName className tys
238 checkOrphanInstance moduleName className tys
239− let dict = TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) className tys (Just deps) TCDRegular isInstanceExported
239+ let dict = TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) [] className tys (Just deps) TCDRegular
240 addTypeClassDictionaries (Just moduleName) . M.singleton className $ M.singleton (canonicalizeDictionary dict) dict
240 addTypeClassDictionaries (Just moduleName) . M.singleton className $ M.singleton (canonicalizeDictionary dict) dict
241 return d
241 return d
242
242
243 where
243 where
244
244
245 checkOrphanInstance :: ModuleName -> Qualified ProperName -> [Type] -> Check ()
245 checkOrphanInstance :: ModuleName -> Qualified ProperName -> [Type] -> Check ()
246− checkOrphanInstance mn (Qualified (Just mn') _) tys
246+ checkOrphanInstance mn (Qualified (Just mn') _) tys'
247− | mn == mn' || any checkType tys = return ()
247+ | mn == mn' || any checkType tys' = return ()
248− | otherwise = throwError . errorMessage $ OrphanInstance dictName className tys
248+ | otherwise = throwError . errorMessage $ OrphanInstance dictName className tys'
249 where
249 where
250 checkType :: Type -> Bool
250 checkType :: Type -> Bool
251 checkType (TypeVar _) = False
251 checkType (TypeVar _) = False
@@ -255,14 +255,6 @@ typeCheckAll mainModuleName moduleName exps ds = mapM go ds <* mapM_ checkOrphan
255 checkType _ = error "Invalid type in instance in checkOrphanInstance"
255 checkType _ = error "Invalid type in instance in checkOrphanInstance"
256 checkOrphanInstance _ _ _ = error "Unqualified class name in checkOrphanInstance"
256 checkOrphanInstance _ _ _ = error "Unqualified class name in checkOrphanInstance"
257
257
258− isInstanceExported :: Bool
259− isInstanceExported = any exportsInstance exps
260−
261− exportsInstance :: DeclarationRef -> Bool
262− exportsInstance (TypeInstanceRef name) | name == dictName = True
263− exportsInstance (PositionedDeclarationRef _ _ r) = exportsInstance r
264− exportsInstance _ = False
265−
266 -- |
258 -- |
267 -- This function adds the argument kinds for a type constructor so that they may appear in the externs file,
259 -- This function adds the argument kinds for a type constructor so that they may appear in the externs file,
268 -- extracted from the kind of the type constructor itself.
260 -- extracted from the kind of the type constructor itself.
src/Language/PureScript/TypeChecker/Entailment.hs+48−88
@@ -41,13 +41,11 @@ import Language.PureScript.TypeClassDictionaries
41import Language.PureScript.Types
41import Language.PureScript.Types
42import qualified Language.PureScript.Constants as C
42import qualified Language.PureScript.Constants as C
43
43
44−newtype Work = Work Integer deriving (Show, Eq, Ord, Num)
45−
46-- |
44-- |
47-- Check that the current set of type class dictionaries entail the specified type class goal, and, if so,
45-- Check that the current set of type class dictionaries entail the specified type class goal, and, if so,
48-- return a type class dictionary reference.
46-- return a type class dictionary reference.
49--
47--
50−entails :: Environment -> ModuleName -> M.Map (Maybe ModuleName) (M.Map (Qualified ProperName) (M.Map (Qualified Ident) TypeClassDictionaryInScope)) -> Constraint -> Bool -> Check Expr
48+entails :: Environment -> ModuleName -> M.Map (Maybe ModuleName) (M.Map (Qualified ProperName) (M.Map (Qualified Ident) TypeClassDictionaryInScope)) -> Constraint -> Check Expr
51entails env moduleName context = solve
49entails env moduleName context = solve
52 where
50 where
53 forClassName :: Qualified ProperName -> [TypeClassDictionaryInScope]
51 forClassName :: Qualified ProperName -> [TypeClassDictionaryInScope]
@@ -56,56 +54,57 @@ entails env moduleName context = solve
56 findDicts :: Qualified ProperName -> Maybe ModuleName -> [TypeClassDictionaryInScope]
54 findDicts :: Qualified ProperName -> Maybe ModuleName -> [TypeClassDictionaryInScope]
57 findDicts cn = maybe [] M.elems . (>>= M.lookup cn) . flip M.lookup context
55 findDicts cn = maybe [] M.elems . (>>= M.lookup cn) . flip M.lookup context
58
56
59− solve :: Constraint -> Bool -> Check Expr
57+ solve :: Constraint -> Check Expr
60− solve (className, tys) trySuperclasses = do
58+ solve (className, tys) = do
61− let dicts = flip evalStateT (Work 0) $ go trySuperclasses className tys
59+ dict <- go 0 className tys
62− checkOverlaps dicts
60+ return $ dictionaryValueToValue dict
63 where
61 where
64− go :: Bool -> Qualified ProperName -> [Type] -> StateT Work [] DictionaryValue
62+ go :: Int -> Qualified ProperName -> [Type] -> Check DictionaryValue
65− go trySuperclasses' className' tys' = do
63+ go work className' tys' | work > 1000 = throwError . errorMessage $ PossiblyInfiniteInstance className' tys'
66− workDone <- get
64+ go work className' tys' = do
67− guard $ workDone < 1000
65+ let instances = do
68− modify (1 +)
66+ tcd <- forClassName className'
69− directInstances <|> superclassInstances
67+ -- Make sure the type unifies with the type in the type instance definition
68+ subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' (tcdInstanceTypes tcd)
69+ return (subst, tcd)
70+ (subst, tcd) <- unique instances
71+ -- Solve any necessary subgoals
72+ args <- solveSubgoals subst (tcdDependencies tcd)
73+ return $ foldr (\(superclassName, index) dict -> SubclassDictionaryValue dict superclassName index)
74+ (mkDictionary (canonicalizeDictionary tcd) args)
75+ (tcdPath tcd)
70 where
76 where
71− directInstances :: StateT Work [] DictionaryValue
77+
72− directInstances = do
78+ unique :: [(a, TypeClassDictionaryInScope)] -> Check (a, TypeClassDictionaryInScope)
73− tcd <- lift $ forClassName className'
79+ unique [] = throwError . errorMessage $ NoInstanceFound className' tys'
74− -- Make sure the type unifies with the type in the type instance definition
80+ unique [a] = return a
75− subst <- lift . maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' (tcdInstanceTypes tcd)
81+ unique tcds | pairwise overlapping (map snd tcds) = throwError . errorMessage $ OverlappingInstances className' tys' (map (tcdName . snd) tcds)
76− -- Solve any necessary subgoals
82+ | otherwise = return (minimumBy (compare `on` length . tcdPath . snd) tcds)
77− args <- solveSubgoals subst (tcdDependencies tcd)
78− return $ mkDictionary (canonicalizeDictionary tcd) args
79
83
80− superclassInstances :: StateT Work [] DictionaryValue
84+ -- |
81− superclassInstances = do
85+ -- Check if two dictionaries are overlapping
82− guard trySuperclasses'
86+ --
83− (subclassName, (args, _, implies)) <- lift $ M.toList (typeClasses env)
87+ -- Dictionaries which are subclass dictionaries cannot overlap, since otherwise the overlap would have
84− -- Try each superclass
88+ -- been caught when constructing superclass dictionaries.
85− (index, (superclass, suTyArgs)) <- lift $ zip [0..] implies
89+ overlapping :: TypeClassDictionaryInScope -> TypeClassDictionaryInScope -> Bool
86− -- Make sure the type class name matches the superclass name
90+ overlapping TypeClassDictionaryInScope{ tcdPath = _ : _ } _ = False
87− guard $ className' == superclass
91+ overlapping _ TypeClassDictionaryInScope{ tcdPath = _ : _ } = False
88− -- Make sure the types unify with the types in the superclass implication
92+ overlapping tcd1 tcd2 = tcdName tcd1 /= tcdName tcd2
89− subst <- lift . maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' suTyArgs
90− -- Finally, satisfy the subclass constraint
91− args' <- lift . maybeToList $ mapM ((`lookup` subst) . fst) args
92− suDict <- go True subclassName args'
93− return $ SubclassDictionaryValue suDict superclass index
94
93
95− -- Create dictionaries for subgoals which still need to be solved by calling go recursively
94+ -- Create dictionaries for subgoals which still need to be solved by calling go recursively
96− -- E.g. the goal (Show a, Show b) => Show (Either a b) can be satisfied if the current type
95+ -- E.g. the goal (Show a, Show b) => Show (Either a b) can be satisfied if the current type
97− -- unifies with Either a b, and we can satisfy the subgoals Show a and Show b recursively.
96+ -- unifies with Either a b, and we can satisfy the subgoals Show a and Show b recursively.
98− solveSubgoals :: [(String, Type)] -> Maybe [Constraint] -> StateT Work [] (Maybe [DictionaryValue])
97+ solveSubgoals :: [(String, Type)] -> Maybe [Constraint] -> Check (Maybe [DictionaryValue])
99− solveSubgoals _ Nothing = return Nothing
98+ solveSubgoals _ Nothing = return Nothing
100− solveSubgoals subst (Just subgoals) = do
99+ solveSubgoals subst (Just subgoals) = do
101− dict <- mapM (uncurry (go True) . second (map (replaceAllTypeVars subst))) subgoals
100+ dict <- mapM (uncurry (go (work + 1)) . second (map (replaceAllTypeVars subst))) subgoals
102− return $ Just dict
101+ return $ Just dict
103
102
104− -- Make a dictionary from subgoal dictionaries by applying the correct function
103+ -- Make a dictionary from subgoal dictionaries by applying the correct function
105− mkDictionary :: Qualified Ident -> Maybe [DictionaryValue] -> DictionaryValue
104+ mkDictionary :: Qualified Ident -> Maybe [DictionaryValue] -> DictionaryValue
106− mkDictionary fnName Nothing = LocalDictionaryValue fnName
105+ mkDictionary fnName Nothing = LocalDictionaryValue fnName
107− mkDictionary fnName (Just []) = GlobalDictionaryValue fnName
106+ mkDictionary fnName (Just []) = GlobalDictionaryValue fnName
108− mkDictionary fnName (Just dicts) = DependentDictionaryValue fnName dicts
107+ mkDictionary fnName (Just dicts) = DependentDictionaryValue fnName dicts
109
108
110 -- Turn a DictionaryValue into a Expr
109 -- Turn a DictionaryValue into a Expr
111 dictionaryValueToValue :: DictionaryValue -> Expr
110 dictionaryValueToValue :: DictionaryValue -> Expr
@@ -122,46 +121,7 @@ entails env moduleName context = solve
122 let grps = groupBy ((==) `on` fst) subst
121 let grps = groupBy ((==) `on` fst) subst
123 guard (all (pairwise (unifiesWith env) . map snd) grps)
122 guard (all (pairwise (unifiesWith env) . map snd) grps)
124 return $ map head grps
123 return $ map head grps
125− -- |
124+
126− -- Check for overlapping instances
127− --
128− checkOverlaps :: [DictionaryValue] -> Check Expr
129− checkOverlaps dicts =
130− case [ (d1, d2) | d1 <- dicts, d2 <- dicts, d1 `overlapping` d2 ] of
131− ds@(_ : _) -> throwError . errorMessage $ OverlappingInstances className tys $ nub (map fst ds)
132− _ -> case chooseSimplestDictionaries dicts of
133− [] -> throwError . errorMessage $ NoInstanceFound className tys
134− d : _ -> return $ dictionaryValueToValue d
135− -- Choose the simplest DictionaryValues from a list of candidates
136− -- The reason for this function is as follows:
137− -- When considering overlapping instances, we don't want to consider the same dictionary
138− -- to be an overlap of itself when obtained as a superclass of another class.
139− -- Observing that we probably don't want to select a superclass instance when an instance
140− -- is available directly, and that there is no way for a superclass instance to actually
141− -- introduce an overlap that wouldn't have been there already, we simply remove dictionaries
142− -- obtained as superclass instances if there are simpler instances available.
143− chooseSimplestDictionaries :: [DictionaryValue] -> [DictionaryValue]
144− chooseSimplestDictionaries ds = case filter isSimpleDictionaryValue ds of
145− [] -> ds
146− simple -> simple
147− isSimpleDictionaryValue SubclassDictionaryValue{} = False
148− isSimpleDictionaryValue (DependentDictionaryValue _ ds) = all isSimpleDictionaryValue ds
149− isSimpleDictionaryValue _ = True
150− -- |
151− -- Check if two dictionaries are overlapping
152− --
153− -- Dictionaries which are subclass dictionaries cannot overlap, since otherwise the overlap would have
154− -- been caught when constructing superclass dictionaries.
155− --
156− overlapping :: DictionaryValue -> DictionaryValue -> Bool
157− overlapping (LocalDictionaryValue nm1) (LocalDictionaryValue nm2) | nm1 == nm2 = False
158− overlapping (GlobalDictionaryValue nm1) (GlobalDictionaryValue nm2) | nm1 == nm2 = False
159− overlapping (DependentDictionaryValue nm1 ds1) (DependentDictionaryValue nm2 ds2)
160− | nm1 == nm2 = or $ zipWith overlapping ds1 ds2
161− overlapping SubclassDictionaryValue{} _ = False
162− overlapping _ SubclassDictionaryValue{} = False
163− overlapping _ _ = True
164−
165 valUndefined :: Expr
125 valUndefined :: Expr
166 valUndefined = Var (Qualified (Just (ModuleName [ProperName C.prim])) (Ident C.undefined))
126 valUndefined = Var (Qualified (Just (ModuleName [ProperName C.prim])) (Ident C.undefined))
167
127
src/Language/PureScript/TypeChecker/Subsumption.hs+1−1
@@ -69,7 +69,7 @@ subsumes' val ty1 (KindedType ty2 _) =
69 subsumes val ty1 ty2
69 subsumes val ty1 ty2
70subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
70subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
71 dicts <- getTypeClassDictionaries
71 dicts <- getTypeClassDictionaries
72− subsumes' (Just $ foldl App val (map (flip (TypeClassDictionary True) dicts) constraints)) ty1 ty2
72+ subsumes' (Just $ foldl App val (map (flip TypeClassDictionary dicts) constraints)) ty1 ty2
73subsumes' val (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyObject && f2 == tyObject = do
73subsumes' val (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyObject && f2 == tyObject = do
74 let
74 let
75 (ts1, r1') = rowToList r1
75 (ts1, r1') = rowToList r1
src/Language/PureScript/TypeChecker/Types.hs+26−15
@@ -166,7 +166,7 @@ overTypes f = let (_, f', _) = everywhereOnValues id g id in f'
166 where
166 where
167 g :: Expr -> Expr
167 g :: Expr -> Expr
168 g (TypedValue checkTy val t) = TypedValue checkTy val (f t)
168 g (TypedValue checkTy val t) = TypedValue checkTy val (f t)
169− g (TypeClassDictionary b (nm, tys) sco) = TypeClassDictionary b (nm, map f tys) sco
169+ g (TypeClassDictionary (nm, tys) sco) = TypeClassDictionary (nm, map f tys) sco
170 g other = other
170 g other = other
171
171
172-- |
172-- |
@@ -177,9 +177,9 @@ replaceTypeClassDictionaries mn =
177 let (_, f, _) = everywhereOnValuesTopDownM return go return
177 let (_, f, _) = everywhereOnValuesTopDownM return go return
178 in f
178 in f
179 where
179 where
180− go (TypeClassDictionary trySuperclasses constraint dicts) = do
180+ go (TypeClassDictionary constraint dicts) = do
181 env <- getEnv
181 env <- getEnv
182− entails env mn dicts constraint trySuperclasses
182+ entails env mn dicts constraint
183 go other = return other
183 go other = return other
184
184
185-- |
185-- |
@@ -202,7 +202,7 @@ instantiatePolyTypeWithUnknowns val (ForAll ident ty _) = do
202instantiatePolyTypeWithUnknowns val (ConstrainedType constraints ty) = do
202instantiatePolyTypeWithUnknowns val (ConstrainedType constraints ty) = do
203 dicts <- getTypeClassDictionaries
203 dicts <- getTypeClassDictionaries
204 (_, ty') <- instantiatePolyTypeWithUnknowns (error "Types under a constraint cannot themselves be constrained") ty
204 (_, ty') <- instantiatePolyTypeWithUnknowns (error "Types under a constraint cannot themselves be constrained") ty
205− return (foldl App val (map (flip (TypeClassDictionary True) dicts) constraints), ty')
205+ return (foldl App val (map (flip TypeClassDictionary dicts) constraints), ty')
206instantiatePolyTypeWithUnknowns val ty = return (val, ty)
206instantiatePolyTypeWithUnknowns val ty = return (val, ty)
207
207
208-- |
208-- |
@@ -268,7 +268,7 @@ infer' (Var var) = do
268 case ty of
268 case ty of
269 ConstrainedType constraints ty' -> do
269 ConstrainedType constraints ty' -> do
270 dicts <- getTypeClassDictionaries
270 dicts <- getTypeClassDictionaries
271− return $ TypedValue True (foldl App (Var var) (map (flip (TypeClassDictionary True) dicts) constraints)) ty'
271+ return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) constraints)) ty'
272 _ -> return $ TypedValue True (Var var) ty
272 _ -> return $ TypedValue True (Var var) ty
273infer' v@(Constructor c) = do
273infer' v@(Constructor c) = do
274 env <- getEnv
274 env <- getEnv
@@ -292,7 +292,7 @@ infer' (Let ds val) = do
292 return $ TypedValue True (Let ds' val') valTy
292 return $ TypedValue True (Let ds' val') valTy
293infer' (SuperClassDictionary className tys) = do
293infer' (SuperClassDictionary className tys) = do
294 dicts <- getTypeClassDictionaries
294 dicts <- getTypeClassDictionaries
295− return $ TypeClassDictionary False (className, tys) dicts
295+ return $ TypeClassDictionary (className, tys) dicts
296infer' (TypedValue checkType val ty) = do
296infer' (TypedValue checkType val ty) = do
297 Just moduleName <- checkCurrentModule <$> get
297 Just moduleName <- checkCurrentModule <$> get
298 (kind, args) <- liftCheck $ kindOfWithScopedVars ty
298 (kind, args) <- liftCheck $ kindOfWithScopedVars ty
@@ -449,10 +449,25 @@ check' val t@(ConstrainedType constraints ty) = do
449 dictNames <- forM constraints $ \(Qualified _ (ProperName className), _) -> do
449 dictNames <- forM constraints $ \(Qualified _ (ProperName className), _) -> do
450 n <- liftCheck freshDictionaryName
450 n <- liftCheck freshDictionaryName
451 return $ Ident $ "__dict_" ++ className ++ "_" ++ show n
451 return $ Ident $ "__dict_" ++ className ++ "_" ++ show n
452− val' <- withBindingGroupVisible $ withTypeClassDictionaries (zipWith (\name (className, instanceTy) ->
452+ dicts <- join <$> liftCheck (zipWithM (newDictionaries []) (map (Qualified Nothing) dictNames) constraints)
453− TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular False) (map (Qualified Nothing) dictNames)
453+ val' <- withBindingGroupVisible $ withTypeClassDictionaries dicts $ check val ty
454− constraints) $ check val ty
455 return $ TypedValue True (foldr (Abs . Left) val' dictNames) t
454 return $ TypedValue True (foldr (Abs . Left) val' dictNames) t
455+ where
456+ -- | Add a dictionary for the constraint to the scope, and dictionaries
457+ -- for all implies superclass instances.
458+ newDictionaries :: [(Qualified ProperName, Integer)] -> Qualified Ident -> (Qualified ProperName, [Type]) -> Check [TypeClassDictionaryInScope]
459+ newDictionaries path name (className, instanceTy) = do
460+ tcs <- gets (typeClasses . checkEnv)
461+ let (args, _, superclasses) = fromMaybe (error "newDictionaries: type class lookup failed") $ M.lookup className tcs
462+ supDicts <- join <$> zipWithM (\(supName, supArgs) index ->
463+ newDictionaries ((supName, index) : path)
464+ name
465+ (supName, instantiateSuperclass (map fst args) supArgs instanceTy)
466+ ) superclasses [0..]
467+ return (TypeClassDictionaryInScope name path className instanceTy Nothing TCDRegular : supDicts)
468+
469+ instantiateSuperclass :: [String] -> [Type] -> [Type] -> [Type]
470+ instantiateSuperclass args supArgs tys = map (replaceAllTypeVars (zip args tys)) supArgs
456check' val (SaturatedTypeSynonym name args) = do
471check' val (SaturatedTypeSynonym name args) = do
457 ty <- introduceSkolemScope <=< expandTypeSynonym name $ args
472 ty <- introduceSkolemScope <=< expandTypeSynonym name $ args
458 check val ty
473 check val ty
@@ -501,13 +516,9 @@ check' (SuperClassDictionary className tys) _ = do
501 -- TypeClassDictionary placeholder. The reason we do this is that it is necessary to have the
516 -- TypeClassDictionary placeholder. The reason we do this is that it is necessary to have the
502 -- correct super instance dictionaries in scope, and these are not available when the type class
517 -- correct super instance dictionaries in scope, and these are not available when the type class
503 -- declaration gets desugared.
518 -- declaration gets desugared.
504− --
505− -- Note also that the first argument to TypeClassDictionary is False, meaning we _do not_ want
506− -- to consider superclass instances when searching for this dictionary - doing so might lead
507− -- to traversing a cycle in the instance graph.
508 -}
519 -}
509 dicts <- getTypeClassDictionaries
520 dicts <- getTypeClassDictionaries
510− return $ TypeClassDictionary False (className, tys) dicts
521+ return $ TypeClassDictionary (className, tys) dicts
511check' (TypedValue checkType val ty1) ty2 = do
522check' (TypedValue checkType val ty1) ty2 = do
512 Just moduleName <- checkCurrentModule <$> get
523 Just moduleName <- checkCurrentModule <$> get
513 (kind, args) <- liftCheck $ kindOfWithScopedVars ty1
524 (kind, args) <- liftCheck $ kindOfWithScopedVars ty1
@@ -648,7 +659,7 @@ checkFunctionApplication' fn (KindedType ty _) arg ret =
648 checkFunctionApplication fn ty arg ret
659 checkFunctionApplication fn ty arg ret
649checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
660checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
650 dicts <- getTypeClassDictionaries
661 dicts <- getTypeClassDictionaries
651− checkFunctionApplication' (foldl App fn (map (flip (TypeClassDictionary True) dicts) constraints)) fnTy arg ret
662+ checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) constraints)) fnTy arg ret
652checkFunctionApplication' fn fnTy dict@TypeClassDictionary{} _ =
663checkFunctionApplication' fn fnTy dict@TypeClassDictionary{} _ =
653 return (fnTy, App fn dict)
664 return (fnTy, App fn dict)
654checkFunctionApplication' _ fnTy arg _ = throwError . errorMessage $ CannotApplyFunction fnTy arg
665checkFunctionApplication' _ fnTy arg _ = throwError . errorMessage $ CannotApplyFunction fnTy arg
src/Language/PureScript/TypeClassDictionaries.hs+7−19
@@ -26,30 +26,18 @@ import Language.PureScript.Types
26--
26--
27data TypeClassDictionaryInScope
27data TypeClassDictionaryInScope
28 = TypeClassDictionaryInScope {
28 = TypeClassDictionaryInScope {
29− -- |
30− -- The identifier with which the dictionary can be accessed at runtime
29+ -- | The identifier with which the dictionary can be accessed at runtime
31− --
32 tcdName :: Qualified Ident
30 tcdName :: Qualified Ident
33− -- |
31+ -- | How to obtain this instance via superclass relationships
32+ , tcdPath :: [(Qualified ProperName, Integer)]
34− -- The name of the type class to which this type class instance applies
33+ -- | The name of the type class to which this type class instance applies
35− --
36 , tcdClassName :: Qualified ProperName
34 , tcdClassName :: Qualified ProperName
37− -- |
38− -- The types to which this type class instance applies
35+ -- | The types to which this type class instance applies
39− --
40 , tcdInstanceTypes :: [Type]
36 , tcdInstanceTypes :: [Type]
41− -- |
42− -- Type class dependencies which must be satisfied to construct this dictionary
37+ -- | Type class dependencies which must be satisfied to construct this dictionary
43− --
44 , tcdDependencies :: Maybe [Constraint]
38 , tcdDependencies :: Maybe [Constraint]
45− -- |
46− -- The type of this dictionary
39+ -- | The type of this dictionary
47− --
48 , tcdType :: TypeClassDictionaryType
40 , tcdType :: TypeClassDictionaryType
49− -- |
50− -- Is this instance exported by its module?
51− --
52− , tcdExported :: Bool
53 } deriving (Show, Data, Typeable)
41 } deriving (Show, Data, Typeable)
54
42
55-- |
43-- |