or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotation-backports.mdbackported-collections.mdcollection-extensions.mdcollection-factories.mdindex.mditerator-size-ops.mdjava-interop.mdmap-extensions.mdmethod-chaining.mdoption-converters.mdresource-management.mdstring-parsing.md

annotation-backports.mddocs/

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