git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Type wildcards are disallowed in type synonyms, data declarations, instances. #287
2d01405Phil Freeman
examples/failing/TypeWildcards1.pursnew file+4
@@ -0,0 +1,4 @@
1+module TypeWildcards where
2+
3+type Test = _
4+
examples/failing/TypeWildcards2.pursnew file+4
@@ -0,0 +1,4 @@
1+module TypeWildcards where
2+
3+data Test = Test _
4+
examples/failing/TypeWildcards3.pursnew file+7
@@ -0,0 +1,7 @@
1+module TypeWildcards where
2+
3+data Foo a = Foo
4+
5+instance showFoo :: Show (Foo _) where
6+ show Foo = "Foo"
7+
examples/passing/TypeWildcards.purs+3
@@ -1,5 +1,8 @@
1module Main where
1module Main where
2
2
3+testTopLevel :: _ -> _
4+testTopLevel n = n + 1
5+
3test :: forall a. (Eq a) => (a -> a) -> a -> a
6test :: forall a. (Eq a) => (a -> a) -> a -> a
4test f a = go (f a) a
7test f a = go (f a) a
5 where
8 where
src/Language/PureScript/Parser/Declarations.hs+8−8
@@ -64,7 +64,7 @@ parseDataDeclaration = do
64 tyArgs <- many (indented *> kindedIdent)
64 tyArgs <- many (indented *> kindedIdent)
65 ctors <- P.option [] $ do
65 ctors <- P.option [] $ do
66 _ <- lexeme $ indented *> P.char '='
66 _ <- lexeme $ indented *> P.char '='
67− sepBy1 ((,) <$> properName <*> P.many (indented *> parseTypeAtom)) pipe
67+ sepBy1 ((,) <$> properName <*> P.many (indented *> noWildcards parseTypeAtom)) pipe
68 return $ DataDeclaration dtype name tyArgs ctors
68 return $ DataDeclaration dtype name tyArgs ctors
69
69
70parseTypeDeclaration :: P.Parsec String ParseState Declaration
70parseTypeDeclaration :: P.Parsec String ParseState Declaration
@@ -76,7 +76,7 @@ parseTypeSynonymDeclaration :: P.Parsec String ParseState Declaration
76parseTypeSynonymDeclaration =
76parseTypeSynonymDeclaration =
77 TypeSynonymDeclaration <$> (P.try (reserved "type") *> indented *> properName)
77 TypeSynonymDeclaration <$> (P.try (reserved "type") *> indented *> properName)
78 <*> many (indented *> kindedIdent)
78 <*> many (indented *> kindedIdent)
79− <*> (lexeme (indented *> P.char '=') *> parsePolyType)
79+ <*> (lexeme (indented *> P.char '=') *> noWildcards parsePolyType)
80
80
81parseValueDeclaration :: P.Parsec String ParseState Declaration
81parseValueDeclaration :: P.Parsec String ParseState Declaration
82parseValueDeclaration = do
82parseValueDeclaration = do
@@ -106,16 +106,16 @@ parseExternDeclaration = P.try (reserved "foreign") *> indented *> reserved "imp
106 <|> (do reserved "instance"
106 <|> (do reserved "instance"
107 name <- parseIdent <* lexeme (indented *> P.string "::")
107 name <- parseIdent <* lexeme (indented *> P.string "::")
108 deps <- P.option [] $ do
108 deps <- P.option [] $ do
109− deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many parseTypeAtom))
109+ deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many (noWildcards parseTypeAtom)))
110 indented
110 indented
111 reservedOp "=>"
111 reservedOp "=>"
112 return deps
112 return deps
113 className <- indented *> parseQualified properName
113 className <- indented *> parseQualified properName
114− tys <- P.many (indented *> parseTypeAtom)
114+ tys <- P.many (indented *> noWildcards parseTypeAtom)
115 return $ ExternInstanceDeclaration name deps className tys)
115 return $ ExternInstanceDeclaration name deps className tys)
116 <|> (do ident <- parseIdent
116 <|> (do ident <- parseIdent
117 js <- P.optionMaybe (JSRaw <$> stringLiteral)
117 js <- P.optionMaybe (JSRaw <$> stringLiteral)
118− ty <- lexeme (indented *> P.string "::") *> parsePolyType
118+ ty <- lexeme (indented *> P.string "::") *> noWildcards parsePolyType
119 return $ ExternDeclaration (if isJust js then InlineJavascript else ForeignImport) ident js ty))
119 return $ ExternDeclaration (if isJust js then InlineJavascript else ForeignImport) ident js ty))
120
120
121parseAssociativity :: P.Parsec String ParseState Associativity
121parseAssociativity :: P.Parsec String ParseState Associativity
@@ -176,7 +176,7 @@ parseTypeClassDeclaration = do
176 reserved "class"
176 reserved "class"
177 implies <- P.option [] $ do
177 implies <- P.option [] $ do
178 indented
178 indented
179− implies <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many parseTypeAtom))
179+ implies <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many (noWildcards parseTypeAtom)))
180 reservedOp "<="
180 reservedOp "<="
181 return implies
181 return implies
182 className <- indented *> properName
182 className <- indented *> properName
@@ -191,12 +191,12 @@ parseTypeInstanceDeclaration = do
191 reserved "instance"
191 reserved "instance"
192 name <- parseIdent <* lexeme (indented *> P.string "::")
192 name <- parseIdent <* lexeme (indented *> P.string "::")
193 deps <- P.optionMaybe $ do
193 deps <- P.optionMaybe $ do
194− deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many parseTypeAtom))
194+ deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many (noWildcards parseTypeAtom)))
195 indented
195 indented
196 reservedOp "=>"
196 reservedOp "=>"
197 return deps
197 return deps
198 className <- indented *> parseQualified properName
198 className <- indented *> parseQualified properName
199− ty <- P.many (indented *> parseTypeAtom)
199+ ty <- P.many (indented *> (noWildcards parseTypeAtom))
200 members <- P.option [] . P.try $ do
200 members <- P.option [] . P.try $ do
201 indented *> reserved "where"
201 indented *> reserved "where"
202 mark (P.many (same *> positioned parseValueDeclaration))
202 mark (P.many (same *> positioned parseValueDeclaration))
src/Language/PureScript/Parser/Types.hs+10
@@ -16,6 +16,7 @@
16module Language.PureScript.Parser.Types (
16module Language.PureScript.Parser.Types (
17 parseType,
17 parseType,
18 parsePolyType,
18 parsePolyType,
19+ noWildcards,
19 parseTypeAtom
20 parseTypeAtom
20) where
21) where
21
22
@@ -112,6 +113,15 @@ parseType = do
112parsePolyType :: P.Parsec String ParseState Type
113parsePolyType :: P.Parsec String ParseState Type
113parsePolyType = parseAnyType
114parsePolyType = parseAnyType
114
115
116+-- |
117+-- Parse an atomic type with no wildcards
118+--
119+noWildcards :: P.Parsec String ParseState Type -> P.Parsec String ParseState Type
120+noWildcards p = do
121+ ty <- p
122+ when (containsWildcards ty) $ P.unexpected "type wildcard"
123+ return ty
124+
115parseNameAndType :: P.Parsec String ParseState t -> P.Parsec String ParseState (String, t)
125parseNameAndType :: P.Parsec String ParseState t -> P.Parsec String ParseState (String, t)
116parseNameAndType p = (,) <$> (indented *> (identifierName <|> stringLiteral) <* indented <* lexeme (P.string "::")) <*> p
126parseNameAndType p = (,) <$> (indented *> (identifierName <|> stringLiteral) <* indented <* lexeme (P.string "::")) <*> p
117
127
src/Language/PureScript/Types.hs+10
@@ -219,6 +219,16 @@ moveQuantifiersToFront = go [] []
219 [] -> constrained
219 [] -> constrained
220 qs' -> foldl (\ty' (q, sco) -> ForAll q ty' sco) constrained qs'
220 qs' -> foldl (\ty' (q, sco) -> ForAll q ty' sco) constrained qs'
221
221
222+-- |
223+-- Check if a type contains wildcards
224+--
225+containsWildcards :: Type -> Bool
226+containsWildcards = everythingOnTypes (||) go
227+ where
228+ go :: Type -> Bool
229+ go TypeWildcard = True
230+ go _ = False
231+
222--
232--
223-- Traversals
233-- Traversals
224--
234--