0
# Annotation Backports
1
2
Scala 2.13 annotations made available on earlier Scala versions to enable forward compatibility and consistent code across versions.
3
4
## @nowarn Annotation
5
6
```scala { .api }
7
class nowarn extends scala.annotation.StaticAnnotation
8
```
9
10
Suppresses compiler warnings for the annotated element. This annotation was introduced in Scala 2.13.2 and 2.12.13.
11
12
### Compatibility Behavior
13
14
- **Scala 2.13.2+ and 2.12.13+**: Full warning suppression functionality
15
- **Scala 2.11 and earlier 2.12 versions**: No-op annotation (present but does not suppress warnings)
16
- **Purpose**: Enables forward compatibility when writing code that targets multiple Scala versions
17
18
### Usage
19
20
#### Method-Level Suppression
21
22
```scala
23
import scala.annotation.nowarn
24
25
class Example {
26
@nowarn
27
def deprecatedMethodUsage(): String = {
28
// This would normally produce a deprecation warning
29
someDeprecatedMethod()
30
}
31
32
@nowarn("cat=deprecation")
33
def specificWarningSuppress(): Int = {
34
// Suppress only deprecation warnings
35
anotherDeprecatedMethod()
36
}
37
}
38
```
39
40
#### Expression-Level Suppression
41
42
```scala
43
import scala.annotation.nowarn
44
45
def processData(): Unit = {
46
val result = (computeValue(): @nowarn)
47
48
// Suppress warnings for a specific expression
49
val x = {
50
someOperationWithWarnings()
51
}: @nowarn
52
}
53
```
54
55
#### Class-Level Suppression
56
57
```scala
58
import scala.annotation.nowarn
59
60
@nowarn
61
class LegacyClass {
62
// All warnings in this class are suppressed
63
def method1(): Unit = deprecatedCall1()
64
def method2(): Unit = deprecatedCall2()
65
}
66
```
67
68
### Warning Categories
69
70
On Scala versions that support it, `@nowarn` can target specific warning categories:
71
72
```scala
73
@nowarn("cat=deprecation") // Suppress deprecation warnings
74
@nowarn("cat=unused") // Suppress unused warnings
75
@nowarn("cat=lint") // Suppress linting warnings
76
@nowarn("cat=other") // Suppress other warnings
77
78
// Multiple categories
79
@nowarn("cat=deprecation&unused")
80
81
// Pattern-based suppression
82
@nowarn("msg=.*is deprecated.*")
83
```
84
85
## @unused Annotation
86
87
```scala { .api }
88
class unused extends scala.annotation.StaticAnnotation
89
```
90
91
Indicates that the annotated element is intentionally unused, suppressing "unused" warnings from the compiler.
92
93
### Usage
94
95
#### Parameter Suppression
96
97
```scala
98
import scala.annotation.unused
99
100
def processCallback(
101
data: String,
102
@unused metadata: Map[String, String] // Metadata not used but part of API
103
): String = {
104
data.toUpperCase
105
}
106
107
// Function with unused parameters
108
def eventHandler(
109
event: Event,
110
@unused timestamp: Long, // Timestamp for future use
111
@unused source: String // Source for debugging
112
): Unit = {
113
println(s"Processing event: $event")
114
}
115
```
116
117
#### Variable Suppression
118
119
```scala
120
import scala.annotation.unused
121
122
def complexComputation(): Int = {
123
val result = expensiveComputation()
124
@unused val debugInfo = gatherDebugInfo() // For debugging, not used in production
125
result
126
}
127
```
128
129
#### Import Suppression
130
131
```scala
132
import scala.annotation.unused
133
import scala.collection.mutable.Map // Used in code
134
@unused import scala.util.Random // Imported for conditional compilation
135
```
136
137
## Cross-Version Compatibility Examples
138
139
### Conditional Compilation with @nowarn
140
141
```scala
142
import scala.annotation.nowarn
143
144
class CrossVersionCode {
145
def parseNumber(s: String): Option[Int] = {
146
// Different implementations for different Scala versions
147
148
// Scala 2.13+ has toIntOption
149
try {
150
s.toIntOption // This method exists in 2.13+
151
} catch {
152
case _: NoSuchMethodError =>
153
// Fallback for older versions
154
(try { Some(s.toInt) } catch { case _: NumberFormatException => None }): @nowarn
155
}
156
}
157
158
@nowarn("cat=deprecation")
159
def legacyApiUsage(): String = {
160
// Using deprecated API that we need for backward compatibility
161
someDeprecatedApiCall()
162
}
163
}
164
```
165
166
### Library Migration Support
167
168
```scala
169
import scala.annotation.{nowarn, unused}
170
import scala.collection.compat._
171
172
class MigrationHelper {
173
@nowarn("cat=unused")
174
def processCollection[T](
175
data: Traversable[T],
176
@unused processingHint: String = "default" // Future parameter
177
): List[T] = {
178
179
// Use compat library for cross-version support
180
data.toList
181
.tap(list => println(s"Processing ${list.size} items"))
182
.filter(_ != null)
183
}
184
185
@nowarn("cat=deprecation")
186
def bridgeOldAndNewApi(): Unit = {
187
// Calling both old and new APIs during migration period
188
val oldResult = callOldDeprecatedApi()
189
val newResult = callNewApi()
190
reconcileResults(oldResult, newResult)
191
}
192
}
193
```
194
195
### Testing with Intentionally Unused Code
196
197
```scala
198
import scala.annotation.unused
199
200
class TestHelpers {
201
// Test utilities that might not be used in all test suites
202
@unused
203
def createTestUser(name: String = "test"): User = User(name)
204
205
@unused
206
def mockDatabase(): Database = new InMemoryDatabase()
207
208
// Test that has setup code for future test cases
209
@nowarn("cat=unused")
210
def setupComplexTest(): Unit = {
211
@unused val testData = generateLargeTestDataset()
212
@unused val mockServices = setupMockServices()
213
214
// Current test is simple, but setup is ready for expansion
215
assertTrue(true)
216
}
217
}
218
```
219
220
### Conditional API Features
221
222
```scala
223
import scala.annotation.{nowarn, unused}
224
225
trait ApiTrait {
226
def coreMethod(): String
227
228
// Optional method that might not be implemented by all classes
229
@unused
230
def optionalMethod(): Option[String] = None
231
}
232
233
class BasicImplementation extends ApiTrait {
234
def coreMethod(): String = "basic"
235
236
// Don't implement optional method - annotation prevents warning
237
}
238
239
class AdvancedImplementation extends ApiTrait {
240
def coreMethod(): String = "advanced"
241
242
@nowarn("cat=unused") // May not use all parameters yet
243
override def optionalMethod(): Option[String] = Some("advanced-feature")
244
}
245
```
246
247
### Macro and Code Generation Support
248
249
```scala
250
import scala.annotation.nowarn
251
252
// Code that's generated or used by macros
253
class GeneratedCode {
254
@nowarn // Generated code may have unused elements
255
def generatedMethod(
256
@unused param1: String,
257
@unused param2: Int,
258
usedParam: Boolean
259
): String = {
260
if (usedParam) "active" else "inactive"
261
}
262
}
263
264
// Macro-supporting code
265
@nowarn("cat=other") // Suppress macro-related warnings
266
object MacroSupport {
267
// Methods used by macros at compile time
268
def compiletimeHelper(): String = "helper"
269
}
270
```
271
272
## Build Configuration Integration
273
274
### SBT Configuration
275
276
For Scala 2.13+ you can also configure warning suppression at the build level:
277
278
```scala
279
// In build.sbt - complement to @nowarn annotations
280
scalacOptions ++= {
281
CrossVersion.partialVersion(scalaVersion.value) match {
282
case Some((2, n)) if n >= 13 =>
283
Seq("-Wconf:cat=unused-imports:s") // Suppress unused import warnings
284
case _ =>
285
Seq.empty
286
}
287
}
288
```
289
290
### Cross-Building with Annotations
291
292
```scala
293
// project/Dependencies.scala
294
val scalaCollectionCompat = Seq(
295
"org.scala-lang.modules" %% "scala-collection-compat" % "2.13.0"
296
)
297
298
// Use annotations to handle version differences
299
import scala.annotation.nowarn
300
301
@nowarn("cat=unused")
302
object CrossVersionImports {
303
// Import may be unused on some Scala versions
304
import scala.collection.compat._
305
306
def createList[T](items: T*): List[T] = {
307
List.from(items) // Available via compat library
308
}
309
}
310
```
311
312
## Migration Strategy
313
314
When migrating code across Scala versions:
315
316
1. **Add @nowarn annotations** for deprecated API usage during transition periods
317
2. **Use @unused annotations** for parameters/variables that will be used in the future
318
3. **Combine with collection-compat library** for smooth API transitions
319
4. **Review and remove annotations** after migration is complete
320
321
```scala
322
// Phase 1: Migration preparation
323
@nowarn("cat=deprecation")
324
def transitionMethod(): Unit = {
325
oldApi() // Still needed for some deployments
326
newApi() // New implementation
327
}
328
329
// Phase 2: After migration (clean up)
330
def transitionMethod(): Unit = {
331
newApi() // Only new implementation
332
// @nowarn annotation removed
333
}
334
```
335
336
## Implementation Notes
337
338
- `@nowarn` is a no-op on Scala versions that don't support it
339
- `@unused` helps with code clarity and prevents accidental removal of intentionally unused code
340
- These annotations are compile-time only and have no runtime impact
341
- They facilitate gradual migration and cross-version compatibility