From e80f967ebb3de801acc27060cf11fcb80f7f9ee2 Mon Sep 17 00:00:00 2001 From: "hoc081098@gmail.com" Date: Sun, 27 Apr 2025 22:24:10 +0700 Subject: [PATCH] Add UnsafeResultValueAccess annotation to Result class for safer value access --- .../main/kotlin/kotlin-conventions.gradle.kts | 1 + .../com/github/michaelbull/result/Result.kt | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/buildSrc/src/main/kotlin/kotlin-conventions.gradle.kts b/buildSrc/src/main/kotlin/kotlin-conventions.gradle.kts index 6e94e33..dafcb00 100644 --- a/buildSrc/src/main/kotlin/kotlin-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/kotlin-conventions.gradle.kts @@ -59,6 +59,7 @@ kotlin { all { languageSettings.apply { optIn("kotlin.contracts.ExperimentalContracts") + optIn("com.github.michaelbull.result.UnsafeResultValueAccess") } } diff --git a/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Result.kt b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Result.kt index 804c926..aa7b689 100644 --- a/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Result.kt +++ b/kotlin-result/src/commonMain/kotlin/com/github/michaelbull/result/Result.kt @@ -51,10 +51,12 @@ public value class Result internal constructor( private val inlineValue: Any?, ) { + @UnsafeResultValueAccess @Suppress("UNCHECKED_CAST") public val value: V get() = inlineValue as V + @UnsafeResultValueAccess @Suppress("UNCHECKED_CAST") public val error: E get() = (inlineValue as Failure).error @@ -102,3 +104,19 @@ private class Failure( return "Failure($error)" } } + +/** + * Marks access to [Result.value] or [Result.error] as potentially unsafe unless the [Result] + * is explicitly checked for [Result.isOk] or [Result.isErr] beforehand. + * + * Ensure that you verify the [Result] state using [Result.isOk] or [Result.isErr] before accessing its value. + * Alternatively, consider using the [Result.fold] function to safely handle the result. + */ +@RequiresOptIn( + level = RequiresOptIn.Level.ERROR, + message = "Accessing Result.value or Result.error without checking the Result state may lead to unsafe behavior.", +) +@MustBeDocumented +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.PROPERTY) +public annotation class UnsafeResultValueAccess