Skip to content

Commit 020cf55

Browse files
committed
Check for unhashable types in type-annotations
1 parent f9a8ebe commit 020cf55

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1710,6 +1710,17 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
17101710
if (AST::is_a<AST::Name_t>(*s->m_slice) || AST::is_a<AST::Subscript_t>(*s->m_slice)) {
17111711
ASR::ttype_t *type = ast_expr_to_asr_type(loc, *s->m_slice,
17121712
is_allocatable, is_const, raise_error, abi, is_argument);
1713+
if (!is_hashable(type)) {
1714+
diag.add(diag::Diagnostic(
1715+
"Unhashable type: '" + ASRUtils::type_to_str(type) + "'",
1716+
diag::Level::Error, diag::Stage::Semantic, {
1717+
diag::Label("Mutable type '" + ASRUtils::type_to_str(type)
1718+
+ "' cannot be stored in a set.",
1719+
{s->m_slice->base.loc})
1720+
})
1721+
);
1722+
throw SemanticAbort();
1723+
}
17131724
return ASRUtils::TYPE(ASR::make_Set_t(al, loc, type));
17141725
} else {
17151726
throw SemanticError("Only Name in Subscript supported for now in `set`"
@@ -1745,6 +1756,17 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
17451756
}
17461757
ASR::ttype_t *key_type = ast_expr_to_asr_type(loc, *t->m_elts[0],
17471758
is_allocatable, is_const, raise_error, abi, is_argument);
1759+
if (!is_hashable(key_type)) {
1760+
diag.add(diag::Diagnostic(
1761+
"Unhashable type: '" + ASRUtils::type_to_str(key_type) + "'",
1762+
diag::Level::Error, diag::Stage::Semantic, {
1763+
diag::Label("Mutable type '" + ASRUtils::type_to_str(key_type)
1764+
+ "' cannot become a key in dict. Hint: Use an immutable type for key.",
1765+
{t->m_elts[0]->base.loc})
1766+
})
1767+
);
1768+
throw SemanticAbort();
1769+
}
17481770
ASR::ttype_t *value_type = ast_expr_to_asr_type(loc, *t->m_elts[1],
17491771
is_allocatable, is_const, raise_error, abi, is_argument);
17501772
raise_error_when_dict_key_is_float_or_complex(key_type, loc);
@@ -3788,7 +3810,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
37883810
ai.m_step, type, nullptr);
37893811
return false;
37903812
} else if (ASR::is_a<ASR::Dict_t>(*type)) {
3791-
throw SemanticError("unhashable type in dict: 'slice'", loc);
3813+
throw SemanticError("Unhashable type in dict: 'slice'", loc);
37923814
}
37933815
} else if(AST::is_a<AST::Tuple_t>(*m_slice) &&
37943816
ASRUtils::is_array(type)) {
@@ -6106,8 +6128,15 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
61066128
if (key_type == nullptr) {
61076129
key_type = ASRUtils::expr_type(key);
61086130
if (!is_hashable(key_type)) {
6109-
throw SemanticError("unhashable type: '" + ASRUtils::type_to_str(key_type) + "'",
6110-
key->base.loc);
6131+
diag.add(diag::Diagnostic(
6132+
"Unhashable type: '" + ASRUtils::type_to_str(key_type) + "'",
6133+
diag::Level::Error, diag::Stage::Semantic, {
6134+
diag::Label("Mutable type '" + ASRUtils::type_to_str(key_type)
6135+
+ "' cannot become a key in dict. Hint: Use an immutable type for key.",
6136+
{key->base.loc})
6137+
})
6138+
);
6139+
throw SemanticAbort();
61116140
}
61126141
} else {
61136142
if (!ASRUtils::check_equal_type(ASRUtils::expr_type(key), key_type)) {
@@ -6579,8 +6608,15 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
65796608
if (type == nullptr) {
65806609
type = ASRUtils::expr_type(value);
65816610
if (!is_hashable(type)) {
6582-
throw SemanticError("unhashable type: '" + ASRUtils::type_to_str(type) + "'",
6583-
type->base.loc);
6611+
diag.add(diag::Diagnostic(
6612+
"Unhashable type: '" + ASRUtils::type_to_str(type) + "'",
6613+
diag::Level::Error, diag::Stage::Semantic, {
6614+
diag::Label("Mutable type '" + ASRUtils::type_to_str(type)
6615+
+ "' cannot be stored in a set.",
6616+
{value->base.loc})
6617+
})
6618+
);
6619+
throw SemanticAbort();
65846620
}
65856621
} else {
65866622
if (!ASRUtils::check_equal_type(ASRUtils::expr_type(value), type)) {

0 commit comments

Comments
 (0)