From db1b7f800358ffbc87a35c11ccbaec64a80967c4 Mon Sep 17 00:00:00 2001 From: Walter Smuts Date: Thu, 14 Sep 2023 13:06:58 +0200 Subject: [PATCH 1/4] Add test case for exhausive branch returns Since the current behaviour is not the desired behaviour I add a case enforcing the current behaviour. On the commit that changes the behaviour we change this test aswel. That way we maintain the invariant that all commits pass the tests. --- .../EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 Tests/EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo diff --git a/Tests/EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo b/Tests/EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo new file mode 100644 index 000000000..e7fdd7c11 --- /dev/null +++ b/Tests/EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo @@ -0,0 +1,9 @@ +//- compileAndRun expecting: failure + +public fun main() { + let _ = f() +} + +public fun f() -> Int { + if true { return 0 } else { return 1 } +} //! diagnostic missing return in function expected to return 'Int' From 27e34180ea302e4e50a63d4260776fc8cdeb69fc Mon Sep 17 00:00:00 2001 From: Walter Smuts Date: Fri, 15 Sep 2023 11:50:23 +0200 Subject: [PATCH 2/4] Add special case for return type missing in DI --- .../Analysis/Module+NormalizeObjectStates.swift | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Sources/IR/Analysis/Module+NormalizeObjectStates.swift b/Sources/IR/Analysis/Module+NormalizeObjectStates.swift index 16bbc2986..156cf4520 100644 --- a/Sources/IR/Analysis/Module+NormalizeObjectStates.swift +++ b/Sources/IR/Analysis/Module+NormalizeObjectStates.swift @@ -534,6 +534,16 @@ extension Module { if o.value == .full(.initialized) { return } if k == .set { + // If the parameter is a return value (index == 0) we emit specialised diagnostics + if case .parameter(_, let index) = p, index == 0 { + let t = self[f].output + if !t.isVoidOrNever { + diagnostics.insert( + .missingFunctionReturn(expectedReturnType: t, at: site) + ) + return + } + } diagnostics.insert( .uninitializedSetParameter(beforeReturningFrom: f, in: self, at: site)) return @@ -991,4 +1001,11 @@ extension Diagnostic { .error("use of uninitialized object", at: site) } + fileprivate static func missingFunctionReturn( + expectedReturnType: AnyType, + at site: SourceRange + ) -> Diagnostic { + .error("missing return in function expected to return '\(expectedReturnType)'", at: site) + } + } From 9cc296bee5ea601b1c43ad976ffe46f4bbc65486 Mon Sep 17 00:00:00 2001 From: Walter Smuts Date: Fri, 1 Sep 2023 09:17:59 +0200 Subject: [PATCH 3/4] Remove blanket failure for void/never return This also inverts the negative test --- Sources/IR/Emitter.swift | 10 +--------- .../TestCases/ExhaustiveBranchReturns.hylo | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Sources/IR/Emitter.swift b/Sources/IR/Emitter.swift index bf746b5eb..eaa2b7c3d 100644 --- a/Sources/IR/Emitter.swift +++ b/Sources/IR/Emitter.swift @@ -233,9 +233,7 @@ struct Emitter { ) -> SourceRange { switch emit(braceStmt: b) { case .next: - if !canonical(returnType).isVoidOrNever { - report(.error(missingReturn: returnType, at: .empty(atEndOf: ast[b].site))) - } else { + if canonical(returnType).isVoidOrNever { emitStore(value: .void, to: returnValue!, at: .empty(atEndOf: ast[b].site)) } return ast[b].site @@ -2587,12 +2585,6 @@ extension Diagnostic { .error("integer literal '\(s)' overflows when stored into '\(t)'", at: site) } - fileprivate static func error( - missingReturn returnType: AnyType, at site: SourceRange - ) -> Diagnostic { - .error("missing return in function expected to return '\(returnType)'", at: site) - } - fileprivate static func warning(unreachableStatement s: AnyStmtID, in ast: AST) -> Diagnostic { .error("statement will never be executed", at: .empty(at: ast[s].site.first())) } diff --git a/Tests/EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo b/Tests/EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo index e7fdd7c11..4775ef85d 100644 --- a/Tests/EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo +++ b/Tests/EndToEndTests/TestCases/ExhaustiveBranchReturns.hylo @@ -1,4 +1,4 @@ -//- compileAndRun expecting: failure +//- compileAndRun expecting: success public fun main() { let _ = f() @@ -6,4 +6,4 @@ public fun main() { public fun f() -> Int { if true { return 0 } else { return 1 } -} //! diagnostic missing return in function expected to return 'Int' +} From b076201cc32218e6af685fd36f2efae47821d250 Mon Sep 17 00:00:00 2001 From: Dimi Racordon Date: Fri, 15 Sep 2023 13:14:28 +0200 Subject: [PATCH 4/4] Update Sources/IR/Analysis/Module+NormalizeObjectStates.swift --- Sources/IR/Analysis/Module+NormalizeObjectStates.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/IR/Analysis/Module+NormalizeObjectStates.swift b/Sources/IR/Analysis/Module+NormalizeObjectStates.swift index 156cf4520..9858540fe 100644 --- a/Sources/IR/Analysis/Module+NormalizeObjectStates.swift +++ b/Sources/IR/Analysis/Module+NormalizeObjectStates.swift @@ -534,8 +534,8 @@ extension Module { if o.value == .full(.initialized) { return } if k == .set { - // If the parameter is a return value (index == 0) we emit specialised diagnostics - if case .parameter(_, let index) = p, index == 0 { + // If the parameter is a return value (index == 0) we emit specialized diagnostics. + if case .parameter(_, 0) = p { let t = self[f].output if !t.isVoidOrNever { diagnostics.insert(