Skip to content

Commit 9643a1e

Browse files
committed
sema: fix missing return statement analysis for infinite iterations
1 parent d1b1d71 commit 9643a1e

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

std/jule/sema/sema.jule

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2995,9 +2995,6 @@ impl missingRetChecker {
29952995
fn checkInfinite(self, it: uintptr, mut s: &Scope): bool {
29962996
mut lead := self.lead
29972997
hard := self.hard
2998-
defer {
2999-
self.lead = lead
3000-
}
30012998

30022999
// Clear lead label data for now.
30033000
self.lead = nil
@@ -3037,10 +3034,27 @@ impl missingRetChecker {
30373034
ret false
30383035
}
30393036
}
3040-
}
3041-
3042-
// Save the hard register, there is nothing to breaker for infinite loop.
3043-
// Avoid goto statements, because they are in this iteration.
3037+
// There is no old lead or the new lead more close to the root scope,
3038+
// do not fallback to the old lead, because we have report it to parent
3039+
// infinite loop analysis, if any. This lead might be breaker for it.
3040+
//
3041+
// Scheme on pseudo AST
3042+
// ╭──────────────────────╮
3043+
// │ fn example() { │
3044+
// │ for { │
3045+
// │ for { │
3046+
// │ goto Foo │ < jumps to below, out of even the root infinite iteration
3047+
// │ } │ if we clear the current lead, analysis of the root iteration
3048+
// │ } │ will not be aware of it is breaked
3049+
// │ Foo: │
3050+
// │ } │
3051+
// ╰──────────────────────╯
3052+
if lead == nil || lead.Scope.ChildIndex > self.lead.Scope.ChildIndex {
3053+
lead = self.lead
3054+
}
3055+
}
3056+
3057+
self.lead = lead
30443058
self.hard = hard
30453059

30463060
// Time to catch break statements for the iteration.

std/jule/sema/sema_test.jule

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,49 @@ fn test()!: int {
436436
}
437437
}
438438
}
439+
`,
440+
err: true,
441+
},
442+
{
443+
code: `
444+
fn test(): int {
445+
for {
446+
for {
447+
for {
448+
goto Foo
449+
}
450+
}
451+
Foo:
452+
}
453+
}
454+
`,
455+
err: false,
456+
},
457+
{
458+
code: `
459+
fn test(): int {
460+
{
461+
for {
462+
for {
463+
goto Foo
464+
}
465+
}
466+
Foo:
467+
}
468+
}
469+
`,
470+
err: true,
471+
},
472+
{
473+
code: `
474+
fn test(): int {
475+
for {
476+
for {
477+
goto Foo
478+
}
479+
}
480+
Foo:
481+
}
439482
`,
440483
err: true,
441484
},

0 commit comments

Comments
 (0)