list.insert() causes inconsistent error messages
In the following we define two function-equivalent code snippets, i.e., test1.py and test2.py. "if 'abc' in a:pass" uses the same value of a, i.e., None, while the error messages are different for the two test programs. I think the output of test2.py is the expected behavior.
test1.py
l = [None]
l[0] = {'abc': 5}
l.insert(0, None)
a = l[0]
print(a) # None
if 'abc' in a:pass
The output of test1.py
None
ValueError: optional is None
Raised from: std.internal.types.optional.unwrap:0
/home/xxm/Desktop/Codon/codon-linux-x86_64/codon-deploy/lib/codon/stdlib/internal/types/optional.codon:80:5
Aborted (core dumped)
test2.py
l = [None]
#l[0] = {'abc': 5}
#l.insert(0, None)
a = l[0]
print(a) # None
if 'abc' in a:pass
The output of test2.py:
test.py:355:4-14: error: 'NoneType' object has no attribute '__contains__'
Reproduce step:
download the Pre-built binaries for Linux Type " codon run --release test.py" in the console.
Environment: Ubuntu 18.04 Codon v0.16.0
The output of l in codon is reasonable because it has the type List[Optional[Dict[str, int]]] under codon's auto type deduction rule. However, this can be confusing because the type is implicit.
@xiaxinmeng As @learnforpractice noted, that is the expected behavior.
There are two different lists: the first is of type List[Optional[Dict[str, int]]] and the second is of type List[Optional].
a: List[Optional] = [None]
n = a[0]
print(type(n) is Optional) # True
temp = {'abc': 5}
a: List[Optional[Dict[str, int]]] = []
a.append(None)
a.append(temp)
n = a[0] # None
d = a[1] # {'abc': 5}
print(type(n) is Optional) # False
print(type(n) is Optional[Dict[str, int]]) # True
print(type(d) is Optional) # False
print(type(d) is Optional[Dict[str, int]]) # True
l = [None]
l[0] = {'abc': 5} # List[Optional[Dict[str, int]]]
l.insert(0, None)
n = l[0] # None
d = l[1] # {'abc': 5}
print(type(n) is Optional) # False
print(type(n) is Optional[Dict[str, int]]) # True
print(type(d) is Optional) # False
print(type(d) is Optional[Dict[str, int]]) # True
Yes, this is the expected behaviour as 'abc' in a checks for the presence of 'abc' in None (which is of type Optional[Dict[str, int]]. As None has no data, it throws optional is None.
Better error messaging is added to #604.