Skip to content

Commit 177b800

Browse files
committed
Lkt: emit an error if PropertyError is called without raise
Ensure that PropertyError is called through the raise keyword. TN: U928-029
1 parent 9d665ee commit 177b800

File tree

3 files changed

+122
-37
lines changed

3 files changed

+122
-37
lines changed

contrib/lkt/language/parser.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,17 @@ def check_semantic_impl():
459459
has_error=results.any(lambda r: r.has_error)
460460
)
461461

462+
@langkit_property(return_type=T.LKNode.entity)
463+
def first_no_paren_parent():
464+
"""
465+
Return the first parent that is not a ``ParenExpr``.
466+
"""
467+
return If(
468+
Entity.parent.is_a(ParenExpr),
469+
Entity.parent.first_no_paren_parent(),
470+
Entity.parent
471+
)
472+
462473

463474
class LangkitRoot(LKNode):
464475
"""
@@ -2571,6 +2582,23 @@ def check_correctness_pre():
25712582
)
25722583
)
25732584
)
2585+
# In case of PropertyError, check for RaiseExpr
2586+
._or(
2587+
If(
2588+
And(
2589+
rd.result_ref == Entity.property_error_type,
2590+
Not(Entity.first_no_paren_parent.is_a(T.RaiseExpr))
2591+
),
2592+
2593+
Self.error(
2594+
S("cannot call ")
2595+
.concat(Entity.property_error_type.full_name)
2596+
.concat(S(" outside of a raise expression"))
2597+
).singleton,
2598+
2599+
No(T.SemanticResult.array)
2600+
)
2601+
)
25742602
)
25752603

25762604
@langkit_property(return_type=T.InferInstantiation)
Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
fun prop1(): Bool = raise PropertyError("error")
22
fun prop2(): Bool = (raise PropertyError("error"))
3+
fun prop3(): Bool = raise (PropertyError("error"))
4+
fun prop4(): Bool = raise (((PropertyError("error"))))
5+
6+
# TODO: prop5 and prop6 should be rejected (we don't want any PropertyError
7+
# value living outside of the exception system).
8+
# @invalid fun prop5(): PropertyError = raise PropertyError()
9+
# @invalid fun prop6(): Bool = raise prop5()
310

411
# Invalid because of missing raise keyword
5-
@invalid val prop3: Bool = PropertyError("error")
6-
@invalid val prop4: Bool = (PropertyError("error"))
12+
@invalid val prop7: Bool = PropertyError("error")
13+
@invalid val prop8: Bool = (PropertyError("error"))
714

8-
fun prop5(): Bool = {
15+
fun prop9(): Bool = {
916
val n: Int = 1;
1017

1118
raise PropertyError("Explicit error")
1219
}
1320

1421
# Invalid because only PropertyError can be raised
1522
val i: Int = 1
16-
@invalid fun prop6(): Bool = raise i
23+
@invalid fun prop10(): Bool = raise i

testsuite/tests/contrib/lkt_semantic/property_error/test.out

Lines changed: 83 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,79 +33,129 @@ Expr <RaiseExpr test.lkt:2:22-2:50>
3333
Expr <ParenExpr test.lkt:2:21-2:51>
3434
has type <EnumTypeDecl prelude: "Bool">
3535

36-
Id <RefId "Bool" test.lkt:5:21-5:25>
36+
Id <RefId "Bool" test.lkt:3:14-3:18>
3737
references <EnumTypeDecl prelude: "Bool">
3838

39-
Id <RefId "PropertyError" test.lkt:5:28-5:41>
39+
Id <RefId "PropertyError" test.lkt:3:28-3:41>
4040
references <StructDecl prelude: "PropertyError">
4141

42-
Expr <StringLit test.lkt:5:42-5:49>
42+
Expr <StringLit test.lkt:3:42-3:49>
4343
has type <StructDecl prelude: "String">
4444

45-
test.lkt:5:28: error: Mismatched types: expected `Bool`, got `PropertyError`
46-
5 | @invalid val prop3: Bool = PropertyError("error")
47-
| ^^^^^^^^^^^^^^^^^^^^^^
45+
Expr <CallExpr test.lkt:3:28-3:50>
46+
has type <StructDecl prelude: "PropertyError">
47+
48+
Expr <ParenExpr test.lkt:3:27-3:51>
49+
has type <StructDecl prelude: "PropertyError">
50+
51+
Expr <RaiseExpr test.lkt:3:21-3:51>
52+
has type <EnumTypeDecl prelude: "Bool">
53+
54+
Id <RefId "Bool" test.lkt:4:14-4:18>
55+
references <EnumTypeDecl prelude: "Bool">
56+
57+
Id <RefId "PropertyError" test.lkt:4:30-4:43>
58+
references <StructDecl prelude: "PropertyError">
59+
60+
Expr <StringLit test.lkt:4:44-4:51>
61+
has type <StructDecl prelude: "String">
62+
63+
Expr <CallExpr test.lkt:4:30-4:52>
64+
has type <StructDecl prelude: "PropertyError">
65+
66+
Expr <ParenExpr test.lkt:4:29-4:53>
67+
has type <StructDecl prelude: "PropertyError">
4868

49-
Id <RefId "Bool" test.lkt:6:21-6:25>
69+
Expr <ParenExpr test.lkt:4:28-4:54>
70+
has type <StructDecl prelude: "PropertyError">
71+
72+
Expr <ParenExpr test.lkt:4:27-4:55>
73+
has type <StructDecl prelude: "PropertyError">
74+
75+
Expr <RaiseExpr test.lkt:4:21-4:55>
76+
has type <EnumTypeDecl prelude: "Bool">
77+
78+
Id <RefId "Bool" test.lkt:12:21-12:25>
5079
references <EnumTypeDecl prelude: "Bool">
5180

52-
Id <RefId "PropertyError" test.lkt:6:29-6:42>
81+
test.lkt:12:28: error: cannot call PropertyError outside of a raise expression
82+
12 | @invalid val prop7: Bool = PropertyError("error")
83+
| ^^^^^^^^^^^^^^^^^^^^^^
84+
85+
Id <RefId "PropertyError" test.lkt:12:28-12:41>
86+
references <StructDecl prelude: "PropertyError">
87+
88+
Expr <StringLit test.lkt:12:42-12:49>
89+
has type <StructDecl prelude: "String">
90+
91+
test.lkt:12:28: error: Mismatched types: expected `Bool`, got `PropertyError`
92+
12 | @invalid val prop7: Bool = PropertyError("error")
93+
| ^^^^^^^^^^^^^^^^^^^^^^
94+
95+
Id <RefId "Bool" test.lkt:13:21-13:25>
96+
references <EnumTypeDecl prelude: "Bool">
97+
98+
test.lkt:13:29: error: cannot call PropertyError outside of a raise expression
99+
13 | @invalid val prop8: Bool = (PropertyError("error"))
100+
| ^^^^^^^^^^^^^^^^^^^^^^
101+
102+
Id <RefId "PropertyError" test.lkt:13:29-13:42>
53103
references <StructDecl prelude: "PropertyError">
54104

55-
Expr <StringLit test.lkt:6:43-6:50>
105+
Expr <StringLit test.lkt:13:43-13:50>
56106
has type <StructDecl prelude: "String">
57107

58-
test.lkt:6:29: error: Mismatched types: expected `Bool`, got `PropertyError`
59-
6 | @invalid val prop4: Bool = (PropertyError("error"))
60-
| ^^^^^^^^^^^^^^^^^^^^^^
108+
test.lkt:13:29: error: Mismatched types: expected `Bool`, got `PropertyError`
109+
13 | @invalid val prop8: Bool = (PropertyError("error"))
110+
| ^^^^^^^^^^^^^^^^^^^^^^
61111

62-
test.lkt:6:28: error: Mismatched types: expected `Bool`, got `PropertyError`
63-
6 | @invalid val prop4: Bool = (PropertyError("error"))
64-
| ^^^^^^^^^^^^^^^^^^^^^^^^
112+
test.lkt:13:28: error: Mismatched types: expected `Bool`, got `PropertyError`
113+
13 | @invalid val prop8: Bool = (PropertyError("error"))
114+
| ^^^^^^^^^^^^^^^^^^^^^^^^
65115

66-
Id <RefId "Bool" test.lkt:8:14-8:18>
116+
Id <RefId "Bool" test.lkt:15:14-15:18>
67117
references <EnumTypeDecl prelude: "Bool">
68118

69-
Id <RefId "Int" test.lkt:9:11-9:14>
119+
Id <RefId "Int" test.lkt:16:11-16:14>
70120
references <StructDecl prelude: "Int">
71121

72-
Expr <NumLit test.lkt:9:17-9:18>
122+
Expr <NumLit test.lkt:16:17-16:18>
73123
has type <StructDecl prelude: "Int">
74124

75-
Id <RefId "PropertyError" test.lkt:11:10-11:23>
125+
Id <RefId "PropertyError" test.lkt:18:10-18:23>
76126
references <StructDecl prelude: "PropertyError">
77127

78-
Expr <StringLit test.lkt:11:24-11:40>
128+
Expr <StringLit test.lkt:18:24-18:40>
79129
has type <StructDecl prelude: "String">
80130

81-
Expr <CallExpr test.lkt:11:10-11:41>
131+
Expr <CallExpr test.lkt:18:10-18:41>
82132
has type <StructDecl prelude: "PropertyError">
83133

84-
Expr <RaiseExpr test.lkt:11:4-11:41>
134+
Expr <RaiseExpr test.lkt:18:4-18:41>
85135
has type <EnumTypeDecl prelude: "Bool">
86136

87-
Expr <BlockExpr test.lkt:8:21-12:2>
137+
Expr <BlockExpr test.lkt:15:21-19:2>
88138
has type <EnumTypeDecl prelude: "Bool">
89139

90-
Id <RefId "Int" test.lkt:15:8-15:11>
140+
Id <RefId "Int" test.lkt:22:8-22:11>
91141
references <StructDecl prelude: "Int">
92142

93-
Expr <NumLit test.lkt:15:14-15:15>
143+
Expr <NumLit test.lkt:22:14-22:15>
94144
has type <StructDecl prelude: "Int">
95145

96-
Id <RefId "Bool" test.lkt:16:23-16:27>
146+
Id <RefId "Bool" test.lkt:23:24-23:28>
97147
references <EnumTypeDecl prelude: "Bool">
98148

99-
test.lkt:16:36: error: raised expression needs to be of type `PropertyError`, got `Int`
100-
16 | @invalid fun prop6(): Bool = raise i
101-
| ^
149+
test.lkt:23:37: error: raised expression needs to be of type `PropertyError`, got `Int`
150+
23 | @invalid fun prop10(): Bool = raise i
151+
| ^
102152

103-
Id <RefId "i" test.lkt:16:36-16:37>
104-
references <ValDecl "i" test.lkt:15:1-15:15>
153+
Id <RefId "i" test.lkt:23:37-23:38>
154+
references <ValDecl "i" test.lkt:22:1-22:15>
105155

106-
Expr <RefId "i" test.lkt:16:36-16:37>
156+
Expr <RefId "i" test.lkt:23:37-23:38>
107157
has type <StructDecl prelude: "Int">
108158

109-
Expr <RaiseExpr test.lkt:16:30-16:37>
159+
Expr <RaiseExpr test.lkt:23:31-23:38>
110160
has type <EnumTypeDecl prelude: "Bool">
111161

0 commit comments

Comments
 (0)