Skip to content

Commit 4f1d41f

Browse files
Adjust Gradle configuration and introduce allWarningsAsErrors (#3466)
* Also, add tests that verify our disabled assertions * Fix nullability in AgentPremain that used to work by accident (because we disabled those assertions) * Fix all corresponding warnings Co-authored-by: Dmitry Khalanskiy <[email protected]>
1 parent 85a2601 commit 4f1d41f

File tree

20 files changed

+113
-35
lines changed

20 files changed

+113
-35
lines changed

build.gradle

+1-12
Original file line numberDiff line numberDiff line change
@@ -168,18 +168,7 @@ configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != core
168168
apply plugin: "bom-conventions"
169169

170170
// Configure subprojects with Kotlin sources
171-
configure(subprojects.findAll { !sourceless.contains(it.name) }) {
172-
// Use atomicfu plugin, it also adds all the necessary dependencies
173-
apply plugin: 'kotlinx-atomicfu'
174-
175-
// Configure options for all Kotlin compilation tasks
176-
tasks.withType(AbstractKotlinCompile).all {
177-
kotlinOptions.freeCompilerArgs += OptInPreset.optInAnnotations.collect { "-Xopt-in=" + it }
178-
kotlinOptions.freeCompilerArgs += "-progressive"
179-
// Remove null assertions to get smaller bytecode on Android
180-
kotlinOptions.freeCompilerArgs += ["-Xno-param-assertions", "-Xno-receiver-assertions", "-Xno-call-assertions"]
181-
}
182-
}
171+
apply plugin: "configure-compilation-conventions"
183172

184173
if (build_snapshot_train) {
185174
println "Hacking test tasks, removing stress and flaky tests"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
import org.jetbrains.kotlin.gradle.tasks.*
6+
7+
configure(subprojects) {
8+
if (name in sourceless) return@configure
9+
apply(plugin = "kotlinx-atomicfu")
10+
val projectName = name
11+
tasks.withType(KotlinCompile::class).all {
12+
val isMainTaskName = name == "compileKotlin" || name == "compileKotlinJvm"
13+
kotlinOptions {
14+
if (isMainTaskName) {
15+
allWarningsAsErrors = true
16+
}
17+
val newOptions =
18+
listOf(
19+
"-progressive", "-Xno-param-assertions", "-Xno-receiver-assertions",
20+
"-Xno-call-assertions"
21+
) + optInAnnotations.map { "-opt-in=$it" }
22+
freeCompilerArgs = freeCompilerArgs + newOptions
23+
}
24+
}
25+
}

kotlinx-coroutines-core/common/src/channels/AbstractChannel.kt

+17-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5+
@file:Suppress("UNCHECKED_CAST", "UNUSED_PARAMETER")
6+
57
package kotlinx.coroutines.channels
68

79
import kotlinx.atomicfu.*
@@ -16,6 +18,7 @@ import kotlin.jvm.*
1618
/**
1719
* Abstract send channel. It is a base class for all send channel implementations.
1820
*/
21+
@Suppress("UNCHECKED_CAST", "UNUSED_PARAMETER")
1922
internal abstract class AbstractSendChannel<E>(
2023
@JvmField protected val onUndeliveredElement: OnUndeliveredElement<E>?
2124
) : SendChannel<E> {
@@ -122,7 +125,12 @@ internal abstract class AbstractSendChannel<E>(
122125
return sendSuspend(element)
123126
}
124127

125-
@Suppress("DEPRECATION", "DEPRECATION_ERROR")
128+
@Suppress("DEPRECATION_ERROR")
129+
@Deprecated(
130+
level = DeprecationLevel.ERROR,
131+
message = "Deprecated in the favour of 'trySend' method",
132+
replaceWith = ReplaceWith("trySend(element).isSuccess")
133+
) // see super()
126134
override fun offer(element: E): Boolean {
127135
// Temporary migration for offer users who rely on onUndeliveredElement
128136
try {
@@ -705,6 +713,11 @@ internal abstract class AbstractChannel<E>(
705713
onCancellationConstructor = onUndeliveredElementReceiveCancellationConstructor
706714
)
707715

716+
@Deprecated(
717+
message = "Deprecated in favor of onReceiveCatching extension",
718+
level = DeprecationLevel.ERROR,
719+
replaceWith = ReplaceWith("onReceiveCatching")
720+
) // See super()
708721
override val onReceiveOrNull: SelectClause1<E?>
709722
get() = SelectClause1Impl<E?>(
710723
clauseObject = this,
@@ -726,7 +739,7 @@ internal abstract class AbstractChannel<E>(
726739
if (selectResult is Closed<*>) throw selectResult.receiveException
727740
else selectResult as E
728741

729-
private fun processResultSelectReceiveCatching(ignoredParam: Any?, selectResult: Any?): Any? =
742+
private fun processResultSelectReceiveCatching(ignoredParam: Any?, selectResult: Any?): Any =
730743
if (selectResult is Closed<*>) ChannelResult.closed(selectResult.closeCause)
731744
else ChannelResult.success(selectResult as E)
732745

@@ -735,8 +748,8 @@ internal abstract class AbstractChannel<E>(
735748
else selectResult as E
736749

737750
private val onUndeliveredElementReceiveCancellationConstructor: OnCancellationConstructor? = onUndeliveredElement?.let {
738-
{ select: SelectInstance<*>, ignoredParam: Any?, element: Any? ->
739-
{ cause: Throwable -> if (element !is Closed<*>) onUndeliveredElement.callUndeliveredElement(element as E, select.context) }
751+
{ select: SelectInstance<*>, _: Any?, element: Any? ->
752+
{ _: Throwable -> if (element !is Closed<*>) onUndeliveredElement.callUndeliveredElement(element as E, select.context) }
740753
}
741754
}
742755

kotlinx-coroutines-core/common/src/channels/ArrayChannel.kt

+4-3
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,10 @@ internal open class ArrayChannel<E>(
158158
// Too late, already cancelled, but we removed it from the queue and need to notify on undelivered element.
159159
// The only exception is when this "send" operation is an `onSend` clause that has to be re-registered
160160
// in the corresponding `select` invocation.
161-
val send = send!!
162-
if (!(send is SendElementSelectWithUndeliveredHandler<*> && send.trySelectResult == REREGISTER))
163-
send.undeliveredElement()
161+
send!!.apply {
162+
if (!(this is SendElementSelectWithUndeliveredHandler<*> && trySelectResult == REREGISTER))
163+
undeliveredElement()
164+
}
164165
}
165166
}
166167
if (replacement !== POLL_FAILED && replacement !is Closed<*>) {

kotlinx-coroutines-core/common/src/channels/Broadcast.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@ public fun <E> ReceiveChannel<E>.broadcast(
4747
start: CoroutineStart = CoroutineStart.LAZY
4848
): BroadcastChannel<E> {
4949
val scope = GlobalScope + Dispatchers.Unconfined + CoroutineExceptionHandler { _, _ -> }
50+
val channel = this
5051
// We can run this coroutine in the context that ignores all exceptions, because of `onCompletion = consume()`
5152
// which passes all exceptions upstream to the source ReceiveChannel
5253
return scope.broadcast(capacity = capacity, start = start, onCompletion = { cancelConsumed(it) }) {
53-
for (e in this@broadcast) {
54+
for (e in channel) {
5455
send(e)
5556
}
5657
}

kotlinx-coroutines-core/common/src/channels/Channel.kt

+1
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ public interface ReceiveChannel<out E> {
360360
*
361361
* @suppress **Deprecated**: in favor of onReceiveCatching extension.
362362
*/
363+
@Suppress("DEPRECATION_ERROR")
363364
@Deprecated(
364365
message = "Deprecated in favor of onReceiveCatching extension",
365366
level = DeprecationLevel.ERROR,

kotlinx-coroutines-core/common/src/internal/DispatchedContinuation.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ internal class DispatchedContinuation<in T>(
207207

208208
// We inline it to save an entry on the stack in cases where it shows (unconfined dispatcher)
209209
// It is used only in Continuation<T>.resumeCancellableWith
210+
@Suppress("NOTHING_TO_INLINE")
210211
inline fun resumeCancellableWith(
211212
result: Result<T>,
212213
noinline onCancellation: ((cause: Throwable) -> Unit)?
@@ -235,7 +236,7 @@ internal class DispatchedContinuation<in T>(
235236
}
236237

237238
// inline here is to save us an entry on the stack for the sake of better stacktraces
238-
239+
@Suppress("NOTHING_TO_INLINE")
239240
inline fun resumeCancelled(state: Any?): Boolean {
240241
val job = context[Job]
241242
if (job != null && !job.isActive) {
@@ -247,6 +248,7 @@ internal class DispatchedContinuation<in T>(
247248
return false
248249
}
249250

251+
@Suppress("NOTHING_TO_INLINE")
250252
inline fun resumeUndispatchedWith(result: Result<T>) {
251253
withContinuationContext(continuation, countOrElement) {
252254
continuation.resumeWith(result)

kotlinx-coroutines-core/common/src/internal/DispatchedTask.kt

-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ internal fun <T> DispatchedTask<T>.dispatch(mode: Int) {
167167
}
168168
}
169169

170-
@Suppress("UNCHECKED_CAST")
171170
internal fun <T> DispatchedTask<T>.resume(delegate: Continuation<T>, undispatched: Boolean) {
172171
// This resume is never cancellable. The result is always delivered to delegate continuation.
173172
val state = takeState()

kotlinx-coroutines-core/jvm/src/channels/Actor.kt

+7-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,12 @@ private class LazyActorCoroutine<E>(
162162
return super.send(element)
163163
}
164164

165-
@Suppress("DEPRECATION", "DEPRECATION_ERROR")
165+
@Suppress("DEPRECATION_ERROR")
166+
@Deprecated(
167+
level = DeprecationLevel.ERROR,
168+
message = "Deprecated in the favour of 'trySend' method",
169+
replaceWith = ReplaceWith("trySend(element).isSuccess")
170+
) // See super()
166171
override fun offer(element: E): Boolean {
167172
start()
168173
return super.offer(element)
@@ -181,6 +186,7 @@ private class LazyActorCoroutine<E>(
181186
return closed
182187
}
183188

189+
@Suppress("UNCHECKED_CAST")
184190
override val onSend: SelectClause2<E, SendChannel<E>> get() = SelectClause2Impl(
185191
clauseObject = this,
186192
regFunc = LazyActorCoroutine<*>::onSendRegFunction as RegistrationFunction,

kotlinx-coroutines-core/jvm/src/debug/AgentPremain.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ internal object AgentPremain {
2626
}.getOrNull() ?: DebugProbesImpl.enableCreationStackTraces
2727

2828
@JvmStatic
29+
@Suppress("UNUSED_PARAMETER")
2930
fun premain(args: String?, instrumentation: Instrumentation) {
3031
AgentInstallationType.isInstalledStatically = true
3132
instrumentation.addTransformer(DebugProbesTransformer)
@@ -36,13 +37,13 @@ internal object AgentPremain {
3637

3738
internal object DebugProbesTransformer : ClassFileTransformer {
3839
override fun transform(
39-
loader: ClassLoader,
40+
loader: ClassLoader?,
4041
className: String,
4142
classBeingRedefined: Class<*>?,
4243
protectionDomain: ProtectionDomain,
4344
classfileBuffer: ByteArray?
4445
): ByteArray? {
45-
if (className != "kotlin/coroutines/jvm/internal/DebugProbesKt") {
46+
if (loader == null || className != "kotlin/coroutines/jvm/internal/DebugProbesKt") {
4647
return null
4748
}
4849
/*

kotlinx-coroutines-core/jvm/src/internal/MainDispatchers.kt

-3
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,6 @@ private class MissingMainCoroutineDispatcher(
9898
override fun limitedParallelism(parallelism: Int): CoroutineDispatcher =
9999
missing()
100100

101-
override suspend fun delay(time: Long) =
102-
missing()
103-
104101
override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle =
105102
missing()
106103

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
package kotlinx.coroutines
5+
6+
import kotlinx.coroutines.*
7+
import org.junit.Test
8+
import kotlin.test.*
9+
10+
11+
class NoParamAssertionsTest : TestBase() {
12+
// These tests verify that we haven't omitted "-Xno-param-assertions" and "-Xno-receiver-assertions"
13+
14+
@Test
15+
fun testNoReceiverAssertion() {
16+
val function: (ThreadLocal<Int>, Int) -> ThreadContextElement<Int> = ThreadLocal<Int>::asContextElement
17+
@Suppress("UNCHECKED_CAST")
18+
val unsafeCasted = function as ((ThreadLocal<Int>?, Int) -> ThreadContextElement<Int>)
19+
unsafeCasted(null, 42)
20+
}
21+
22+
@Test
23+
fun testNoParamAssertion() {
24+
val function: (ThreadLocal<Any>, Any) -> ThreadContextElement<Any> = ThreadLocal<Any>::asContextElement
25+
@Suppress("UNCHECKED_CAST")
26+
val unsafeCasted = function as ((ThreadLocal<Any?>?, Any?) -> ThreadContextElement<Any>)
27+
unsafeCasted(ThreadLocal.withInitial { Any() }, null)
28+
}
29+
}

kotlinx-coroutines-test/common/src/TestCoroutineScheduler.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public class TestCoroutineScheduler : AbstractCoroutineContextElement(TestCorout
9797
currentTime = event.time
9898
event
9999
}
100-
event.dispatcher.processEvent(event.time, event.marker)
100+
event.dispatcher.processEvent(event.marker)
101101
return true
102102
}
103103

@@ -132,7 +132,7 @@ public class TestCoroutineScheduler : AbstractCoroutineContextElement(TestCorout
132132
val event = synchronized(lock) {
133133
events.removeFirstIf { it.time <= timeMark } ?: return
134134
}
135-
event.dispatcher.processEvent(event.time, event.marker)
135+
event.dispatcher.processEvent(event.marker)
136136
}
137137
}
138138

@@ -173,7 +173,7 @@ public class TestCoroutineScheduler : AbstractCoroutineContextElement(TestCorout
173173
}
174174
}
175175
}
176-
event.dispatcher.processEvent(event.time, event.marker)
176+
event.dispatcher.processEvent(event.marker)
177177
}
178178
}
179179

kotlinx-coroutines-test/common/src/TestDispatcher.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public abstract class TestDispatcher internal constructor() : CoroutineDispatche
2323
public abstract val scheduler: TestCoroutineScheduler
2424

2525
/** Notifies the dispatcher that it should process a single event marked with [marker] happening at time [time]. */
26-
internal fun processEvent(time: Long, marker: Any) {
26+
internal fun processEvent(marker: Any) {
2727
check(marker is Runnable)
2828
marker.run()
2929
}

kotlinx-coroutines-test/jvm/src/migration/TestBuildersDeprecated.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ public fun runTestWithLegacyScope(
159159
context: CoroutineContext = EmptyCoroutineContext,
160160
dispatchTimeoutMs: Long = DEFAULT_DISPATCH_TIMEOUT_MS,
161161
testBody: suspend TestCoroutineScope.() -> Unit
162-
): TestResult {
162+
) {
163163
if (context[RunningInRunTest] != null)
164164
throw IllegalStateException("Calls to `runTest` can't be nested. Please read the docs on `TestResult` for details.")
165165
val testScope = TestBodyCoroutine(createTestCoroutineScope(context + RunningInRunTest))

kotlinx-coroutines-test/jvm/src/migration/TestCoroutineDispatcher.kt

+12
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ public class TestCoroutineDispatcher(public override val scheduler: TestCoroutin
6161
scheduler.registerEvent(this, 0, block, context) { false }
6262

6363
/** @suppress */
64+
@Deprecated(
65+
"Please use a dispatcher that is paused by default, like `StandardTestDispatcher`.",
66+
level = DeprecationLevel.WARNING
67+
)
6468
override suspend fun pauseDispatcher(block: suspend () -> Unit) {
6569
val previous = dispatchImmediately
6670
dispatchImmediately = false
@@ -72,11 +76,19 @@ public class TestCoroutineDispatcher(public override val scheduler: TestCoroutin
7276
}
7377

7478
/** @suppress */
79+
@Deprecated(
80+
"Please use a dispatcher that is paused by default, like `StandardTestDispatcher`.",
81+
level = DeprecationLevel.WARNING
82+
)
7583
override fun pauseDispatcher() {
7684
dispatchImmediately = false
7785
}
7886

7987
/** @suppress */
88+
@Deprecated(
89+
"Please use a dispatcher that is paused by default, like `StandardTestDispatcher`.",
90+
level = DeprecationLevel.WARNING
91+
)
8092
override fun resumeDispatcher() {
8193
dispatchImmediately = true
8294
}

kotlinx-coroutines-test/jvm/src/migration/TestCoroutineExceptionHandler.kt

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public interface UncaughtExceptionCaptor {
4242
/**
4343
* An exception handler that captures uncaught exceptions in tests.
4444
*/
45+
@Suppress("DEPRECATION")
4546
@Deprecated(
4647
"Deprecated for removal without a replacement. " +
4748
"It may be to define one's own `CoroutineExceptionHandler` if you just need to handle '" +

kotlinx-coroutines-test/jvm/src/migration/TestCoroutineScope.kt

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ private class TestCoroutineScopeImpl(
8686
/** These jobs existed before the coroutine scope was used, so it's alright if they don't get cancelled. */
8787
private val initialJobs = coroutineContext.activeJobs()
8888

89+
@Deprecated("Please call `runTest`, which automatically performs the cleanup, instead of using this function.")
8990
override fun cleanupTestCoroutines() {
9091
val delayController = coroutineContext.delayController
9192
val hasUnfinishedJobs = if (delayController != null) {

reactive/kotlinx-coroutines-reactor/src/ReactorFlow.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ private class FlowAsFlux<T : Any>(
3232
private val flow: Flow<T>,
3333
private val context: CoroutineContext
3434
) : Flux<T>() {
35-
override fun subscribe(subscriber: CoreSubscriber<in T>?) {
36-
if (subscriber == null) throw NullPointerException()
35+
override fun subscribe(subscriber: CoreSubscriber<in T>) {
3736
val hasContext = !subscriber.currentContext().isEmpty
3837
val source = if (hasContext) flow.flowOn(subscriber.currentContext().asCoroutineContext()) else flow
3938
subscriber.onSubscribe(FlowSubscription(source, subscriber, context))

reactive/kotlinx-coroutines-rx3/src/RxMaybe.kt

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ private class RxMaybeCoroutine<T>(
4343
) : AbstractCoroutine<T>(parentContext, false, true) {
4444
override fun onCompleted(value: T) {
4545
try {
46+
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // KT-54201
4647
if (value == null) subscriber.onComplete() else subscriber.onSuccess(value)
4748
} catch (e: Throwable) {
4849
handleUndeliverableException(e, context)

0 commit comments

Comments
 (0)