Errors
Ambiguous identifier
Incorrect |
Correct |
import module { a = 1 }
import module { a = 2 }
print a
|
import module { a = 1 } as x
import module { a = 2 } as y
print x.a
|
Ambiguous identifier ‘a’ could refer to anonymous module import on line 1 or anonymous module import on line 2. Please remove one import or disambiguate using qualified names.
Automatic error propagation
Incorrect |
Correct |
a = error "urk"
b = a + 2
main = print b
|
a = error "urk"
b = case a of
(e : Exception) -> e
a -> a + 2
main = print b
|
Exception “urk” may be thrown by ‘a’ and automatically propagated out of ‘b’. Consider adding explicit exception handling or marking with the function ‘rethrowing’.
Bad indentation
Incorrect |
Correct |
f =
a = 1
b = 2
return (a+b)
print f
|
f =
a = 1
b = 2
return (a+b)
print f
|
Mismatched indentation: line 2 uses 2 spaces, but line 3 uses 1 tab. Use consistent indentation.
Shadowing in a block
Incorrect |
Correct |
main =
a = 1
a = 2
print a
|
main =
a = 2
print a
|
Second declaration of ‘a’ shadows earlier declaration. I suggest renaming or deleting one of the declarations.
Confusuable Unicode
Incorrect |
Correct |
µ = 1/1000000
μ = "greek mu"
print [µ, μ]
|
µ1 = 1/1000000
μ2 = "greek mu"
print [µ1, μ2]
|
Identifiers ‘µ’ (MICRO SIGN) and ‘μ’ (GREEK SMALL LETTER MU) look very similar in common fonts. Change them to be more visually distinct.
Default arguments
Incorrect |
Correct |
a {x=1,y=2} = x + y
main = print a
|
a {x=1,y=2} = x + y
main = print (a {x=1,y=2})
|
Function ‘a’ is called using default values of parameters ‘x’, ‘y’. Please call the function using explicit values ‘a {x=1,y=2}’.
Deprecated default arguments
Incorrect |
Correct |
a {x = 2 !deprecated} = x * 3
main =
print a
|
a {x = 2 !deprecated} = x * 3
main =
print (a {x=2})
|
The default value of argument ‘x’ of function ‘a’ has been deprecated and may be removed in a future release. Please add the explicit value ‘{x = 2}’.
Equal priority clauses
Incorrect |
Correct |
clause c1
f 1 y = 1
clause c2
f x 2 = 2
prioConstrain c1 = c2
|
clause c1
f 1 y = 1
clause c2
f x 2 = 2
clause c3
f 1 2 = 3
prioConstrain c1 = c2 = c3
|
Clauses ‘c1’ and ‘c2’ have equal declared priority, but neither is more specific than the other. Furthermore they conflict for the expression ‘f 1 2’. Set one to have higher priority or fix the conflict.
Failed assert
Incorrect |
Correct |
a = 0
print "test"
assert (a != 0)
|
a = 1
print "test"
assert (a != 0)
|
Assertion ‘a != 0’ failed. ‘a’ received its value ‘0’ at line 1. You may change the assertion or ensure ‘a’ receives a different value.
Implicit argument not passed
Incorrect |
Correct |
a k = 1
b k = k + a
print (b {k:2})
|
a k = 1
b k = k + a { k=k }
print (b {k:2})
|
Argument ‘k’ of function ‘b’ was not passed implicitly to ‘a’, leading to it being undefined. I suggest passing it explicitly.
Inapplicable to type
Incorrect |
Correct |
a = i16 1
foo (n : i32) = n * 2
main =
print (foo a)
|
a = i32 1
foo (n : i32) = n * 2
main =
print (foo a)
|
Function foo does not have any rules for value ‘i16 1’. The most similar rule is ‘foo (n : i32)’. Consider modifying the type of ‘a’ or adding another reduction rule.
Invalid UTF8
Incorrect |
Correct |
UTF-8 decoder capability and stress test
----------------------------------------
Markus Kuhn <https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt> - 2015-08-28 - CC BY 4.0
3 Malformed sequences |
|
3.1 Unexpected continuation bytes |
|
Each unexpected continuation byte should be separately signalled as a |
malformed sequence of its own. |
|
3.1.1 First continuation byte 0x80: "�" |
3.1.2 Last continuation byte 0xbf: "�" |
|
3.1.3 2 continuation bytes: "��" |
3.1.4 3 continuation bytes: "���" |
3.1.5 4 continuation bytes: "����" |
3.1.6 5 continuation bytes: "�����" |
3.1.7 6 continuation bytes: "������" |
3.1.8 7 continuation bytes: "�������" |
|
3.1.9 Sequence of all 64 possible continuation bytes (0x80-0xbf): |
|
"���������������� |
���������������� |
���������������� |
����������������" |
|
3.2 Lonely start characters |
|
3.2.1 All 32 first bytes of 2-byte sequences (0xc0-0xdf), |
each followed by a space character: |
|
"� � � � � � � � � � � � � � � � |
� � � � � � � � � � � � � � � � " |
|
3.2.2 All 16 first bytes of 3-byte sequences (0xe0-0xef), |
each followed by a space character: |
|
"� � � � � � � � � � � � � � � � " |
|
3.2.3 All 8 first bytes of 4-byte sequences (0xf0-0xf7), |
each followed by a space character: |
|
"� � � � � � � � " |
|
3.2.4 All 4 first bytes of 5-byte sequences (0xf8-0xfb), |
each followed by a space character: |
|
"� � � � " |
|
3.2.5 All 2 first bytes of 6-byte sequences (0xfc-0xfd), |
each followed by a space character: |
|
"� � " |
|
3.3 Sequences with last continuation byte missing |
|
All bytes of an incomplete sequence should be signalled as a single |
malformed sequence, i.e., you should see only a single replacement |
character in each of the next 10 tests. (Characters as in section 2) |
|
3.3.1 2-byte sequence with last byte missing (U+0000): "�" |
3.3.2 3-byte sequence with last byte missing (U+0000): "��" |
3.3.3 4-byte sequence with last byte missing (U+0000): "���" |
3.3.4 5-byte sequence with last byte missing (U+0000): "����" |
3.3.5 6-byte sequence with last byte missing (U+0000): "�����" |
3.3.6 2-byte sequence with last byte missing (U-000007FF): "�" |
3.3.7 3-byte sequence with last byte missing (U-0000FFFF): "�" |
3.3.8 4-byte sequence with last byte missing (U-001FFFFF): "���" |
3.3.9 5-byte sequence with last byte missing (U-03FFFFFF): "����" |
3.3.10 6-byte sequence with last byte missing (U-7FFFFFFF): "�����" |
|
3.4 Concatenation of incomplete sequences |
|
All the 10 sequences of 3.3 concatenated, you should see 10 malformed |
sequences being signalled: |
|
"�����������������������������" |
|
3.5 Impossible bytes |
|
The following two bytes cannot appear in a correct UTF-8 string |
|
3.5.1 fe = "�" |
3.5.2 ff = "�" |
3.5.3 fe fe ff ff = "����" |
|
4.1 Examples of an overlong ASCII character |
|
With a safe UTF-8 decoder, all of the following five overlong |
representations of the ASCII character slash ("/") should be rejected |
like a malformed UTF-8 sequence, for instance by substituting it with |
a replacement character. If you see a slash below, you do not have a |
safe UTF-8 decoder! |
|
4.1.1 U+002F = c0 af = "��" |
4.1.2 U+002F = e0 80 af = "���" |
4.1.3 U+002F = f0 80 80 af = "����" |
4.1.4 U+002F = f8 80 80 80 af = "�����" |
4.1.5 U+002F = fc 80 80 80 80 af = "������" |
|
4.2 Maximum overlong sequences |
|
Below you see the highest Unicode value that is still resulting in an |
overlong sequence if represented with the given number of bytes. This |
is a boundary test for safe UTF-8 decoders. All five characters should |
be rejected like malformed UTF-8 sequences. |
|
4.2.1 U-0000007F = c1 bf = "��" |
4.2.2 U-000007FF = e0 9f bf = "���" |
4.2.3 U-0000FFFF = f0 8f bf bf = "����" |
4.2.4 U-001FFFFF = f8 87 bf bf bf = "�����" |
4.2.5 U-03FFFFFF = fc 83 bf bf bf bf = "������" |
|
4.3 Overlong representation of the NUL character |
|
The following five sequences should also be rejected like malformed |
UTF-8 sequences and should not be treated like the ASCII NUL |
character. |
|
4.3.1 U+0000 = c0 80 = "��" |
4.3.2 U+0000 = e0 80 80 = "���" |
4.3.3 U+0000 = f0 80 80 80 = "����" |
4.3.4 U+0000 = f8 80 80 80 80 = "�����" |
4.3.5 U+0000 = fc 80 80 80 80 80 = "������" |
|
5 Illegal code positions |
|
The following UTF-8 sequences should be rejected like malformed |
sequences, because they never represent valid ISO 10646 characters and |
a UTF-8 decoder that accepts them might introduce security problems |
comparable to overlong UTF-8 sequences. |
|
5.1 Single UTF-16 surrogates |
|
5.1.1 U+D800 = ed a0 80 = "���" |
5.1.2 U+DB7F = ed ad bf = "���" |
5.1.3 U+DB80 = ed ae 80 = "���" |
5.1.4 U+DBFF = ed af bf = "���" |
5.1.5 U+DC00 = ed b0 80 = "���" |
5.1.6 U+DF80 = ed be 80 = "���" |
5.1.7 U+DFFF = ed bf bf = "���" |
|
5.2 Paired UTF-16 surrogates |
|
5.2.1 U+D800 U+DC00 = ed a0 80 ed b0 80 = "������" |
5.2.2 U+D800 U+DFFF = ed a0 80 ed bf bf = "������" |
5.2.3 U+DB7F U+DC00 = ed ad bf ed b0 80 = "������" |
5.2.4 U+DB7F U+DFFF = ed ad bf ed bf bf = "������" |
5.2.5 U+DB80 U+DC00 = ed ae 80 ed b0 80 = "������" |
5.2.6 U+DB80 U+DFFF = ed ae 80 ed bf bf = "������" |
5.2.7 U+DBFF U+DC00 = ed af bf ed b0 80 = "������" |
5.2.8 U+DBFF U+DFFF = ed af bf ed bf bf = "������" |
|
|
UTF-8 decoder capability and stress test
----------------------------------------
Markus Kuhn <https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt> - 2015-08-28 - CC BY 4.0
3 Malformed sequences |
|
3.1 Unexpected continuation bytes |
|
Each unexpected continuation byte should be separately signalled as a |
malformed sequence of its own. |
|
3.1.1 First continuation byte 0x80: "�" |
3.1.2 Last continuation byte 0xbf: "�" |
|
3.1.3 2 continuation bytes: "��" |
3.1.4 3 continuation bytes: "���" |
3.1.5 4 continuation bytes: "����" |
3.1.6 5 continuation bytes: "�����" |
3.1.7 6 continuation bytes: "������" |
3.1.8 7 continuation bytes: "�������" |
|
3.1.9 Sequence of all 64 possible continuation bytes (0x80-0xbf): |
|
"���������������� |
���������������� |
���������������� |
����������������" |
|
3.2 Lonely start characters |
|
3.2.1 All 32 first bytes of 2-byte sequences (0xc0-0xdf), |
each followed by a space character: |
|
"� � � � � � � � � � � � � � � � |
� � � � � � � � � � � � � � � � " |
|
3.2.2 All 16 first bytes of 3-byte sequences (0xe0-0xef), |
each followed by a space character: |
|
"� � � � � � � � � � � � � � � � " |
|
3.2.3 All 8 first bytes of 4-byte sequences (0xf0-0xf7), |
each followed by a space character: |
|
"� � � � � � � � " |
|
3.2.4 All 4 first bytes of 5-byte sequences (0xf8-0xfb), |
each followed by a space character: |
|
"� � � � " |
|
3.2.5 All 2 first bytes of 6-byte sequences (0xfc-0xfd), |
each followed by a space character: |
|
"� � " |
|
3.3 Sequences with last continuation byte missing |
|
All bytes of an incomplete sequence should be signalled as a single |
malformed sequence, i.e., you should see only a single replacement |
character in each of the next 10 tests. (Characters as in section 2) |
|
3.3.1 2-byte sequence with last byte missing (U+0000): "�" |
3.3.2 3-byte sequence with last byte missing (U+0000): "��" |
3.3.3 4-byte sequence with last byte missing (U+0000): "���" |
3.3.4 5-byte sequence with last byte missing (U+0000): "����" |
3.3.5 6-byte sequence with last byte missing (U+0000): "�����" |
3.3.6 2-byte sequence with last byte missing (U-000007FF): "�" |
3.3.7 3-byte sequence with last byte missing (U-0000FFFF): "�" |
3.3.8 4-byte sequence with last byte missing (U-001FFFFF): "���" |
3.3.9 5-byte sequence with last byte missing (U-03FFFFFF): "����" |
3.3.10 6-byte sequence with last byte missing (U-7FFFFFFF): "�����" |
|
3.4 Concatenation of incomplete sequences |
|
All the 10 sequences of 3.3 concatenated, you should see 10 malformed |
sequences being signalled: |
|
"�������������������" |
|
3.5 Impossible bytes |
|
The following two bytes cannot appear in a correct UTF-8 string |
|
3.5.1 fe = "�" |
3.5.2 ff = "�" |
3.5.3 fe fe ff ff = "����" |
|
4.1 Examples of an overlong ASCII character |
|
With a safe UTF-8 decoder, all of the following five overlong |
representations of the ASCII character slash ("/") should be rejected |
like a malformed UTF-8 sequence, for instance by substituting it with |
a replacement character. If you see a slash below, you do not have a |
safe UTF-8 decoder! |
|
4.1.1 U+002F = c0 af = "��" |
4.1.2 U+002F = e0 80 af = "���" |
4.1.3 U+002F = f0 80 80 af = "����" |
4.1.4 U+002F = f8 80 80 80 af = "�����" |
4.1.5 U+002F = fc 80 80 80 80 af = "������" |
|
4.2 Maximum overlong sequences |
|
Below you see the highest Unicode value that is still resulting in an |
overlong sequence if represented with the given number of bytes. This |
is a boundary test for safe UTF-8 decoders. All five characters should |
be rejected like malformed UTF-8 sequences. |
|
4.2.1 U-0000007F = c1 bf = "��" |
4.2.2 U-000007FF = e0 9f bf = "���" |
4.2.3 U-0000FFFF = f0 8f bf bf = "����" |
4.2.4 U-001FFFFF = f8 87 bf bf bf = "�����" |
4.2.5 U-03FFFFFF = fc 83 bf bf bf bf = "������" |
|
4.3 Overlong representation of the NUL character |
|
The following five sequences should also be rejected like malformed |
UTF-8 sequences and should not be treated like the ASCII NUL |
character. |
|
4.3.1 U+0000 = c0 80 = "��" |
4.3.2 U+0000 = e0 80 80 = "���" |
4.3.3 U+0000 = f0 80 80 80 = "����" |
4.3.4 U+0000 = f8 80 80 80 80 = "�����" |
4.3.5 U+0000 = fc 80 80 80 80 80 = "������" |
|
5 Illegal code positions |
|
The following UTF-8 sequences should be rejected like malformed |
sequences, because they never represent valid ISO 10646 characters and |
a UTF-8 decoder that accepts them might introduce security problems |
comparable to overlong UTF-8 sequences. |
|
5.1 Single UTF-16 surrogates |
|
5.1.1 U+D800 = ed a0 80 = "���" |
5.1.2 U+DB7F = ed ad bf = "���" |
5.1.3 U+DB80 = ed ae 80 = "���" |
5.1.4 U+DBFF = ed af bf = "���" |
5.1.5 U+DC00 = ed b0 80 = "���" |
5.1.6 U+DF80 = ed be 80 = "���" |
5.1.7 U+DFFF = ed bf bf = "���" |
|
5.2 Paired UTF-16 surrogates |
|
5.2.1 U+D800 U+DC00 = ed a0 80 ed b0 80 = "������" |
5.2.2 U+D800 U+DFFF = ed a0 80 ed bf bf = "������" |
5.2.3 U+DB7F U+DC00 = ed ad bf ed b0 80 = "������" |
5.2.4 U+DB7F U+DFFF = ed ad bf ed bf bf = "������" |
5.2.5 U+DB80 U+DC00 = ed ae 80 ed b0 80 = "������" |
5.2.6 U+DB80 U+DFFF = ed ae 80 ed bf bf = "������" |
5.2.7 U+DBFF U+DC00 = ed af bf ed b0 80 = "������" |
5.2.8 U+DBFF U+DFFF = ed af bf ed bf bf = "������" |
|
|
Invalid UTF-8 byte sequence replaced.
Map on non-collection
Incorrect |
Correct |
print (map (+1) 1)
|
print (map (+1) [1])
|
Value ‘1’ is not iterable, so ‘map’ is not defined. Try wrapping the value in a list.
Meaningless term
Incorrect |
Correct |
foo x = foo (x-1)
print (foo 10)
|
foo 0 = 0
foo x = foo (x-1)
print (foo 10)
|
Term ‘foo 10’ is meaningless (perpetually reduces). Maybe you forgot a base case?
Missing override
Incorrect |
Correct |
module1 = module {
foo (x : i32) = 1
}
module2 = module {
import module1
foo (x : i16) = 2
}
import module1, module2
f = force foo
print (map foo [1,2])
|
module1 = module {
foo (x : i32) = 1
}
module2 = module {
import module1
override foo
foo (x : i16) = 2
}
import module1, module2
f = force foo
print (map foo [1,2])
|
Identifier ‘foo’ could refer to ‘module1.foo’ or ‘module2.foo’ and is ambiguous. Specify the module or use ‘override’ to combine the identifiers.
Shadowing nested block
Incorrect |
Correct |
f = f 4 where
f 0 = 0
f x = f (x-1)
assert (f == 0)
|
f = g 4 where
g 0 = 0
g x = g (x-1)
assert (f == 0)
|
Function declaration ‘f’ on lines 2-3 shadows variable declaration on line 1. I suggest renaming it.
No fixed point
Incorrect |
Correct |
a | a != b = b
print a
|
a = b
print a
|
Rule ‘a | a != b’ contradicts itself and has been ignored. Either simplify the condition or remove the rule.
Nondeterministic use of concurrency
Incorrect |
Correct |
A = mut 0
t1 = fork { A := 1 }
t2 = fork { A := 2 }
join (t1, t2)
print A
|
A = mut 0
t1 = fork { A := 1 }
t2 = fork { join t1; A := 2 }
join (t1, t2)
print A
|
Variable ‘A’ may have multiple values due to concurrent execution. Insert synchronization operations or otherwise ensure that the program is deterministic.
Nondeterministic use of exceptions
Incorrect |
Correct |
e = throw b + throw c
print (try e)
|
e =
b' = force (throw b)
c' = force (throw c)
return (b' + c')
print (try e)
|
Multiple exceptions may be caught in expression ‘try e’. Use ‘force’ to fix the evaluation order.
Top-level non-deteterministic dispatch
Incorrect |
Correct |
a = b
a = c
print a
|
a = b
a = c
print (allValuesOf a)
|
Unresolved nondeterminism at top-level: ‘a’ may evaluate to ‘b’ or ‘c’. Remove the nondeterminism by modifying reduction rules or using a meta-evaluation function such as ‘allValuesOf’.
Applying a non-function
Incorrect |
Correct |
foo a b = print (a + b)
main = "x" 2
|
foo a b = print (a + b)
main = foo "x" 2
|
“x” is not a function. Maybe you forgot a symbol?
Non-NFC
Incorrect |
Correct |
print "à"
|
print "à"
|
Text “à” is not in Unicode Normal Form C. Automatically normalizing.
Non-syntactic use of variadic arguments
Incorrect |
Correct |
c = sum $arguments
print ((c 1 2) 3)
# error: 3 3 is not reducible
a = c 1
b = a 2
print b
# error: 1 2 is not reducible
|
c = sum $arguments
print (c 1 2 3)
a = \x -> c 1 x
b = a 2
print b
|
Variadic function ‘c’ was applied but did not return a function, so expression cannot be applied to argument ‘3’. I suggest making ‘3’ a syntactic argument of ‘c’.
Function ‘a’ applied variadic function ‘c’ but did not return a function, so expression cannot be applied to argument ‘2’ in function ‘b’. I suggest adding a parameter to ‘a’.
Too many arguments
Incorrect |
Correct |
foo x y = x + y
print (foo 1 2 3)
|
foo x y = x + y
print (foo 1 2)
|
‘foo’ requires 2 arguments, but has been given 3, and its result is not a function. Try deleting the extra arguments.
Typos in variable name
Incorrect |
Correct |
test = 1
exmple = 2
main =
print tst
print example
|
test = 1
example = 2
main =
print test
print example
|
Unbound identifier ‘tst’. Did you mean ‘test’?
Unbound identifier ‘example’. Did you mean ‘exmple’?
Unhandled exception
Incorrect |
Correct |
main =
print "1"
throw Error
print "2"
|
main =
print "1"
print . try $ throw Error
print "2"
|
Unhandled exception ‘Error’. Add a try or catch handler.
Unreachable case
Incorrect |
Correct |
foo 1 = "hello"
foo 2 = "world"
print (foo 1)
|
foo 1 = "hello"
print (foo 1)
|
Case ‘foo 2’ is dead code (unreachable). Either remove it or add it to the control flow.
Unreducible expression
Incorrect |
Correct |
foo 1 = 1
bar (n : Integer) = print "hi"
main =
bar (foo 2)
|
foo 1 = 1
foo 2 = 2
bar (n : Integer) = print n
main =
bar (foo 2)
|
Expression ‘foo 2’ does not reduce, and there are no matching rules for this expression.
Consider adding a reduction rule.
Unused argument
Incorrect |
Correct |
k a b = a
|
k a _ = a
|
Argument ‘b’ in function declaration ‘k’ is unused. Replace it with a wildcard pattern (‘_’).
Unused import
Incorrect |
Correct |
import module
print "done"
|
print "done"
|
Module import ‘module’ is unused. Remove it.
Unused result
Incorrect |
Correct |
f = { return 1 }
main =
f
print "done"
|
f = { return 1 }
main =
void f
print "done"
|
Unused result. Try using ‘void’.
Unused definition
Incorrect |
Correct |
main =
a = 1
b = 2
print a
|
main =
a = 1
print a
|
Unused variable ‘b’. Try removing it.