0% found this document useful (0 votes)
828 views1,320 pages

Kotlin Reference

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
828 views1,320 pages

Kotlin Reference

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1320

Kotlin

Language Documentation 1.7.20


Table of Contents

Kotlin Docs 54

Get started with Kotlin 54

Learn Kotlin fundamentals 54

Install Kotlin 54

Create your powerful application with Kotlin 54

Is anything missing? 58

Kotlin Multiplatform 58

Kotlin Multiplatform use cases 58

How Kotlin Multiplatform works 59

Get started 60

Kotlin for server side 61

Frameworks for server-side development with Kotlin 61

Deploying Kotlin server-side applications 62

Products that use Kotlin on the server side 62

Next steps 62

Kotlin for Android 62

Kotlin for JavaScript 63

Use cases for Kotlin/JS 63

Kotlin/JS frameworks 64

Kotlin/JS, Today and Tomorrow 65

Get started with Kotlin/JS 65

New Kotlin/JS IR compiler 66

Join the Kotlin/JS community 66

Kotlin Native 66

Why Kotlin/Native? 66

Target platforms 66

2
Interoperability 67

Sharing code between platforms 67

How to get started 67

Kotlin for data science 68

Interactive editors 68

Libraries 70

Kotlin for competitive programming 72

Simple example: Reachable Numbers problem 72

Functional operators example: Long Number problem 74

More tips and tricks 76

Learning Kotlin 76

What's new in Kotlin 1.7.20 76

Support for Kotlin K2 compiler plugins 77

Language 78

Kotlin/JVM 82

Kotlin/Native 84

Kotlin/JS 86

Gradle 86

Standard library 87

Documentation updates 89

Install Kotlin 1.7.20 90

What's new in Kotlin 1.7.0 90

New Kotlin K2 compiler for the JVM in Alpha 91

Language 92

Kotlin/JVM 94

Kotlin/Native 95

Kotlin/JS 97

Standard library 98

3
Gradle 103

Migrating to Kotlin 1.7.0 108

What's new in Kotlin 1.6.20 109

Language 109

Kotlin/JVM 111

Kotlin/Native 113

Kotlin Multiplatform 117

Kotlin/JS 119

Security 121

Gradle 123

What's new in Kotlin 1.6.0 125

Language 125

Supporting previous API versions for a longer period 128

Kotlin/JVM 128

Kotlin/Native 129

Kotlin/JS 132

Kotlin Gradle plugin 132

Standard library 133

Tools 137

Coroutines 1.6.0-RC 137

Migrating to Kotlin 1.6.0 138

What's new in Kotlin 1.5.30 138

Language features 139

Kotlin/JVM 143

Kotlin/Native 144

Kotlin Multiplatform 147

Kotlin/JS 149

Gradle 149

Standard library 152

4
Serialization 1.3.0-RC 155

What's new in Kotlin 1.5.20 156

Kotlin/JVM 156

Kotlin/Native 158

Kotlin/JS 159

Gradle 159

Standard library 160

What's new in Kotlin 1.5.0 161

Language features 161

Kotlin/JVM 163

Kotlin/Native 166

Kotlin/JS 167

Kotlin Multiplatform 167

Standard library 167

kotlin-test library 172

kotlinx libraries 175

Migrating to Kotlin 1.5.0 177

What's new in Kotlin 1.4.30 177

Language features 177

Kotlin/JVM 180

Kotlin/Native 181

Kotlin/JS 181

Gradle project improvements 182

Standard library 182

Serialization updates 184

What's new in Kotlin 1.4.20 184

Kotlin/JVM 184

Kotlin/JS 185

5
Kotlin/Native 187
Kotlin Multiplatform 189

Standard library 190

Kotlin Android Extensions 190

What's new in Kotlin 1.4 191

Language features and improvements 191

New tools in the IDE 195

New compiler 198

Kotlin/JVM 201

Kotlin/JS 203

Kotlin/Native 204

Kotlin Multiplatform 206

Gradle project improvements 210

Standard library 212

Stable JSON serialization 218

Scripting and REPL 218

Migrating to Kotlin 1.4.0 219

What's new in Kotlin 1.3 220

Coroutines release 220

Kotlin/Native 220

Multiplatform projects 220

Contracts 221

Capturing when subject in a variable 222

@JvmStatic and @JvmField in companions of interfaces 223

Nested declarations in annotation classes 223

Parameterless main 223

Functions with big arity 224

Progressive mode 224

Inline classes 224

6
Unsigned integers
225
@JvmDefault 225

Standard library 226

Tooling 228

What's new in Kotlin 1.2 228

Table of contents 229

Multiplatform projects (experimental) 229

Other language features 230

Standard library 233

JVM backend 235

JavaScript backend 236

Tools 236

What's new in Kotlin 1.1 236

Table of contents 236

JavaScript 236

Coroutines (experimental) 237

Other language features 238

Standard library 242

JVM Backend 246

JavaScript backend 247

What's new in Kotlin 1.7.20-RC 248

Support for Kotlin K2 compiler plugins 248

Preview of the ..< operator for creating open-ended ranges 249

The new Kotlin/Native memory manager is enabled by default 250

Generic inline classes 252

Support for Gradle 7.1 252

How to update to the Kotlin 1.7.20-RC 252

Participate in the Kotlin Early Access Preview 253

Build details 253

7
Install the EAP Plugin for IntelliJ IDEA or Android Studio 253

If you run into any problems 255

Configure your build for EAP 255

Configure in Gradle 256

Configure in Maven 257

Basic syntax 258

Package definition and imports 258

Program entry point 258

Print to the standard output 258

Functions 259

Variables 259

Creating classes and instances 260

Comments 261

String templates 261

Conditional expressions 262

for loop 262

while loop 262

when expression 263

Ranges 263

Collections 264

Nullable values and null checks 265

Type checks and automatic casts 266

Idioms 267

Create DTOs (POJOs/POCOs) 267

Default values for function parameters 268

Filter a list 268

Check the presence of an element in a collection 268

String interpolation 268

8
Instance checks 268
Read-only list 268

Read-only map 268

Access a map entry 269

Traverse a map or a list of pairs 269

Iterate over a range 269

Lazy property 269

Extension functions 269

Create a singleton 269

Instantiate an abstract class 269

If-not-null shorthand 270

If-not-null-else shorthand 270

Execute a statement if null 270

Get first item of a possibly empty collection 270

Execute if not null 270

Map nullable value if not null 271

Return on when statement 271

try-catch expression 271

if expression 271

Builder-style usage of methods that return Unit 271

Single-expression functions 272

Call multiple methods on an object instance (with) 272

Configure properties of an object (apply) 272

Java 7's try-with-resources 273

Generic function that requires the generic type information 273

Nullable Boolean 273

Swap two variables 273

Mark code as incomplete (TODO) 273

What's next? 273

9
Coding conventions 274

Configure style in IDE 274

Source code organization 274

Naming rules 275

Formatting 277

Documentation comments 286

Avoid redundant constructs 286

Idiomatic use of language features 287

Coding conventions for libraries 291

Basic types 291

Numbers 291

Integer types 292

Floating-point types 292

Literal constants for numbers 293

Numbers representation on the JVM 294

Explicit number conversions 294

Operations on numbers 295

Booleans 297

Characters 297

Strings 298

String literals 299

String templates 299

Arrays 300

Primitive type arrays 301

Unsigned integer types 301

Unsigned arrays and ranges 301

Unsigned integers literals 302

10
Use cases 302

Type checks and casts 303

is and !is operators 303

Smart casts 303

"Unsafe" cast operator 304

"Safe" (nullable) cast operator 304

Generics type checks and casts 304

Conditions and loops 305

If expression 305

When expression 305

For loops 307

While loops 308

Break and continue in loops 308

Returns and jumps 308

Break and continue labels 309

Return to labels 309

Exceptions 311

Exception classes 311

Checked exceptions 311

The Nothing type 312

Java interoperability 313

Packages and imports 313

Default imports 313

Imports 314

Visibility of top-level declarations 314

Classes 314

Constructors 315

Creating instances of classes 317

11
Class members 317

Inheritance 317

Abstract classes 317

Companion objects 318

Inheritance 318

Overriding methods 319

Overriding properties 319

Derived class initialization order 320

Calling the superclass implementation 320

Overriding rules 321

Properties 322

Declaring properties 322

Getters and setters 322

Compile-time constants 324

Late-initialized properties and variables 324

Overriding properties 325

Delegated properties 325

Interfaces 325

Implementing interfaces 326

Properties in interfaces 326

Interfaces Inheritance 326

Resolving overriding conflicts 327

Functional (SAM) interfaces 327

SAM conversions 327

Migration from an interface with constructor function to a functional interface 328

Functional interfaces vs. type aliases 329

Visibility modifiers 329

Packages 329

12
Class members
330
Modules 331

Extensions 331

Extension functions 332

Extensions are resolved statically 332

Nullable receiver 333

Extension properties 333

Companion object extensions 334

Scope of extensions 334

Declaring extensions as members 334

Note on visibility 336

Data classes 336

Properties declared in the class body 337

Copying 337

Data classes and destructuring declarations 338

Standard data classes 338

Sealed classes 338

Location of direct subclasses 339

Sealed classes and when expression 339

Generics: in, out, where 339

Variance 340

Type projections 342

Generic functions 344

Generic constraints 344

Type erasure 345

Underscore operator for type arguments 346

Nested and inner classes 347

Inner classes 347

13
Anonymous inner classes 348

Enum classes 348

Anonymous classes 348

Implementing interfaces in enum classes 349

Working with enum constants 349

Inline classes 350

Members 350

Inheritance 351

Representation 351

Inline classes vs type aliases 353

Inline classes and delegation 353

Object expressions and declarations 354

Object expressions 354

Object declarations 356

Delegation 358

Overriding a member of an interface implemented by delegation 359

Delegated properties 360

Standard delegates 361

Delegating to another property 362

Storing properties in a map 362

Local delegated properties 363

Property delegate requirements 363

Translation rules for delegated properties 364

Providing a delegate 366

Type aliases 368

Functions 368

Function usage 369

14
Function scope 373

Generic functions 374

Tail recursive functions 374

High-order functions and lambdas 375

Higher-order functions 375

Function types 376

Lambda expressions and anonymous functions 378

Inline functions 381

noinline 382

Non-local returns 382

Reified type parameters 383

Inline properties 384

Restrictions for public API inline functions 384

Operator overloading 384

Unary operations 385

Binary operations 386

Infix calls for named functions 390

Type-safe builders 390

How it works 391

Scope control: @DslMarker 393

Full definition of the com.example.html package 394

Using builders with builder type inference 395

Writing your own builders 396

How builder inference works 397

Null safety 400

Nullable types and non-null types 400

Checking for null in conditions 401

Safe calls 401

15
Elvis operator 402

The !! operator 402

Safe casts 402

Collections of a nullable type 403

What's next? 403

Equality 403

Structural equality 403

Referential equality 403

Floating-point numbers equality 404

This expressions 404

Qualified this 404

Implicit this 404

Asynchronous programming techniques 405

Threading 405

Callbacks 406

Futures, promises, and others 406

Reactive extensions 407

Coroutines 407

Coroutines 408

How to start 408

Sample projects 409

Annotations 409

Usage 409

Constructors 410

Instantiation 411

Lambdas 411

Annotation use-site targets 411

Java annotations 412

16
Repeatable annotations 414

Destructuring declarations 414

Example: returning two values from a function 415

Example: destructuring declarations and maps 415

Underscore for unused variables 416

Destructuring in lambdas 416

Reflection 416

JVM dependency 416

Class references 417

Callable references 418

Get started with Kotlin Multiplatform Mobile 422

Next step 422

Join the community 422

Set up an environment 423

Install the necessary tools 423

Check your environment 423

Possible issues and solutions 424

Next step 425

Get help 425

Create your first cross-platform app 425

Create the project from a template 425

Examine the project structure 428

Run your application 431

Update your application 436

Next step 440

Get help 440

Add dependencies to your project 440

Dependency types 441

17
Add a multiplatform dependency 441

Next step 443

Get help 443

Upgrade your app 443

Add more dependencies 443

Create API requests 444

Update Android and iOS apps 446

Next step 449

Get help 450

Wrap up your project 450

Understand mobile project structure 450

Root project 451

Shared module 453

Android application 457

iOS application 459

Make your Android application work on iOS – tutorial 462

Prepare an environment for development 462

Make your code cross-platform 463

Make your cross-platform application work on iOS 472

Enjoy the results – update the logic only once 481

What else to share? 484

What's next? 485

Publish your application 485

Android app 485

iOS app 485

Get started with Kotlin Multiplatform 486

Start from scratch 486

Dive deep into Kotlin Multiplatform 486

18
Get help 487

Understand Multiplatform project structure 487

Multiplatform plugin 487

Targets 488

Source sets 488

Compilations 491

Set up targets for Kotlin Multiplatform 492

Distinguish several targets for one platform 492

Build a full-stack web app with Kotlin Multiplatform 493

Create the project 494

Build the backend 495

Set up the frontend 501

Build the frontend 505

Include a database to store data 509

Deploy to the cloud 512

What's next 514

Create and publish a multiplatform library – tutorial 514

Set up the environment 514

Create a project 515

Write cross-platform code 517

Provide platform-specific implementations 517

Test your library 519

Publish your library to the local Maven repository 521

Add a dependency on the published library 522

What's next? 523

Publishing multiplatform libraries 523

Structure of publications 523

Avoid duplicate publications 524

19
Publish an Android library 525

Share code on platforms 525

Share code on all platforms 526

Share code on similar platforms 526

What's next? 532

Connect to platform-specific APIs 533

Examples 533

Rules for expected and actual declarations 538

Hierarchical project structure 539

For multiplatform project authors 539

For library authors 540

Compatibility 540

How to opt-out 541

Adding dependencies on multiplatform libraries 541

Dependency on a Kotlin library 542

Dependency on Kotlin Multiplatform libraries 543

Dependency on another multiplatform project 545

What's next? 546

Adding Android dependencies 546

What's next? 547

Adding iOS dependencies 547

With CocoaPods 548

Without CocoaPods 548

Workaround to enable IDE support for the shared iOS source set 551

What's next? 552

Run tests with Kotlin Multiplatform 553

Required dependencies 553

20
Run tests for one or more targets 553

Test shared code 553

Configure compilations 554

Configure all compilations 555

Configure compilations for one target 555

Configure one compilation 555

Create a custom compilation 556

Use Java sources in JVM compilations 557

Configure interop with native languages 558

Compilation for Android 560

Compilation of the source set hierarchy 560

Build final native binaries 561

Declare binaries 562

Access binaries 563

Export dependencies to binaries 565

Build universal frameworks 566

Build XCFrameworks 567

Customize the Info.plist file 569

Multiplatform Gradle DSL reference 569

Id and version 570

Top-level blocks 570

Targets 570

Source sets 580

Compilations 582

Dependencies 585

Language settings 587

Samples 588

FAQ 592

21
What is Kotlin Multiplatform Mobile? 592

What is the Kotlin Multiplatform Mobile plugin? 593

What is Kotlin/Native and how does it relate to Kotlin Multiplatform Mobile? 593

What are the plans for the technology evolution? 594

Can I run an iOS application on Microsoft Windows or Linux? 595

Where can I get complete examples to play with? 595

In which IDE should I work on my cross-platform app? 595

How can I write concurrent code in Kotlin Multiplatform Mobile projects? 595

How can I speed up my Kotlin Multiplatform module compilation for iOS? 595

What platforms do you support? 595

Introduce cross-platform mobile development to your team 596

Start with empathy 596

Explain how it works 596

Show the value 597

Offer proof 597

Prepare for questions 597

Be supportive 598

Get started with Kotlin/JVM 599

Create a project 599

Create an application 600

Run the application 601

What's next? 603

Comparison to Java 603

Some Java issues addressed in Kotlin 603

What Java has that Kotlin does not 603

What Kotlin has that Java does not 604

What's next? 604

Calling Java from Kotlin 604

22
Getters and setters 605

Methods returning void 605

Escaping for Java identifiers that are keywords in Kotlin 605

Null-safety and platform types 605

Mapped types 611

Java generics in Kotlin 614

Java arrays 614

Java varargs 615

Operators 616

Checked exceptions 616

Object methods 616

Inheritance from Java classes 617

Accessing static members 617

Java reflection 617

SAM conversions 617

Using JNI with Kotlin 618

Using Lombok-generated declarations in Kotlin 618

Calling Kotlin from Java 618

Properties 619

Package-level functions 619

Instance fields 620

Static fields 621

Static methods 622

Default methods in interfaces 623

Visibility 624

KClass 625

Handling signature clashes with @JvmName 625

Overloads generation 626

Checked exceptions 626

23
Null-safety 627
Variant generics 627

Create a RESTful web service with a database using Spring Boot – tutorial 628

Before you start 629

Bootstrap the project 629

Explore the project build file 631

Explore the Spring Boot application 632

Create a data class and a controller 632

Run the application 633

Add database support 634

Configure the database 635

Execute HTTP requests 636

What's next? 638

Test code using JUnit in JVM – tutorial 638

Add dependencies 638

Add the code to test it 639

Create a test 639

Run a test 640

What's next 642

Mixing Java and Kotlin in one project – tutorial 642

Adding Java source code to an existing Kotlin project 642

Adding Kotlin source code to an existing Java project 644

Converting an existing Java file to Kotlin with J2K 645

Using Java records in Kotlin 645

Using Java records from Kotlin code 646

Declare records in Kotlin 646

Further discussion 647

Strings in Java and Kotlin 647

24
Concatenate strings 647

Build a string 647

Create a string from collection items 648

Set default value if the string is blank 648

Replace characters at the beginning and end of a string 649

Replace occurrences 649

Split a string 650

Take a substring 650

Use multiline strings 651

What's next? 652

Collections in Java and Kotlin 652

Operations that are the same in Java and Kotlin 653

Operations that differ a bit 655

Operations that don't exist in Java's standard library 656

Mutability 657

Covariance 658

Ranges and progressions 658

Comparison by several criteria 659

Sequences 660

Removal of elements from a list 661

Traverse a map 661

Get the first and the last items of a possibly empty collection 661

Create a set from a list 662

Group elements 662

Filter elements 663

Collection transformation operations 665

What's next? 666

Nullability in Java and Kotlin 666

Support for nullable types 666

25
Platform types 668

Checking the result of a function call 668

Default values instead of null 669

Functions returning a value or null 669

Aggregate operations 670

Casting types safely 670

What's next? 671

Get started with Kotlin/JS for React 671

Create an application 671

Run the application 673

Update the application 673

What's next? 677

Set up a Kotlin/JS project 678

Execution environments 679

Dependencies 680

run task 682

test task 682

webpack bundling 683

CSS 685

Node.js 686

Yarn 686

Distribution target directory 688

Module name 689

package.json customization 689

Troubleshooting 689

Run Kotlin/JS 690

Run the Node.js target 690

Run the browser target 691

26
Development server and continuous compilation 692

Debug Kotlin/JS code 694

Debug in browser 694

Debug in the IDE 696

Debug in Node.js 699

What's next? 699

If you run into any problems 700

Run tests in Kotlin/JS 700

Kotlin/JS dead code elimination 703

Exclude declarations from DCE 703

Disable DCE 704

Kotlin/JS IR compiler 704

Lazy initialization of top-level properties 705

Incremental compilation for development binaries 705

Output .js files: one per module or one for the whole project 706

Ignoring compilation errors 706

Minification of member names in production 706

Preview: generation of TypeScript declaration files (d.ts) 707

Current limitations of the IR compiler 707

Migrating existing projects to the IR compiler 707

Authoring libraries for the IR compiler with backwards compatibility 708

Migrating Kotlin/JS projects to the IR compiler 708

Convert JS- and React-related classes and interfaces to external interfaces 708

Convert properties of external interfaces to var 709

Convert functions with receivers in external interfaces to regular functions 709

Create plain JS objects for interoperability 710

Replace toString() calls on function references with .name 710

Explicitly specify binaries.executable() in the build script 710

27
Additional troubleshooting tips when working with the Kotlin/JS IR compiler 711

Browser and DOM API 711

Interaction with the DOM 712

Use JavaScript code from Kotlin 712

Inline JavaScript 712

external modifier 713

Dynamic type 716

Use dependencies from npm 717

Use Kotlin code from JavaScript 718

Isolating declarations in a separate JavaScript object in plain mode 718

Package structure 718

Kotlin types in JavaScript 720

JavaScript modules 720

Browser targets 721

JavaScript libraries and Node.js files 721

@JsModule annotation 722

Kotlin/JS reflection 724

Class references 724

KType and typeOf() 724

Example 724

Typesafe HTML DSL 725

Generation of external declarations with Dukat 726

Generate external declarations at build time 726

Manually generate external declarations via Gradle task 727

Samples 727

Build a web application with React and Kotlin/JS — tutorial 728

28
Before you start 728
Create a web app draft 732

Design app components 736

Compose components 741

Add more components 743

Use packages from npm 745

Use an external REST API 748

Deploy to production and the cloud 751

What's next 753

Get started with Kotlin/Native in IntelliJ IDEA 754

Create a new Kotlin/Native project in IntelliJ IDEA 754

Build and run the application 755

Update the application 756

What's next? 758

Get started with Kotlin/Native using Gradle 758

Create project files 759

Build and run the application 760

Open the project in an IDE 760

What's next? 760

Get started with Kotlin/Native using the command-line compiler 760

Obtain the compiler 761

Write "Hello Kotlin/Native" program 761

Compile the code from the console 761

Interoperability with C 761

Platform libraries 762

Simple example 762

Create bindings for a new library 762

Bindings 764

29
Mapping primitive data types from C – tutorial 769

Types in C language 770

Example C library 770

Inspect generated Kotlin APIs for a C library 771

Primitive types in kotlin 772

Fix the code 773

Next steps 774

Mapping struct and union types from C – tutorial 774

Mapping struct and union C types 774

Inspect Generated Kotlin APIs for a C library 775

Struct and union types in Kotlin 776

Use struct and union types from Kotlin 777

Run the code 779

Next steps 780

Mapping function pointers from C – tutorial 780

Mapping function pointer types from C 780

Inspect generated Kotlin APIs for a C library 781

C function pointers in Kotlin 782

Pass Kotlin function as C function pointer 783

Use the C function pointer from Kotlin 783

Fix the code 783

Next Steps 784

Mapping Strings from C – tutorial 784

Working with C strings 784

Inspect generated Kotlin APIs for a C library 785

Strings in Kotlin 786

Pass Kotlin string to C 787

Read C Strings in Kotlin 787

30
Receive C string bytes from Kotlin 787

Fix the Code 788

Next steps 788

Create an app using C Interop and libcurl – tutorial 789

Create a Kotlin/Native project 789

Create a definition file 791

Add interoperability to the build process 792

Write the application code 793

Compile and run the application 793

Interoperability with Swift/Objective-C 794

Usage 795

Mappings 795

Casting between mapped types 801

Subclassing 801

C features 802

Export of KDoc comments to generated Objective-C headers 802

Unsupported 803

Kotlin/Native as an Apple framework – tutorial 803

Create a Kotlin library 803

Generated framework headers 806

Garbage collection and reference counting 809

Use the code from Objective-C 809

Use the code from Swift 810

Xcode and framework dependencies 810

Next steps 811

CocoaPods overview and setup 811

Set up an environment to work with CocoaPods 811

Add and configure Kotlin CocoaPods Gradle plugin 812

31
Update Podfile for Xcode 813

Possible issues and solutions 814

Add dependencies on a Pod library 815

From the CocoaPods repository 815

On a locally stored library 816

From a custom Git repository 817

From a zip, tar, or jar archive 818

From a custom Podspec repository 819

With custom cinterop options 820

On a static Pod library 820

Use a Kotlin Gradle project as a CocoaPods dependency 821

Xcode project with one target 821

Xcode project with several targets 822

CocoaPods Gradle plugin DSL reference 823

Enable the plugin 823

cocoapods block 823

pod() function 826

Kotlin/Native libraries 827

Kotlin compiler specifics 827

cinterop tool specifics 827

klib utility 828

Several examples 828

Advanced topics 829

Platform libraries 830

POSIX bindings 830

Popular native libraries 831

Availability by default 831

Kotlin/Native as a dynamic library – tutorial 831

32
Create a Kotlin library 831

Generated headers file 834

Use generated headers from C 837

Compile and run the example on Linux and macOS 838

Compile and run the example on Windows 838

Next steps 838

Kotlin/Native memory management 839

Garbage collector 839

Memory consumption 840

Unit tests in the background 840

Legacy memory manager 840

What's next 840

iOS integration 840

Threads 841

Garbage collection and lifecycle 842

Support for background state and App Extensions 844

Migrate to the new memory manager 845

Update Kotlin 845

Update dependencies 845

Update your code 846

Support both new and legacy memory managers 847

What's next 847

Immutability and concurrency in Kotlin/Native 847

Concurrency in Kotlin/Native 848

Concurrency overview 851

Rules for state sharing 851

Immutable and frozen state 852

Global state 853

33
Current and future models 854

Concurrent mutability 855

Atomics 855

Thread-isolated state 857

Low-level capabilities 858

Concurrency and coroutines 858

Coroutines 859

Multithreaded coroutines 861

Alternatives to kotlinx-coroutines 862

Debugging Kotlin/Native 863

Produce binaries with debug info with Kotlin/Native compiler 863

Breakpoints 864

Stepping 865

Variable inspection 865

Known issues 866

Symbolicating iOS crash reports 866

Producing .dSYM for release Kotlin binaries 867

Make frameworks static when using rebuild from bitcode 867

Decode inlined stack frames 868

Tips for improving Kotlin/Native compilation times 868

General recommendations 868

Gradle configuration 868

Windows OS configuration 869

Kotlin/Native FAQ 869

How do I run my program? 869

What is Kotlin/Native memory management model? 870

How do I create a shared library? 870

How do I create a static library or an object file? 870

34
How do I run Kotlin/Native behind a corporate proxy? 870

How do I specify a custom Objective-C prefix/name for my Kotlin framework? 870

How do I rename the iOS framework? 871

How do I enable bitcode for my Kotlin framework? 871

Why do I see InvalidMutabilityException? 872

How do I make a singleton object mutable? 872

How can I compile my project with unreleased versions of Kotlin/Native? 872

Get started with Kotlin custom scripting – tutorial 872

Project structure 873

Before you start 873

Create a project 873

Add scripting modules 874

Create a script definition 876

Create a scripting host 878

Run scripts 879

What's next? 880

Kotlin releases 881

Update to a new release 881

IDE support 881

Release details 881

Kotlin Multiplatform Mobile plugin releases 887

Update to the new release 887

Release details 888

Kotlin plugin releases 892

Update to a new release 892

Release details 892

Kotlin roadmap 894

Key priorities 894

35
Kotlin roadmap by subsystem 895

What's changed since November 2021 898

Collections overview 899

Collection types 900

Constructing collections 905

Construct from elements 905

Create with collection builder functions 905

Empty collections 905

Initializer functions for lists 906

Concrete type constructors 906

Copy 906

Invoke functions on other collections 907

Iterators 908

List iterators 909

Mutable iterators 909

Ranges and progressions 910

Range 911

Progression 911

Sequences 912

Construct 913

Sequence operations 914

Sequence processing example 914

Collection operations overview 916

Extension and member functions 916

Common operations 916

Write operations 918

Collection transformation operations 918

Map 918

36
Map 918

Zip 919

Associate 920

Flatten 921

String representation 921

Filtering collections 922

Filter by predicate 923

Partition 924

Test predicates 924

Plus and minus operators 925

Grouping 925

Retrieve collection parts 926

Slice 926

Take and drop 926

Chunked 927

Windowed 927

Retrieve single elements 928

Retrieve by position 929

Retrieve by condition 929

Retrieve with selector 930

Random element 930

Check element existence 931

Ordering 931

Natural order 933

Custom orders 933

Reverse order 933

Random order 934

Aggregate operations 934

37
Fold and reduce 935

Collection write operations 937

Adding elements 937

Removing elements 938

Updating elements 939

List-specific operations 939

Retrieve elements by index 939

Retrieve list parts 940

Find element positions 940

List write operations 942

Set-specific operations 944

Map-specific operations 944

Retrieve keys and values 944

Filter 945

Plus and minus operators 945

Map write operations 946

Scope functions 948

Function selection 949

Distinctions 950

Functions 953

takeIf and takeUnless 956

Opt-in requirements 957

Opt in to using API 957

Require opt-in for API 960

Opt-in requirements for pre-stable APIs 961

Coroutines guide 962

Table of contents 962

38
Additional references 962

Coroutines basics 963

Your first coroutine 963

Extract function refactoring 964

Scope builder 964

Scope builder and concurrency 965

An explicit job 966

Coroutines are light-weight 966

Coroutines and channels − tutorial 967

Before you start 967

Blocking requests 969

Callbacks 973

Suspending functions 976

Coroutines 978

Concurrency 980

Structured concurrency 984

Showing progress 988

Channels 990

Testing coroutines 994

What's next 998

Cancellation and timeouts 998

Cancelling coroutine execution 998

Cancellation is cooperative 999

Making computation code cancellable 1000

Closing resources with finally 1000

Run non-cancellable block 1001

Timeout 1002

Asynchronous timeout and resources 1003

39
Composing suspending functions 1004

Sequential by default 1004

Concurrent using async 1005

Lazily started async 1006

Async-style functions 1007

Structured concurrency with async 1008

Coroutine context and dispatchers 1010

Dispatchers and threads 1010

Unconfined vs confined dispatcher 1011

Debugging coroutines and threads 1012

Jumping between threads 1013

Job in the context 1014

Children of a coroutine 1015

Parental responsibilities 1015

Naming coroutines for debugging 1016

Combining context elements 1017

Coroutine scope 1017

Asynchronous Flow 1020

Representing multiple values 1020

Flows are cold 1022

Flow cancellation basics 1023

Flow builders 1024

Intermediate flow operators 1024

Terminal flow operators 1026

Flows are sequential 1027

Flow context 1027

Buffering 1030

Composing multiple flows 1033

Flattening flows 1034

40
Flow exceptions 1037

Exception transparency 1038

Flow completion 1040

Imperative versus declarative 1042

Launching flow 1043

Flow and Reactive Streams 1046

Channels 1046

Channel basics 1046

Closing and iteration over channels 1047

Building channel producers 1047

Pipelines 1047

Prime numbers with pipeline 1048

Fan-out 1050

Fan-in 1051

Buffered channels 1052

Channels are fair 1053

Ticker channels 1053

Coroutine exceptions handling 1054

Exception propagation 1054

CoroutineExceptionHandler 1055

Cancellation and exceptions 1056

Exceptions aggregation 1058

Supervision 1059

Shared mutable state and concurrency 1062

The problem 1062

Volatiles are of no help 1063

Thread-safe data structures 1063

Thread confinement fine-grained 1064

41
Thread confinement coarse-grained 1065

Mutual exclusion 1066

Actors 1067

Select expression (experimental) 1068

Selecting from channels 1068

Selecting on close 1070

Selecting to send 1071

Selecting deferred values 1072

Switch over a channel of deferred values 1073

Debug coroutines using IntelliJ IDEA – tutorial 1075

Create coroutines 1075

Debug coroutines 1076

Debug Kotlin Flow using IntelliJ IDEA – tutorial 1079

Create a Kotlin flow 1079

Debug the coroutine 1080

Add a concurrently running coroutine 1082

Debug a Kotlin flow with two coroutines 1083

Serialization 1084

Libraries 1084

Formats 1084

Example: JSON serialization 1085

Keywords and operators 1086

Hard keywords 1086

Soft keywords 1088

Modifier keywords 1089

Special identifiers 1090

Operators and special symbols 1090

Gradle 1091

42
Apply the plugin 1091

Targeting multiple platforms 1092

Targeting the JVM 1092

Targeting JavaScript 1096

Targeting Android 1097

Configure dependencies 1097

Annotation processing 1102

Incremental compilation 1102

Gradle build cache support 1103

Gradle configuration cache support 1103

Build reports 1103

Compiler options 1104

Generating documentation 1108

OSGi 1108

Using the Gradle Kotlin DSL 1108

Kotlin daemon and using it with Gradle 1108

Defining Kotlin compiler execution strategy 1110

Triggering configuration actions with the KotlinBasePlugin interface 1111

Maven 1112

Plugin and versions 1112

Dependencies 1112

Compile Kotlin-only source code 1113

Compile Kotlin and Java sources 1113

Incremental compilation 1114

Annotation processing 1115

Jar file 1115

Self-contained Jar file 1115

Specifying compiler options 1116

Generating documentation 1118

43
OSGi 1118

Ant 1118

Getting the Ant tasks 1118

Targeting JVM with Kotlin-only source 1118

Targeting JVM with Kotlin-only source and multiple roots 1119

Targeting JVM with Kotlin and Java source 1119

Targeting JavaScript with single source folder 1119

Targeting JavaScript with Prefix, PostFix and sourcemap options 1119

Targeting JavaScript with single source folder and metaInfo option 1120

References 1120

IDEs for Kotlin development 1122

IntelliJ IDEA 1122

Android Studio 1122

Compatibility with the Kotlin language versions 1122

Other IDEs support 1122

What's next? 1122

Migrate to Kotlin code style 1123

Kotlin coding conventions and IntelliJ IDEA formatter 1123

Differences between "Kotlin coding conventions" and "IntelliJ IDEA default code style" 1123

Migration to a new code style discussion 1124

Migration to a new code style 1124

Store old code style in project 1125

Run code snippets 1126

IDE: scratches and worksheets 1126

Browser: Kotlin Playground 1128

Command line: ki shell 1131

Kotlin command-line compiler 1133

Install the compiler 1134

44
Create and run an application 1134

Compile a library 1135

Run the REPL 1135

Run scripts 1135

Kotlin compiler options 1136

Compiler options 1136

Common options 1136

Kotlin/JVM compiler options 1138

Kotlin/JS compiler options 1139

Kotlin/Native compiler options 1141

All-open compiler plugin 1143

Gradle 1143

Maven 1144

Spring support 1144

Command-line compiler 1145

No-arg compiler plugin 1146

Gradle 1146

Maven 1146

JPA support 1147

Command-line compiler 1147

SAM-with-receiver compiler plugin 1147

Gradle 1148

Maven 1148

Command-line compiler 1149

Using kapt 1149

Using in Gradle 1149

Annotation processor arguments 1150

Gradle build cache support 1150

45
Improving the speed of builds that use kapt 1151

Compile avoidance for kapt 1153

Incremental annotation processing 1153

Java compiler options 1153

Non-existent type correction 1153

Using in Maven 1154

Using in CLI 1154

Generating Kotlin sources 1155

AP/Javac options encoding 1155

Keeping Java compiler's annotation processors 1155

Lombok compiler plugin 1156

Supported annotations 1156

Gradle 1156

Maven 1157

Using with kapt 1158

Kotlin Symbol Processing API 1158

Overview 1159

How KSP looks at source files 1159

SymbolProcessorProvider: the entry point 1160

Resources 1161

Supported libraries 1161

KSP quickstart 1162

Create a processor of your own 1163

Use your own processor in a project 1164

Pass options to processors 1166

Make IDE aware of generated code 1166

Why KSP 1167

KSP makes creating lightweight compiler plugins easier 1167

46
Comparison to kotlinc compiler plugins 1168

Comparison to reflection 1168

Comparison to kapt 1168

Limitations 1168

KSP examples 1169

Get all member functions 1169

Check whether a class or function is local 1169

Find the actual class or interface declaration that the type alias points to 1169

Collect suppressed names in a file annotation 1169

How KSP models Kotlin code 1170

Type and resolution 1170

Java annotation processing to KSP reference 1171

Program elements 1171

Types 1172

Misc 1172

Details 1174

Incremental processing 1182

Aggregating vs Isolating 1182

Example 1 1183

Example 2 1184

How file dirtiness is determined 1184

Reporting bugs 1184

Multiple round processing 1184

Changes to your processor 1185

Multiple round behavior 1185

Advanced 1186

KSP with Kotlin Multiplatform 1186

Compilation and processing 1187

47
Avoid the ksp(...) configuration on KSP 1.0.1+ 1187

Running KSP from command line 1188

FAQ 1188

Why KSP? 1189

Why is KSP faster than kapt? 1189

Is KSP Kotlin-specific? 1189

How to upgrade KSP? 1189

Can I use a newer KSP implementation with an older Kotlin compiler? 1189

How often do you update KSP? 1190

Besides Kotlin, are there other version requirements to libraries? 1190

What is KSP's future roadmap? 1190

Kotlin and continuous integration with TeamCity 1190

Gradle, Maven, and Ant 1190

IntelliJ IDEA Build System 1191

Other CI servers 1193

Document Kotlin code: KDoc and Dokka 1193

Generate the documentation 1193

KDoc syntax 1193

Inline markup 1195

Module and package documentation 1195

Kotlin and OSGi 1196

Maven 1196

Gradle 1197

FAQ 1197

Learning materials overview 1197

Kotlin Koans 1198

Kotlin tips 1198

48
null + null in Kotlin 1198

Deduplicating collection items 1199

The suspend and inline mystery 1199

Unshadowing declarations with their fully qualified name 1200

Return and throw with the Elvis operator 1200

Destructuring declarations 1200

Operator functions with nullable values 1201

Timing code 1201

Improving loops 1202

Strings 1202

Doing more with the Elvis operator 1203

Kotlin collections 1203

What's next? 1204

Kotlin books 1204

Advent of Code puzzles in idiomatic Kotlin 1208

Day 1: Report repair 1208

Day 2: Password philosophy 1208

Day 3: Toboggan trajectory 1209

Day 4: Passport processing 1209

Day 5: Binary boarding 1210

Day 6: Custom customs 1211

Day 7: Handy haversacks 1211

Day 8: Handheld halting 1212

Day 9: Encoding error 1212

What's next? 1213

Learning Kotlin with EduTools plugin 1213

Teaching Kotlin with EduTools plugin 1213

FAQ 1213

49
What is Kotlin? 1214

What is the current version of Kotlin? 1214

Is Kotlin free? 1214

Is Kotlin an object-oriented language or a functional one? 1214

What advantages does Kotlin give me over the Java programming language? 1214

Is Kotlin compatible with the Java programming language? 1214

What can I use Kotlin for? 1214

Can I use Kotlin for Android development? 1214

Can I use Kotlin for server-side development? 1215

Can I use Kotlin for web development? 1215

Can I use Kotlin for desktop development? 1215

Can I use Kotlin for native development? 1215

What IDEs support Kotlin? 1215

What build tools support Kotlin? 1215

What does Kotlin compile down to? 1215

Which versions of JVM does Kotlin target? 1216

Is Kotlin hard? 1216

What companies are using Kotlin? 1216

Who develops Kotlin? 1216

Where can I learn more about Kotlin? 1216

Are there any books on Kotlin? 1216

Are any online courses available for Kotlin? 1216

Does Kotlin have a community? 1217

Are there Kotlin events? 1217

Is there a Kotlin conference? 1217

Is Kotlin on social media? 1217

Any other online Kotlin resources? 1217

Where can I get an HD Kotlin logo? 1217

Kotlin Evolution 1217

50
Principles of Pragmatic Evolution 1217

Incompatible changes 1218

Decision making 1219

Feature releases and incremental releases 1219

Libraries 1220

Compiler keys 1220

Compatibility tools 1221

Stability of Kotlin components 1221

Stability levels explained 1221

GitHub badges for Kotlin components 1222

Stability of subcomponents 1222

Current stability of Kotlin components 1223

Stability of Kotlin components (pre 1.4) 1225

Compatibility guide for Kotlin 1.7.20 1226

Basic terms 1226

Language 1226

Compatibility guide for Kotlin 1.7 1227

Basic terms 1227

Language 1228

Standard library 1234

Tools 1236

Compatibility guide for Kotlin 1.6 1240

Basic terms 1240

Language 1240

Standard library 1246

Tools 1250

Compatibility guide for Kotlin 1.5 1252

Basic terms 1252

51
Language and stdlib 1253

Tools 1261

Compatibility guide for Kotlin 1.4 1262

Basic terms 1262

Language and stdlib 1263

Tools 1278

Compatibility guide for Kotlin 1.3 1278

Basic terms 1278

Incompatible changes 1279

Compatibility modes 1290

Binary compatibility warnings 1291

What is cross-platform mobile development? 1291

Cross-platform mobile development: definition and solutions 1291

Is cross-platform mobile development right for you? 1293

The most popular cross-platform solutions 1295

Conclusion 1297

Native and cross-platform app development: how to choose? 1297

What is native mobile app development? 1297

What is cross-platform app development? 1298

Six key aspects to help you choose between cross-platform app development and the native 1300

approach
When should you choose cross-platform app development? 1302

When should you choose native app development? 1302

The Six Best Cross-Platform App Development Frameworks 1302

What is a cross-platform app development framework? 1303

Popular cross-platform app development frameworks 1303

How do you choose the right cross-platform app development framework for your project? 1306

Key takeaways 1307

52
Security
1307

Kotlin documentation as PDF 1308

Contribution 1308

Participate in Early Access Preview 1308

Contribute to the compiler and standard library 1308

Contribute to the Kotlin IDE plugin 1308

Contribute to other Kotlin libraries and tools 1308

Contribute to the documentation 1309

Create tutorials or videos 1309

Translate documentation to other languages 1309

Hold events and presentations 1309

KUG guidelines 1309

How to run a KUG? 1310

Support for KUGs from JetBrains 1310

Support from JetBrains for other tech communities 1310

Kotlin Night guidelines 1310

Event guidelines 1311

Event requirements 1311

JetBrains support 1311

Kotlin brand assets 1312

Kotlin Logo 1312

Kotlin User Group brand assets 1313

Kotlin Night brand assets 1316

53
Kotlin
Docs
Get
started
with
Kotlin
Kotlin is a modern but already mature programming language aimed to make developers happier. It's concise, safe, interoperable with
Java and other languages, and provides many ways to reuse code between multiple platforms for productive programming.

Pick it up to start building powerful applications!

Learn
Kotlin
fundamentals
If you're already familiar with one or more programming languages and want to learn Kotlin, start with these Kotlin learning materials.

If Kotlin is your first programming language, we recommend starting with the Atomic Kotlin book or signing up for the free Kotlin Basics
track on JetBrains Academy.

Install
Kotlin
Kotlin is included in each IntelliJ IDEA and Android Studio release.
Download and install one of these IDEs to start using Kotlin.

Create
your
powerful
application
with
Kotlin

Backend app

Here is how you can take the first steps in developing Kotlin server-side applications.

1. Create your first backend application:

To start from scratch, create a basic JVM application with the IntelliJ IDEA project wizard.

If you prefer more robust examples, choose one of the frameworks below and create a project:

Spring Ktor

A mature family of frameworks with an established ecosystem that is used A lightweight framework for those who value freedom in making
by millions of developers worldwide. architectural decisions.

Create a RESTful web service with Spring Boot. Create HTTP APIs with Ktor.

Build web applications with Spring Boot and Kotlin. Create a WebSocket chat with Ktor.

Use Spring Boot with Kotlin and RSocket. Create an interactive website with Ktor.

Publish server-side Kotlin applications: Ktor on Heroku.

2. Use Kotlin and third-party libraries in your application. Learn more about adding library and tool dependencies to your project.

The Kotlin standard library offers a lot of useful things such as collections or coroutines.

Take a look at the following third-party frameworks, libs and tools for Kotlin.

3. Learn more about Kotlin for server-side:

54
How to write your first unit test.

How to mix Kotlin and Java code in your application.

4. Join the Kotlin server-side community:

Slack: get an invite and join the #getting-started, #server, #spring, or #ktor channels.

StackOverflow: subscribe to the "kotlin", "spring-kotlin", or "ktor" tags.

5. Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

If you've encountered any difficulties or problems, report an issue to ourissue tracker.

Cross-platform mobile app

Here you'll learn how to develop and improve your cross-platform mobile application usingKotlin Multiplatform Mobile.

1. Set up your environment for cross-platform mobile development.

2. Create your first application for iOS and Android:

To start from scratch, create a basic cross-platform mobile application with the project wizard.

If you have an existing Android application and want to make it cross-platform, complete theMake your Android application work on iOStutorial.

If you prefer real-life examples, clone and play with an existing project, for example the networking and data storage project from thehands-on
tutorial or any sample project.

3. Use a wide set of multiplatform libraries to implement the required business logic only once in the shared module. Learn more aboutadding
dependencies.

Library Details

Ktor Docs.

Serialization Docs and sample.

Coroutines Docs and sample.

DateTime Docs.

SQLDelight Third-party library.


Docs.

You can also find a multiplatform library in the community-driven list.

4. Learn more about Kotlin Multiplatform Mobile:

Learn more about Kotlin Multiplatform.

Look through samples on GitHub.

Create and publish a multiplatform library.

Learn how Kotlin Multiplatform is used at Netflix, VMware, Yandex, and many other companies.

5. Join the Kotlin Multiplatform community:

55
Slack: get an invite and join the #getting-started and #multiplatform channels.

StackOverflow: Subscribe to the "kotlin-multiplatform" tag.

6. Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

If you've encountered any difficulties or problems, report an issue to ourissue tracker.

Frontend web
app

Kotlin provides an ability to transpile your Kotlin code, the Kotlin standard library, and any compatible dependencies to JavaScript.

Here you'll learn how to develop and improve your frontend web application usingKotlin/JS.

1. Create your first frontend web application:

To start from scratch, create a basic browser application with the IntelliJ IDEA project wizard.

If you prefer more robust examples, complete the Build a web application with React and Kotlin/JS tutorial. It includes a sample project that can
serve as a good starting point for your own projects, and contains useful snippets and templates.

Check out the list of Kotlin/JS samples for more ideas on how to use Kotlin/JS.

2. Use libraries in your application. Learn more about adding dependencies.

Library Details

stdlib The Kotlin standard library included in all projects by default.

kotlinx.browser The Kotlin library for accessing browser-specific functionality, including typical top-level objects such as document and
window.

kotlinx.html The Kotlin library for generating DOM elements using statically-typed HTML builders.

Ktor The Kotlin multiplatform library for networking.

KVision A third-party object-oriented web framework for Kotlin/JS.

fritz2 A third-party lightweight, high-performance, independent library for building reactive web apps in Kotlin that are heavily
dependent on coroutines and flows.

Doodle A third-party vector-based UI framework that uses browser's capabilities to draw user interfaces.

Compose for Web, a part The JetBrains framework that brings Google's Jetpack Compose UI toolkit to the browser.
of Compose Multiplatform

kotlin-wrappers Provide convenient abstractions and deep integrations for one of the most popular JavaScript frameworks. Kotlin
wrappers also provide support for a number of adjacent technologies like react-redux, react-router, or styled-components.

3. Learn more about Kotlin for frontend web development:

The new Kotlin/JS IR compiler (currently with Beta stability).

56
Using dependencies from npm.

Using Kotlin code from JavaScript.

4. Join the Kotlin frontend web community:

Slack: get an invite and join the #getting-started and #javascript channels.

StackOverflow: subscribe to the "kotlin-js" tag.

5. Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

If you've encountered any difficulties or problems, report an issue to ourissue tracker.

Android app

If you want to start using Kotlin for Android development, readGoogle's recommendation for getting started with Kotlin on Android.

If you're new to Android and want to learn to create applications with Kotlin, check outthis Udacity course.

Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

Multiplatform library

Support for multiplatform programming is one of Kotlin's key benefits. It reduces time spent writing and maintaining the same code for different platforms
while retaining the flexibility and benefits of native programming.

Here you'll learn how to develop and publish a multiplatform library:

1. Create a multiplatform library:

Complete the Create and publish a multiplatform library tutorial. It shows how to create a multiplatform library for JVM, JS, and Native platforms, test
it and publish to a local Maven repository.

Build a full stack web application using this tutorial.

2. Use libraries in your application. Learn more about adding dependencies on libraries.

Library Details

Ktor Docs and sample.

Serialization Docs and sample.

Coroutines Docs.

DateTime Docs.

You can also find a multiplatform library in the community-driven list.

3. Learn more about Kotlin Multiplatform programming:

Introduction to Kotlin Multiplatform.

Kotlin Multiplatform supported platforms.

Kotlin Multiplatform programming benefits.

4. Join the Kotlin Multiplatform community:

57
Slack: get an invite and join the #getting-started and #multiplatform channels.

StackOverflow: Subscribe to the "kotlin-multiplatform" tag.

5. Follow Kotlin on Twitter, Reddit, and Youtube, and don't miss any important ecosystem updates.

If you've encountered any difficulties or problems, report an issue to ourissue tracker.

Is
anything
missing?
If anything is missing or seems confusing on this page, please share your feedback.

Kotlin
Multiplatform

Multiplatform projects are in Alpha. Language features and tooling may change in future Kotlin versions.

Support for multiplatform programming is one of Kotlin's key benefits. It reduces time spent writing and maintaining the same code for
different platforms while retaining the flexibility and benefits of native programming.

Kotlin
Multiplatform
use
cases

Android
and
iOS
applications
Sharing code between mobile platforms is one of the major Kotlin Multiplatform use cases. With Kotlin Multiplatform Mobile, you can build
cross-platform mobile applications and share common code between Android and iOS, such as business logic, connectivity, and more.

Check out the Get started with Kotlin Multiplatform Mobile section and Kotlin Multiplatform Hands-on: Networking and Data Storage,
where you will create an application for Android and iOS that includes a module with shared code for both platforms.

Full-stack
web
applications
Another scenario when code sharing may bring benefits is a connected application where the logic can be reused on both the server and
the client side running in the browser. This is covered by Kotlin Multiplatform as well.

See Build a full-stack web app with Kotlin Multiplatform tutorial, where you will create a connected application consisting of a server part,
using Kotlin/JVM and a web client, using Kotlin/JS.

Multiplatform
libraries
Kotlin Multiplatform is also useful for library authors. You can create a multiplatform library with common code and its platform-specific
implementations for JVM, JS, and Native platforms. Once published, a multiplatform library can be used in other cross-platform projects
as a dependency.

See the Create and publish a multiplatform library tutorial, where you will create a multiplatform library, test it, and publish it to Maven.

Common
code
for
mobile
and
web
applications
One more popular case for using Kotlin Multiplatform is sharing the same code across Android, iOS, and web apps. It reduces the amount

58
of business logic coded by frontend developers and helps implement products more efficiently, decreasing the coding and testing efforts.

See the RSS Reader sample project — a cross-platform application for iOS and Android with desktop and web clients implemented as
experimental features.

How
Kotlin
Multiplatform
works

Kotlin Multiplatform

Common Kotlin includes the language, core libraries, and basic tools. Code written in common Kotlin works everywhere on all
platforms.

With Kotlin Multiplatform libraries, you can reuse the multiplatform logic in common and platform-specific code. Common code can rely

59
on a set of libraries that cover everyday tasks such as HTTP, serialization, and managing coroutines.

To interop with platforms, use platform-specific versions of Kotlin. Platform-specific versions of Kotlin (Kotlin/JVM, Kotlin/JS,
Kotlin/Native) include extensions to the Kotlin language, and platform-specific libraries and tools.

Through these platforms you can access the platform native code (JVM, JS, and Native) and leverage all native capabilities.

Code
sharing
between
platforms
With Kotlin Multiplatform, spend less time on writing and maintaining the same code for different platforms – just share it using the
mechanisms Kotlin provides:

Share code among all platforms used in your project. Use it for sharing the common business logic that applies to all platforms.

Share code among some platforms included in your project but not all. Do this when you can reuse much of the code in similar
platforms:

Code shared for iOS targets

If you need to access platform-specific APIs from the shared code, use the Kotlin mechanism of expected and actual declarations.

Get
started
Look through our examples and tutorials if you want to create applications or libraries targeting JVM, JavaScript, and other platforms

Start with the Get started with Kotlin Multiplatform Mobile if you want to create iOS and Android applications with shared code

New to Kotlin? Take a look at Getting started with Kotlin.

Sample
projects
Look through cross-platform application samples to understand how Kotlin Multiplatform works:

Kotlin Multiplatform Mobile samples

KotlinConf app

60
KotlinConf Spinner app

Build a full-stack web app with Kotlin Multiplatform

Kotlin
for
server
side
Kotlin is a great fit for developing server-side applications. It allows you to write concise and expressive code while maintaining full
compatibility with existing Java-based technology stacks, all with a smooth learning curve:

Expressiveness: Kotlin's innovative language features, such as its support for type-safe builders and delegated properties, help build
powerful and easy-to-use abstractions.

Scalability: Kotlin's support for coroutines helps build server-side applications that scale to massive numbers of clients with modest
hardware requirements.

Interoperability: Kotlin is fully compatible with all Java-based frameworks, so you can use your familiar technology stack while reaping
the benefits of a more modern language.

Migration: Kotlin supports gradual migration of large codebases from Java to Kotlin. You can start writing new code in Kotlin while
keeping older parts of your system in Java.

Tooling: In addition to great IDE support in general, Kotlin offers framework-specific tooling (for example, for Spring) in the plugin for
IntelliJ IDEA Ultimate.

Learning Curve: For a Java developer, getting started with Kotlin is very easy. The automated Java-to-Kotlin converter included in the
Kotlin plugin helps with the first steps. Kotlin Koans can guide you through the key features of the language with a series of interactive
exercises.

Frameworks
for
server-side
development
with
Kotlin
Spring makes use of Kotlin's language features to offer more concise APIs, starting with version 5.0. The online project generator
allows you to quickly generate a new project in Kotlin.

Vert.x, a framework for building reactive Web applications on the JVM, offers dedicated support for Kotlin, including full documentation.

Ktor is a framework built by JetBrains for creating Web applications in Kotlin, making use of coroutines for high scalability and offering
an easy-to-use and idiomatic API.

kotlinx.html is a DSL that can be used to build HTML in Web applications. It serves as an alternative to traditional templating systems
such as JSP and FreeMarker.

Micronaut is a modern JVM-based full-stack framework for building modular, easily testable microservices and serverless applications.
It comes with a lot of useful built-in features.

http4k is the functional toolkit with a tiny footprint for Kotlin HTTP applications, written in pure Kotlin. The library is based on the "Your
Server as a Function" paper from Twitter and represents modeling both HTTP servers and clients as simple Kotlin functions that can be
composed together.

Javalin is a very lightweight web framework for Kotlin and Java which supports WebSockets, HTTP2, and async requests.

The available options for persistence include direct JDBC access, JPA, and using NoSQL databases through their Java drivers. For
JPA, the kotlin-jpa compiler plugin adapts Kotlin-compiled classes to the requirements of the framework.

61
Deploying
Kotlin
server-side
applications
Kotlin applications can be deployed into any host that supports Java Web applications, including Amazon Web Services, Google Cloud
Platform, and more.

To deploy Kotlin applications on Heroku, you can follow the official Heroku tutorial.

AWS Labs provides a sample project showing the use of Kotlin for writing AWS Lambda functions.

Google Cloud Platform offers a series of tutorials for deploying Kotlin applications to GCP, both for Ktor and App Engine and Spring and
App engine. In addition, there is an interactive code lab for deploying a Kotlin Spring application.

Products
that
use
Kotlin
on
the
server
side
Corda is an open-source distributed ledger platform that is supported by major banks and built entirely in Kotlin.

JetBrains Account, the system responsible for the entire license sales and validation process at JetBrains, is written in 100% Kotlin and
has been running in production since 2015 with no major issues.

Next
steps
For a more in-depth introduction to the language, check out the Kotlin documentation on this site and Kotlin Koans.

Watch a webinar "Micronaut for microservices with Kotlin" and explore a detailed guide showing how you can use Kotlin extension
functions in the Micronaut framework.

http4k provides the CLI to generate fully formed projects, and a starter repo to generate an entire CD pipeline using GitHub, Travis, and
Heroku with a single bash command.

Want to migrate from Java to Kotlin? Learn how to perform typical tasks with strings in Java and Kotlin.

Kotlin
for
Android
Android mobile development has been Kotlin-first since Google I/O in 2019.

Using Kotlin for Android development, you can benefit from:

Less code combined with greater readability. Spend less time writing your code and working to understand the code of others.

Mature language and environment. Since its creation in 2011, Kotlin has developed continuously, not only as a language but as a
whole ecosystem with robust tooling. Now it's seamlessly integrated in Android Studio and is actively used by many companies for
developing Android applications.

Kotlin support in Android Jetpack and other libraries. KTX extensions add Kotlin language features, such as coroutines, extension
functions, lambdas, and named parameters, to existing Android libraries.

Interoperability with Java. You can use Kotlin along with the Java programming language in your applications without needing to
migrate all your code to Kotlin.

Support for multiplatform development. You can use Kotlin for developing not only Android but also iOS, backend, and web
applications. Enjoy the benefits of sharing the common code among the platforms.

Code safety. Less code and better readability lead to fewer errors. The Kotlin compiler detects these remaining errors, making the code

62
safe.

Easy learning. Kotlin is very easy to learn, especially for Java developers.

Big community. Kotlin has great support and many contributions from the community, which is growing all over the world. According to
Google, over 60% of the top 1000 apps on the Play Store use Kotlin.

Many startups and Fortune 500 companies have already developed Android applications using Kotlin – see the list at the Google website
for Kotlin developers.

If you want to start using Kotlin for Android development, read Google's recommendation for getting started with Kotlin on Android.

If you're new to Android and want to learn to create applications with Kotlin, check out this Udacity course.

Kotlin
for
JavaScript
Kotlin/JS provides the ability to transpile your Kotlin code, the Kotlin standard library, and any compatible dependencies to JavaScript. The
current implementation of Kotlin/JS targets ES5.

The recommended way to use Kotlin/JS is via the kotlin.js and kotlin.multiplatform Gradle plugins. They let you easily set up and control
Kotlin projects targeting JavaScript in one place. This includes essential functionality such as controlling the bundling of your application,
adding JavaScript dependencies directly from npm, and more. To get an overview of the available options, check out the Kotlin/JS project
setup documentation.

Use
cases
for
Kotlin/JS
There are numerous ways to use Kotlin/JS. Here is a non-exhaustive list of scenarios in which you can use Kotlin/JS:

Write frontend web applications using Kotlin/JS

Kotlin/JS allows you to leverage powerful browser and web APIs in a type-safe fashion. Create, modify, and interact with the
elements in the Document Object Model (DOM), use Kotlin code to control the rendering of canvas or WebGL components, and
enjoy access to many more features that modern browsers support.

Write full, type-safe React applications with Kotlin/JS using the kotlin-wrappers provided by JetBrains, which provide convenient
abstractions and deep integrations for React and other popular JavaScript frameworks. kotlin-wrappers also provides support for a
select number of adjacent technologies, like react-redux, react-router, and styled-components. Interoperability with the JavaScript
ecosystem means that you can also use third-party React components and component libraries.

Use the Kotlin/JS frameworks, which take full advantage of Kotlin concepts and its expressive power and conciseness.

Write server-side and serverless applications using Kotlin/JS

The Node.js target provided by Kotlin/JS enables you to create applications that run on a server or are executed on serverless
infrastructure. This gives you all the advantages of executing in a JavaScript runtime, such as faster startup and a reduced memory
footprint. With kotlinx-nodejs, you have typesafe access to the Node.js API directly from your Kotlin code.

Use Kotlin's multiplatform projects to share code with other Kotlin targets

All the functionality of Kotlin/JS can also be accessed when using the Kotlin multiplatform Gradle plugin.

If your backend is written in Kotlin, you can share common code such as data models or validation logic with a frontend written in
Kotlin/JS, which allows you to write and maintain full-stack web applications.

You can also share business logic between your web interface and mobile apps for Android and iOS, and avoid duplicating
commonly used functionality, like providing abstractions around REST API endpoints, user authentication, or your domain models.

63
Create libraries for use with JavaScript and TypeScript

You don't have to write your whole application in Kotlin/JS – instead, you can generate libraries from your Kotlin code that can be
consumed as modules from any code base written in JavaScript or TypeScript, regardless of the other frameworks or technologies
you use. This approach of creating hybrid applications allows you to leverage the competencies that you and your team might
already have around web development while helping you reduce the amount of duplicated work, making it easier to keep your web
target consistent with other targets of your application.

Of course, this is not a complete list of all the ways you can use Kotlin/JS to your advantage, but merely some cherry-picked use cases.
We invite you to experiment with different combinations and find out what works best for your project.

Whatever your specific use case, Kotlin/JS projects can use compatible libraries from the Kotlin ecosystem, as well as third-party libraries
from the JavaScript and TypeScript ecosystems. To use the latter from Kotlin code, you can either provide your own typesafe wrappers,
use community-maintained wrappers, or let Dukat automatically generate Kotlin declarations for you. Using the Kotlin/JS-exclusive
dynamic type allows you to loosen the constraints of Kotlin's type system and skip creating detailed library wrappers, though this comes
at the expense of type safety.

Kotlin/JS is also compatible with the most common module systems: UMD, CommonJS, and AMD. The ability to produce and consume
modules means that you can interact with the JavaScript ecosystem in a structured manner.

Kotlin/JS
frameworks
Modern web development benefits significantly from frameworks that simplify building web applications. Here are a few examples of
popular web frameworks for Kotlin/JS written by different authors:

KVision
KVision is an object-oriented web framework that makes it possible to write applications in Kotlin/JS with ready-to-use components that
can be used as building blocks for your application's user interface. You can use both reactive and imperative programming models to
build your frontend, use connectors for Ktor, Spring Boot, and other frameworks to integrate it with your server-side applications, and
share code using Kotlin Multiplatform.

Visit https://kvision.io for documentation, tutorials, and examples.

For updates and discussions about the framework, join the #kvision and #javascript channels in the Kotlin Slack.

fritz2
fritz2 is a standalone framework for building reactive web user interfaces. It provides its own type-safe DSL for building and rendering
HTML elements, and it makes use of Kotlin's coroutines and flows to express components and their data bindings. It provides state
management, validation, routing, and more out of the box, and integrates with Kotlin Multiplatform projects.

Visit https://www.fritz2.dev for documentation, tutorials, and examples.

For updates and discussions about the framework, join the #fritz2 and #javascript channels in the Kotlin Slack.

Doodle
Doodle is a vector-based UI framework for Kotlin/JS. Doodle applications use the browser's graphics capabilities to draw user interfaces
instead of relying on DOM, CSS, or Javascript. By using this approach, Doodle gives you precise control over the rendering of arbitrary UI
elements, vector shapes, gradients, and custom visualizations.

Visit https://nacular.github.io/doodle/ for documentation, tutorials, and examples.

64
For updates and discussions about the framework, join the #doodle and #javascript channels in the Kotlin Slack.

Compose
for
Web
Compose for Web, a part of Compose Multiplatform, brings Google's Jetpack Compose UI toolkit to your browser. It allows you to build
reactive web user interfaces using the concepts introduced by Jetpack Compose. It provides a DOM API to describe your website, as well
as an experimental set of multiplatform layout primitives. Compose for Web also gives you the option to share parts of your UI code and
logic across Android, desktop, and the web.

You can find more information about Compose Multiplatform on its landing page.

Join the #compose-web channel on the Kotlin Slack to discuss Compose for Web, or #compose for general Compose Multiplatform
discussions.

Kotlin/JS,
Today
and
Tomorrow
In this video, Kotlin Developer Advocate Sebastian Aigner explains the main Kotlin/JS benefits, shares some tips and use cases, and talks
about the plans and upcoming features for Kotlin/JS.

Gif

Watch video online.

Get
started
with
Kotlin/JS
If you're new to Kotlin, a good first step is to familiarize yourself with the basic syntax of the language.

To start using Kotlin for JavaScript, please refer to Set up a Kotlin/JS project. You can also complete a tutorial to work through or check
out the list of Kotlin/JS sample projects for inspiration. They contain useful snippets and patterns and can serve as nice jump-off points for
your own projects.

Tutorials
for
Kotlin/JS
Build a web application with React and Kotlin/JS — tutorial guides you through the process of building a simple web application using
the React framework, shows how a type-safe Kotlin DSL for HTML makes it easy to build reactive DOM elements, and illustrates how
to use third-party React components and obtain information from APIs, all while writing the whole application logic in pure Kotlin/JS.

65
Build a full-stack web app with Kotlin Multiplatform teaches the concepts behind building an application that targets Kotlin/JVM and
Kotlin/JS by building a client-server application that makes use of shared code, serialization, and other multiplatform paradigms. It also
provides a brief introduction to working with Ktor both as a server- and client-side framework.

Sample
projects
for
Kotlin/JS

Full-stack Spring collaborative to-do list shows how to create a to-do list for collaborative work using kotlin-multiplatform with JS and
JVM targets, Spring for the backend, Kotlin/JS with React for the frontend, and RSocket.

Kotlin/JS and React Redux to-do list implements the React Redux to-do list using JS libraries (react, react-dom, react-router, redux,
and react-redux) from npm and Webpack to bundle, minify, and run the project.

Full-stack demo application guides you through the process of building an app with a feed containing user-generated posts and
comments. All data is stubbed by the fakeJSON and JSON Placeholder services.

New
Kotlin/JS
IR
compiler
The new Kotlin/JS IR compiler (currently with Beta stability) comes with a number of improvements over the current default compiler. For
example, it reduces the size of generated executables via dead code elimination and provides smoother interoperability with the
JavaScript ecosystem and its tooling. By generating TypeScript declaration files (d.ts) from Kotlin code, the new compiler makes it easier
to create "hybrid" applications that mix TypeScript and Kotlin code and to leverage code-sharing functionality using Kotlin Multiplatform.

To learn more about the available features in the new Kotlin/JS IR compiler and how to try it for your project, visit the Kotlin/JS IR compiler
documentation page and the migration guide.

Join
the
Kotlin/JS
community
You can also join the #javascript channel in the official Kotlin Slack to chat with the community and the team.

Kotlin
Native
Kotlin/Native is a technology for compiling Kotlin code to native binaries which can run without a virtual machine. Kotlin/Native includes an
LLVM-based backend for the Kotlin compiler and a native implementation of the Kotlin standard library.

Why
Kotlin/Native?
Kotlin/Native is primarily designed to allow compilation for platforms on which virtual machines are not desirable or possible, such as
embedded devices or iOS. It is ideal for situations when a developer needs to produce a self-contained program that does not require an
additional runtime or virtual machine.

Target
platforms
Kotlin/Native supports the following platforms:

macOS

iOS, tvOS, watchOS

66
Linux

Windows (MinGW)

Android NDK

To compile Apple targets, macOS, iOS, tvOS, and watchOS, you need Xcode and its command-line tools installed.

The full list of supported targets is available here.

Interoperability
Kotlin/Native supports two-way interoperability with native programming languages for different operating systems. The compiler creates:

an executable for many platforms

a static library or dynamic library with C headers for C/C++ projects

an Apple framework for Swift and Objective-C projects

Kotlin/Native supports interoperability to use existing libraries directly from Kotlin/Native:

static or dynamic C libraries

C, Swift, and Objective-C frameworks

It is easy to include compiled Kotlin code in existing projects written in C, C++, Swift, Objective-C, and other languages. It is also easy to
use existing native code, static or dynamic C libraries, Swift/Objective-C frameworks, graphical engines, and anything else directly from
Kotlin/Native.

Kotlin/Native libraries help share Kotlin code between projects. POSIX, gzip, OpenGL, Metal, Foundation, and many other popular libraries
and Apple frameworks are pre-imported and included as Kotlin/Native libraries in the compiler package.

Sharing
code
between
platforms
Multiplatform projects allow sharing common Kotlin code between multiple platforms, including Android, iOS, JVM, JavaScript, and native.
Multiplatform libraries provide required APIs for common Kotlin code and help develop shared parts of a project in Kotlin in one place and
share it with some or all target platforms.

You can use Kotlin Multiplatform Mobile to create multiplatform mobile applications with code shared between Android and iOS.

How
to
get
started

Tutorials
and
documentation
New to Kotlin? Take a look at Getting started with Kotlin.

Recommended documentation:

Kotlin Multiplatform Mobile documentation

Multiplatform documentation

67
C interop

Swift/Objective-C interop

Recommended tutorials:

Get started with Kotlin/Native

Create your first cross-platform mobile application

Types mapping between C and Kotlin/Native

Kotlin/Native as a Dynamic Library

Kotlin/Native as an Apple Framework

Kotlin
for
data
science
From building data pipelines to productionizing machine learning models, Kotlin can be a great choice for working with data:

Kotlin is concise, readable, and easy to learn.

Static typing and null safety help create reliable, maintainable code that is easy to troubleshoot.

Being a JVM language, Kotlin gives you great performance and an ability to leverage an entire ecosystem of tried and true Java
libraries.

Interactive
editors
Notebooks such as Jupyter Notebook, Datalore, and Apache Zeppelin provide convenient tools for data visualization and exploratory
research. Kotlin integrates with these tools to help you explore data, share your findings with colleagues, or build up your data science and
machine learning skills.

Jupyter
Kotlin
kernel
The Jupyter Notebook is an open-source web application that allows you to create and share documents (aka "notebooks") that can
contain code, visualizations, and Markdown text. Kotlin-jupyter is an open source project that brings Kotlin support to Jupyter Notebook.

68
Kotlin in Jupyter notebook

Check out Kotlin kernel's GitHub repo for installation instructions, documentation, and examples.

Kotlin
Notebooks
in
Datalore
With Datalore, you can use Kotlin in the browser straight out of the box, no installation required. You can also collaborate on Kotlin
notebooks in real time, get smart coding assistance when writing code, and share results as interactive or static reports. Check out a
sample report.

69
Kotlin in Datalore

Sign up and use Kotlin with a free Datalore Community account.

Zeppelin
Kotlin
interpreter
Apache Zeppelin is a popular web-based solution for interactive data analytics. It provides strong support for the Apache Spark cluster
computing system, which is particularly useful for data engineering. Starting from version 0.9.0, Apache Zeppelin comes with bundled
Kotlin interpreter.

Kotlin in Zeppelin notebook

Libraries

70
The ecosystem of libraries for data-related tasks created by the Kotlin community is rapidly expanding. Here are some libraries that you
may find useful:

Kotlin
libraries
Multik: multidimensional arrays in Kotlin. The library provides Kotlin-idiomatic, type- and dimension-safe API for mathematical
operations over multidimensional arrays. Multik offers swappable JVM and native computational engines, and a combination of the two
for optimal performance.

KotlinDL is a high-level Deep Learning API written in Kotlin and inspired by Keras. It offers simple APIs for training deep learning
models from scratch, importing existing Keras models for inference, and leveraging transfer learning for tweaking existing pre-trained
models to your tasks.

Kotlin DataFrame is a library for structured data processing. It aims to reconcile Kotlin's static typing with the dynamic nature of data
by utilizing both the full power of the Kotlin language and the opportunities provided by intermittent code execution in Jupyter
notebooks and REPLs.

Kotlin for Apache Spark adds a missing layer of compatibility between Kotlin and Apache Spark. It allows Kotlin developers to use
familiar language features such as data classes, and lambda expressions as simple expressions in curly braces or method references.

kotlin-statistics is a library providing extension functions for exploratory and production statistics. It supports basic numeric
list/sequence/array functions (from sum to skewness), slicing operators (such as countBy, simpleRegressionBy), binning operations,
discrete PDF sampling, naive bayes classifier, clustering, linear regression, and much more.

kmath is an experimental library that was intially inspired by NumPy but evolved to more flexible abstractions. It implements
mathematical operations combined in algebraic structures over Kotlin types, defines APIs for linear structures, expressions, histograms,
streaming operations, provides interchangeable wrappers over existing Java and Kotlin libraries including ND4J, Commons Math,
Multik, and others.

krangl is a library inspired by R's dplyr and Python's pandas. This library provides functionality for data manipulation using a functional-
style API; it also includes functions for filtering, transforming, aggregating, and reshaping tabular data.

lets-plot is a plotting library for statistical data written in Kotlin. Lets-Plot is multiplatform and can be used not only with JVM, but also
with JS and Python.

kravis is another library for the visualization of tabular data inspired by R's ggplot.

londogard-nlp-toolkit is a library that provides utilities when working with natural language processing such as word/subword/sentence
embeddings, word-frequencies, stopwords, stemming, and much more.

Java
libraries
Since Kotlin provides first-class interop with Java, you can also use Java libraries for data science in your Kotlin code. Here are some
examples of such libraries:

DeepLearning4J - a deep learning library for Java

ND4J - an efficient matrix math library for JVM

Dex - a Java-based data visualization tool

Smile - a comprehensive machine learning, natural language processing, linear algebra, graph, interpolation, and visualization system.
Besides Java API, Smile also provides a functional Kotlin API along with Scala and Clojure API.

Smile-NLP-kt - a Kotlin rewrite of the Scala implicits for the natural language processing part of Smile in the format of extension
functions and interfaces.

71
Apache Commons Math - a general math, statistics, and machine learning library for Java

NM Dev - a Java mathematical library that covers all of classical mathematics.

OptaPlanner - a solver utility for optimization planning problems

Charts - a scientific JavaFX charting library in development

Apache OpenNLP - a machine learning based toolkit for the processing of natural language text

CoreNLP - a natural language processing toolkit

Apache Mahout - a distributed framework for regression, clustering and recommendation

Weka - a collection of machine learning algorithms for data mining tasks

Tablesaw - a Java dataframe. It includes a visualization library based on Plot.ly

If this list doesn't cover your needs, you can find more options in the Kotlin Machine Learning Demos GitHub repository with showcases
from Thomas Nield.

Kotlin
for
competitive
programming
This tutorial is designed both for competitive programmers that did not use Kotlin before and for Kotlin developers that did not participate
in any competitive programming events before. It assumes the corresponding programming skills.

Competitive programming is a mind sport where contestants write programs to solve precisely specified algorithmic problems within strict
constraints. Problems can range from simple ones that can be solved by any software developer and require little code to get a correct
solution, to complex ones that require knowledge of special algorithms, data structures, and a lot of practice. While not being specifically
designed for competitive programming, Kotlin incidentally fits well in this domain, reducing the typical amount of boilerplate that a
programmer needs to write and read while working with the code almost to the level offered by dynamically-typed scripting languages,
while having tooling and performance of a statically-typed language.

See Get started with Kotlin/JVM on how to set up development environment for Kotlin. In competitive programming, a single project is
usually created and each problem's solution is written in a single source file.

Simple
example:
Reachable
Numbers
problem
Let's take a look at a concrete example.

Codeforces Round 555 was held on April 26th for 3rd Division, which means it had problems fit for any developer to try. You can use this
link to read the problems. The simplest problem in the set is the Problem A: Reachable Numbers. It asks to implement a straightforward
algorithm described in the problem statement.

We'd start solving it by creating a Kotlin source file with an arbitrary name. A.kt will do well. First, you need to implement a function
specified in the problem statement as:

Let's denote a function f(x) in such a way: we add 1 to x, then, while there is at least one trailing zero in the resulting number, we remove
that zero.

Kotlin is a pragmatic and unopinionated language, supporting both imperative and function programming styles without pushing the
developer towards either one. You can implement the function f in functional style, using such Kotlin features as tail recursion:

tailrec fun removeZeroes(x: Int): Int =

72
if (x % 10 == 0) removeZeroes(x / 10) else x

fun f(x: Int) = removeZeroes(x + 1)

Alternatively, you can write an imperative implementation of the function f using the traditional while loop and mutable variables that are
denoted in Kotlin with var:

fun f(x: Int): Int {


var cur = x + 1
while (cur % 10 == 0) cur /= 10
return cur
}

Types in Kotlin are optional in many places due to pervasive use of type-inference, but every declaration still has a well-defined static type
that is known at compilation.

Now, all is left is to write the main function that reads the input and implements the rest of the algorithm that the problem statement asks
for — to compute the number of different integers that are produced while repeatedly applying function f to the initial number n that is
given in the standard input.

By default, Kotlin runs on JVM and gives direct access to a rich and efficient collections library with general-purpose collections and data-
structures like dynamically-sized arrays (ArrayList), hash-based maps and sets (HashMap/HashSet), tree-based ordered maps and sets
(TreeMap/TreeSet). Using a hash-set of integers to track values that were already reached while applying function f, the straightforward
imperative version of a solution to the problem can be written as shown below:

Kotlin 1.6.0 and later

fun main() {
var n = readln().toInt() // read integer from the input
val reached = HashSet<Int>() // a mutable hash set
while (reached.add(n)) n = f(n) // iterate function f
println(reached.size) // print answer to the output
}

There is no need to handle the case of misformatted input in competitive programming. An input format is always precisely specified in competitive
programming, and the actual input cannot deviate from the input specification in the problem statement. That's why you can use Kotlin's readln() function. It
asserts that the input string is present and throws an exception otherwise. Likewise, the String.toInt() function throws an exception if the input string is not
an integer.

Earlier versions

fun main() {
var n = readLine()!!.toInt() // read integer from the input
val reached = HashSet<Int>() // a mutable hash set
while (reached.add(n)) n = f(n) // iterate function f
println(reached.size) // print answer to the output
}

Note the use of Kotlin's null-assertion operator !! after the readLine() function call. Kotlin's readLine() function is defined to return a nullable type String? and
returns null on the end of the input, which explicitly forces the developer to handle the case of missing input.

There is no need to handle the case of misformatted input in competitive programming. In competitive programming, an input format is always precisely
specified and the actual input cannot deviate from the input specification in the problem statement. That's what the null-assertion operator !! essentially
does — it asserts that the input string is present and throws an exception otherwise. Likewise, the String.toInt().

73
All online competitive programming events allow the use of pre-written code, so you can define your own library of utility functions that are
geared towards competitive programming to make your actual solution code somewhat easier to read and write. You would then use this
code as a template for your solutions. For example, you can define the following helper functions for reading inputs in competitive
programming:

Kotlin 1.6.0 and later

private fun readInt() = readln().toInt()


private fun readStr() = readln().toString()
// similar for other types you'd use in your solutions

Earlier versions

private fun readInt() = readLn().toInt()


private fun readStr() = readLn().toString()
// similar for other types you'd use in your solutions

Note the use of private visibility modifier here. While the concept of visibility modifier is not relevant for competitive programming at all, it
allows you to place multiple solution files based on the same template without getting an error for conflicting public declarations in the
same package.

Functional
operators
example:
Long
Number
problem
For more complicated problems, Kotlin's extensive library of functional operations on collections comes in handy to minimize the
boilerplate and turn the code into a linear top-to-bottom and left-to-right fluent data transformation pipeline. For example, the Problem B:
Long Number problem takes a simple greedy algorithm to implement and it can be written using this style without a single mutable
variable:

Kotlin 1.6.0 and later

fun main() {
// read input
val n = readln().toInt()
val s = readln()
val fl = readln().split(" ").map { it.toInt() }
// define local function f
fun f(c: Char) = '0' + fl[c - '1']
// greedily find first and last indices
val i = s.indexOfFirst { c -> f(c) > c }
.takeIf { it >= 0 } ?: s.length
val j = s.withIndex().indexOfFirst { (j, c) -> j > i && f(c) < c }
.takeIf { it >= 0 } ?: s.length
// compose and write the answer
val ans =
s.substring(0, i) +
s.substring(i, j).map { c -> f(c) }.joinToString("") +
s.substring(j)
println(ans)
}

Earlier versions

fun main() {
// read input

74
val n = readLine()!!.toInt()
val s = readLine()!!
val fl = readLine()!!.split(" ").map { it.toInt() }
// define local function f
fun f(c: Char) = '0' + fl[c - '1']
// greedily find first and last indices
val i = s.indexOfFirst { c -> f(c) > c }
.takeIf { it >= 0 } ?: s.length
val j = s.withIndex().indexOfFirst { (j, c) -> j > i && f(c) < c }
.takeIf { it >= 0 } ?: s.length
// compose and write the answer
val ans =
s.substring(0, i) +
s.substring(i, j).map { c -> f(c) }.joinToString("") +
s.substring(j)
println(ans)
}

In this dense code, in addition to collection transformations, you can see such handy Kotlin features as local functions and the elvis
operator ?: that allow to express idioms like "take the value if it is positive or else use length" with a concise and readable expressions like
.takeIf { it >= 0 } ?: s.length, yet it is perfectly fine with Kotlin to create additional mutable variables and express the same code in
imperative style, too.

To make reading the input in competitive programming tasks like this more concise, you can have the following list of helper input-reading
functions:

Kotlin 1.6.0 and later

private fun readInt() = readln().toInt() // single int


private fun readStrings() = readln().split(" ") // list of strings
private fun readInts() = readStrings().map { it.toInt() } // list of ints

Earlier versions

private fun readLn() = readLine()!! // string line


private fun readInt() = readLn().toInt() // single int
private fun readStrings() = readLn().split(" ") // list of strings

With these helpers, the part of code for reading input becomes simpler, closely following the input specification in the problem statement
line by line:

Kotlin 1.6.0 and later

// read input
val n = readInt()
val s = readln()
val fl = readInts()

Earlier versions

// read input
val n = readInt()
val s = readLn()
val fl = readInts()

75
Note that in competitive programming it is customary to give variables shorter names than it is typical in industrial programming practice,
since the code is to be written just once and not supported thereafter. However, these names are usually still mnemonic — a for arrays, i, j,
and others for indices, r, and c for row and column numbers in tables, x and y for coordinates, and so on. It is easier to keep the same
names for input data as it is given in the problem statement. However, more complex problems require more code which leads to using
longer self-explanatory variable and function names.

More
tips
and
tricks
Competitive programming problems often have input like this:

The first line of the input contains two integers n and k

In Kotlin this line can be concisely parsed with the following statement using destructuring declaration from a list of integers:

val (n, k) = readInts()

It might be temping to use JVM's java.util.Scanner class to parse less structured input formats. Kotlin is designed to interoperate well with
JVM libraries, so that their use feels quite natural in Kotlin. However, beware that java.util.Scanner is extremely slow. So slow, in fact, that
parsing 105 or more integers with it might not fit into a typical 2 second time-limit, which a simple Kotlin's split(" ").map { it.toInt() } would
handle.

Writing output in Kotlin is usually straightforward with println(...) calls and using Kotlin's string templates. However, care must be taken
when output contains on order of 105 lines or more. Issuing so many println calls is too slow, since the output in Kotlin is automatically
flushed after each line. A faster way to write many lines from an array or a list is using joinToString() function with "\n" as the separator, like
this:

println(a.joinToString("\n")) // each element of array/list of a separate line

Learning
Kotlin
Kotlin is easy to learn, especially for those who already know Java. A short introduction to the basic syntax of Kotlin for software
developers can be found directly in the reference section of the website starting from basic syntax.

IDEA has built-in Java-to-Kotlin converter. It can be used by people familiar with Java to learn the corresponding Kotlin syntactic
constructions, but it is not perfect, and it is still worth familiarizing yourself with Kotlin and learning the Kotlin idioms.

A great resource to study Kotlin syntax and API of the Kotlin standard library are Kotlin Koans.

What's
new
in
Kotlin
1.7.20
Release date: September 29, 2022

The Kotlin 1.7.20 release is out! Here are some highlights from this release:

The new Kotlin K2 compiler supports all-open, SAM with receiver, Lombok, and other compiler plugins

We introduced the preview of the ..< operator for creating open-ended ranges

The new Kotlin/Native memory manager is now enabled by default

76
We introduced a new experimental feature for JVM: inline classes with a generic underlying type

You can also find a short overview of the changes in this video:

Gif

Watch video online.

Support
for
Kotlin
K2
compiler
plugins
The Kotlin team continues to stabilize the K2 compiler. K2 is still in Alpha (as announced in the Kotlin 1.7.0 release), but it now supports
several compiler plugins. You can follow this YouTrack issue to get updates from the Kotlin team on the new compiler.

Starting with this 1.7.20 release, the Kotlin K2 compiler supports the following plugins:

all-open

no-arg

SAM with receiver

Lombok

AtomicFU

jvm-abi-gen

The Alpha version of the new K2 compiler only works with JVM projects. It doesn't support Kotlin/JS, Kotlin/Native, or other
multi-platform projects.

Learn more about the new compiler and its benefits in the following videos:

The Road to the New Kotlin Compiler

K2 Compiler: a Top-Down View

How
to
enable
the
Kotlin
K2
compiler

77
To enable the Kotlin K2 compiler and test it, use the following compiler option:

-Xuse-k2

You can check out the performance boost on your JVM projects and compare it with the results of the old compiler.

Leave
your
feedback
on
the
new
K2
compiler
We really appreciate your feedback in any form:

Provide your feedback directly to K2 developers in Kotlin Slack: get an invite and join the #k2-early-adopters channel.

Report any problems you faced with the new K2 compiler to our issue tracker.

Enable the Send usage statistics option to allow JetBrains collecting anonymous data about K2 usage.

Language
Kotlin 1.7.20 introduces preview versions for new language features, as well as puts restrictions on builder type inference:

Preview of the ..< operator for creating open-ended ranges

New data object declarations

Builder type inference restrictions

Preview
of
the
..<
operator
for
creating
open-ended
ranges

The new operator is Experimental, and it has limited support in the IDE.

This release introduces the new ..< operator. Kotlin has the .. operator to express a range of values. The new ..< operator acts like the until
function and helps you define the open-ended range.

Gif

78
Watch video online.

Our research shows that this new operator does a better job at expressing open-ended ranges and making it clear that the upper bound is
not included.

Here is an example of using the ..< operator in a when expression:

when (value) {
in 0.0..<0.25 -> // first quarter
in 0.25..<0.5 -> // second quarter
in 0.5..<0.75 -> // third quarter
in 0.75..1.0 -> // last quarter <- note closed range here
}

Standard library API changes


The following new types and operations will be introduced in the kotlin.ranges packages in the common Kotlin standard library:

New OpenEndRange interface


The new interface to represent open-ended ranges is very similar to the existing ClosedRange<T> interface:

interface OpenEndRange<T : Comparable<T>> {


// lower bound
val start: T
// upper bound, not included in the range
val endExclusive: T
operator fun contains(value: T): Boolean = value >= start && value < endExclusive
fun isEmpty(): Boolean = start >= endExclusive
}

Implementing OpenEndRange in the existing iterable ranges


When developers need to get a range with an excluded upper bound, they currently use the until function to effectively produce a closed
iterable range with the same values. To make these ranges acceptable in the new API that takes OpenEndRange<T>, we want to
implement that interface in the existing iterable ranges: IntRange, LongRange, CharRange, UIntRange, and ULongRange. So they will
simultaneously implement both the ClosedRange<T> and OpenEndRange<T> interfaces.

class IntRange : IntProgression(...), ClosedRange<Int>, OpenEndRange<Int> {


override val start: Int
override val endInclusive: Int
override val endExclusive: Int
}

rangeUntil operators for the standard types


The rangeUntil operators will be provided for the same types and combinations currently defined by the rangeTo operator. We provide
them as extension functions for prototype purposes, but for consistency, we plan to make them members later before stabilizing the
open-ended ranges API.

How to enable the ..< operator


To use the ..< operator or to implement that operator convention for your own types, enable the -language-version 1.8 compiler option.

The new API elements introduced to support the open-ended ranges of the standard types require an opt-in, as usual for an experimental
stdlib API: @OptIn(ExperimentalStdlibApi::class). Alternatively, you could use the -opt-in=kotlin.ExperimentalStdlibApi compiler option.

79
Read more about the new operator in this KEEP document.

Improved
string
representations
for
singletons
and
sealed
class
hierarchies
with
data
objects

Data objects are Experimental, and have limited support in the IDE at the moment.

This release introduces a new type of object declaration for you to use: data object. Data object behaves conceptually identical to a
regular object declaration but comes with a clean toString representation out of the box.

Gif

Watch video online.

package org.example
object MyObject
data object MyDataObject

fun main() {
println(MyObject) // org.example.MyObject@1f32e575
println(MyDataObject) // MyDataObject
}

This makes data object declarations perfect for sealed class hierarchies, where you may use them alongside data class declarations. In
this snippet, declaring EndOfFile as a data object instead of a plain object means that it will get a pretty toString without the need to
override it manually, maintaining symmetry with the accompanying data class definitions:

sealed class ReadResult {


data class Number(val value: Int) : ReadResult()
data class Text(val value: String) : ReadResult()
data object EndOfFile : ReadResult()
}

fun main() {
println(ReadResult.Number(1)) // Number(value=1)
println(ReadResult.Text("Foo")) // Text(value=Foo)
println(ReadResult.EndOfFile) // EndOfFile
}

80
How to enable data objects
To use data object declarations in your code, enable the -language-version 1.8 compiler option. In a Gradle project, you can do so by
adding the following to your build.gradle(.kts):

Kotlin

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
// . . .
kotlinOptions.languageVersion = "1.8"
}

Groovy

compileKotlin {
// . . .
kotlinOptions.languageVersion = '1.8'
}

Read more about data objects, and share your feedback on their implementation in the respective KEEP document.

New
builder
type
inference
restrictions
Kotlin 1.7.20 places some major restrictions on the use of builder type inference that could affect your code. These restrictions apply to
code containing builder lambda functions, where it's impossible to derive the parameter without analyzing the lambda itself. The parameter
is used as an argument. Now, the compiler will always show an error for such code and ask you to specify the type explicitly.

This is a breaking change, but our research shows that these cases are very rare, and the restrictions shouldn't affect your code. If they
do, consider the following cases:

Builder inference with extension that hides members.

If your code contains an extension function with the same name that will be used during the builder inference, the compiler will show
you an error:

class Data {
fun doSmth() {} // 1
}

fun <T> T.doSmth() {} // 2

fun test() {
buildList {
this.add(Data())
this.get(0).doSmth() // Resolves to 2 and leads to error
}
}

To fix the code, you should specify the type explicitly:

class Data {
fun doSmth() {} // 1
}

fun <T> T.doSmth() {} // 2

fun test() {
buildList<Data> { // Type argument!

81
this.add(Data())
this.get(0).doSmth() // resolves to 1
}
}

Builder inference with multiple lambdas and the type arguments are not specified explicitly.

If there are two or more lambda blocks in builder inference, they affect the type. To prevent an error, the compiler requires you to
specify the type:

fun <T: Any> buildList(


first: MutableList<T>.() -> Unit,
second: MutableList<T>.() -> Unit
): List<T> {
val list = mutableListOf<T>()
list.first()
list.second()
return list
}

fun main() {
buildList(
first = { // this: MutableList<String>
add("")
},
second = { // this: MutableList<Int>
val i: Int = get(0)
println(i)
}
)
}

To fix the error, you should specify the type explicitly and fix the type mismatch:

fun main() {
buildList<Int>(
first = { // this: MutableList<Int>
add(0)
},
second = { // this: MutableList<Int>
val i: Int = get(0)
println(i)
}
)
}

If you haven't found your case mentioned above, file an issue to our team.

See this YouTrack issue for more information about this builder inference update.

Kotlin/JVM
Kotlin 1.7.20 introduces generic inline classes, adds more bytecode optimizations for delegated properties, and supports IR in the kapt
stub generating task, making it possible to use all the newest Kotlin features with kapt:

Generic inline classes

More optimized cases of delegated properties

Support for the JVM IR backend in kapt stub generating task

82
Generic
inline
classes

Generic inline classes is an Experimental feature. It may be dropped or changed at any time. Opt-in is required (see details
below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

Kotlin 1.7.20 allows the underlying type of JVM inline classes to be a type parameter. The compiler maps it to Any? or, generally, to the
upper bound of the type parameter.

Gif

Watch video online.

Consider the following example:

@JvmInline
value class UserId<T>(val value: T)

fun compute(s: UserId<String>) {} // compiler generates fun compute-<hashcode>(s: Any?)

The function accepts the inline class as a parameter. The parameter is mapped to the upper bound, not the type argument.

To enable this feature, use the -language-version 1.8 compiler option.

We would appreciate your feedback on this feature in YouTrack.

More
optimized
cases
of
delegated
properties
In Kotlin 1.6.0, we optimized the case of delegating to a property by omitting the $delegate field and generating immediate access to the
referenced property. In 1.7.20, we've implemented this optimization for more cases. The $delegate field will now be omitted if a delegate
is:

A named object:

object NamedObject {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String = ...
}

val s: String by NamedObject

83
A final val property with a backing field and a default getter in the same module:

val impl: ReadOnlyProperty<Any?, String> = ...

class A {
val s: String by impl
}

A constant expression, an enum entry, this, or null. Here's an example of this:

class A {
operator fun getValue(thisRef: Any?, property: KProperty<*>) ...

val s by this
}

Learn more about delegated properties.

We would appreciate your feedback on this feature in YouTrack.

Support
for
the
JVM
IR
backend
in
kapt
stub
generating
task

Support for the JVM IR backend in the kapt stub generating task is an Experimental feature. It may be changed at any time. Opt-
in is required (see details below), and you should use it only for evaluation purposes.

Before 1.7.20, the kapt stub generating task used the old backend, and repeatable annotations didn't work with kapt. With Kotlin 1.7.20,
we've added support for the JVM IR backend in the kapt stub generating task. This makes it possible to use all the newest Kotlin features
with kapt, including repeatable annotations.

To use the IR backend in kapt, add the following option to your gradle.properties file:

kapt.use.jvm.ir=true

We would appreciate your feedback on this feature in YouTrack.

Kotlin/Native
Kotlin 1.7.20 comes with the new Kotlin/Native memory manager enabled by default and gives you the option to customize the Info.plist
file:

The new default memory manager

Customizing the Info.plist file

The
new
Kotlin/Native
memory
manager
enabled
by
default
This release brings further stability and performance improvements to the new memory manager, allowing us to promote the new memory
manager to Beta.

The previous memory manager complicated writing concurrent and asynchronous code, including issues with implementing the

84
kotlinx.coroutines library. This blocked the adoption of Kotlin Multiplatform Mobile because concurrency limitations created problems with
sharing Kotlin code between iOS and Android platforms. The new memory manager finally paves the way to promote Kotlin Multiplatform
Mobile to Beta.

The new memory manager also supports the compiler cache that makes compilation times comparable to previous releases. For more on
the benefits of the new memory manager, see our original blog post for the preview version. You can find more technical details in the
documentation.

Configuration and setup


Starting with Kotlin 1.7.20, the new memory manager is the default. Not much additional setup is required.

If you've already turned it on manually, you can remove the kotlin.native.binary.memoryModel=experimental option from your
gradle.properties or binaryOptions["memoryModel"] = "experimental" from the build.gradle(.kts) file.

If necessary, you can switch back to the legacy memory manager with the kotlin.native.binary.memoryModel=strict option in your
gradle.properties. However, compiler cache support is no longer available for the legacy memory manager, so compilation times might
worsen.

Freezing
In the new memory manager, freezing is deprecated. Don't use it unless you need your code to work with the legacy manager (where
freezing is still required). This may be helpful for library authors that need to maintain support for the legacy memory manager or
developers who want to have a fallback if they encounter issues with the new memory manager.

In such cases, you can temporarily support code for both new and legacy memory managers. To ignore deprecation warnings, do one of
the following:

Annotate usages of the deprecated API with @OptIn(FreezingIsDeprecated::class).

Apply languageSettings.optIn("kotlin.native.FreezingIsDeprecated") to all the Kotlin source sets in Gradle.

Pass the compiler flag -opt-in=kotlin.native.FreezingIsDeprecated.

Calling Kotlin suspending functions from Swift/Objective-C


The new memory manager still restricts calling Kotlin suspend functions from Swift and Objective-C from threads other than the main one,
but you can lift it with a new Gradle option.

This restriction was originally introduced in the legacy memory manager due to cases where the code dispatched a continuation to be
resumed on the original thread. If this thread didn't have a supported event loop, the task would never run, and the coroutine would never
be resumed.

In certain cases, this restriction is no longer required, but a check of all the necessary conditions can't be easily implemented. Because of
this, we decided to keep it in the new memory manager while introducing an option for you to disable it. For this, add the following option
to your gradle.properties:

kotlin.native.binary.objcExportSuspendFunctionLaunchThreadRestriction=none

Do not add this option if you use the native-mt version of kotlinx.coroutines or other libraries that have the same "dispatch to the
original thread" approach.

The Kotlin team is very grateful to Ahmed El-Helw for implementing this option.

85
Leave your feedback
This is a significant change to our ecosystem. We would appreciate your feedback to help make it even better.

Try the new memory manager on your projects and share feedback in our issue tracker, YouTrack.

Customizing
the
Info.plist
file
When producing a framework, the Kotlin/Native compiler generates the information property list file, Info.plist. Previously, it was
cumbersome to customize its contents. With Kotlin 1.7.20, you can directly set the following properties:

Property Binary option

CFBundleIdentifier bundleId

CFBundleShortVersionString bundleShortVersionString

CFBundleVersion bundleVersion

To do that, use the corresponding binary option. Pass the -Xbinary=$option=$value compiler flag or set the binaryOption(option, value)
Gradle DSL for the necessary framework.

The Kotlin team is very grateful to Mads Ager for implementing this feature.

Kotlin/JS
Kotlin/JS has received some enhancements that improve the developer experience and boost performance:

Klib generation is faster in both incremental and clean builds, thanks to efficiency improvements for the loading of dependencies.

Incremental compilation for development binaries has been reworked, resulting in major improvements in clean build scenarios, faster
incremental builds, and stability fixes.

We've improved .d.ts generation for nested objects, sealed classes, and optional parameters in constructors.

Gradle
The updates for the Kotlin Gradle plugin are focused on compatibility with the new Gradle features and the latest Gradle versions.

Kotlin 1.7.20 contains changes to support Gradle 7.1. Deprecated methods and properties were removed or replaced, reducing the
number of deprecation warnings produced by the Kotlin Gradle plugin and unblocking future support for Gradle 8.0.

There are, however, some potentially breaking changes that may need your attention:

Target
configuration
org.jetbrains.kotlin.gradle.dsl.SingleTargetExtension now has a generic parameter, SingleTargetExtension<T : KotlinTarget>.

The kotlin.targets.fromPreset() convention has been deprecated. Instead, you can still use kotlin.targets { fromPreset() }, but we
recommend using more specialized ways to create targets.

86
Target accessors auto-generated by Gradle are no longer available inside the kotlin.targets { } block. Please use the
findByName("targetName") method instead.

Note that such accessors are still available in the case of kotlin.targets, for example, kotlin.targets.linuxX64.

Source
directories
configuration
The Kotlin Gradle plugin now adds Kotlin SourceDirectorySet as a kotlin extension to Java's SourceSet group. This makes it possible to
configure source directories in the build.gradle.kts file similarly to how they are configured in Java, Groovy, and Scala:

sourceSets {
main {
kotlin {
java.setSrcDirs(listOf("src/java"))
kotlin.setSrcDirs(listOf("src/kotlin"))
}
}
}

You no longer need to use a deprecated Gradle convention and specify the source directories for Kotlin.

Remember that you can also use the kotlin extension to access KotlinSourceSet:

kotlin {
sourceSets {
main {
// …
}
}
}

New
method
for
JVM
toolchain
configuration
This release provides the new jvmToolchain() method for enabling the JVM toolchain feature. If you don't need any additional configuration
fields, such as implementation or vendor, you can use this method from the Kotlin extension:

kotlin {
jvmToolchain(17)
}

This simplifies the Kotlin project setup process without any additional configuration. Before this release, you could specify the JDK version
only in the following way:

kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

Standard
library
Kotlin 1.7.20 offers new extension functions for the java.nio.file.Path class, which allows you to walk through a file tree:

walk() lazily traverses the file tree rooted at the specified path.

87
fileVisitor() makes it possible to create a FileVisitor separately. FileVisitor defines actions on directories and files when traversing them.

visitFileTree(fileVisitor: FileVisitor, ...) consumes a ready FileVisitor and uses java.nio.file.Files.walkFileTree() under the hood.

visitFileTree(..., builderAction: FileVisitorBuilder.() -> Unit) creates a FileVisitor with the builderAction and calls the visitFileTree(fileVisitor,
...) function.

FileVisitResult, return type of FileVisitor, has the CONTINUE default value that continues the processing of the file.

The new extension functions for java.nio.file.Path are Experimental. They may be changed at any time. Opt-in is required (see
details below), and you should use them only for evaluation purposes.

Here are some things you can do with these new extension functions:

Explicitly create a FileVisitor and then use:

val cleanVisitor = fileVisitor {


onPreVisitDirectory { directory, attributes ->
// Some logic on visiting directories
FileVisitResult.CONTINUE
}

onVisitFile { file, attributes ->


// Some logic on visiting files
FileVisitResult.CONTINUE
}
}

// Some logic may go here

projectDirectory.visitFileTree(cleanVisitor)

Create a FileVisitor with the builderAction and use it immediately:

projectDirectory.visitFileTree {
// Definition of the builderAction:
onPreVisitDirectory { directory, attributes ->
// Some logic on visiting directories
FileVisitResult.CONTINUE
}

onVisitFile { file, attributes ->


// Some logic on visiting files
FileVisitResult.CONTINUE
}
}

Traverse a file tree rooted at the specified path with the walk() function:

@OptIn(kotlin.io.path.ExperimentalPathApi::class)
fun taverseFileTree() {
val cleanVisitor = fileVisitor {
onPreVisitDirectory { directory, _ ->
if (directory.name == "build") {
directory.toFile().deleteRecursively()
FileVisitResult.SKIP_SUBTREE
} else {
FileVisitResult.CONTINUE
}

88
}

onVisitFile { file, _ ->


if (file.extension == "class") {
file.deleteExisting()
}
FileVisitResult.CONTINUE
}
}

val rootDirectory = createTempDirectory("Project")

rootDirectory.resolve("src").let { srcDirectory ->


srcDirectory.createDirectory()
srcDirectory.resolve("A.kt").createFile()
srcDirectory.resolve("A.class").createFile()
}

rootDirectory.resolve("build").let { buildDirectory ->


buildDirectory.createDirectory()
buildDirectory.resolve("Project.jar").createFile()
}

// Use walk function:


val directoryStructure = rootDirectory.walk(PathWalkOption.INCLUDE_DIRECTORIES)
.map { it.relativeTo(rootDirectory).toString() }
.toList().sorted()
assertPrints(directoryStructure, "[, build, build/Project.jar, src, src/A.class, src/A.kt]")

rootDirectory.visitFileTree(cleanVisitor)

val directoryStructureAfterClean = rootDirectory.walk(PathWalkOption.INCLUDE_DIRECTORIES)


.map { it.relativeTo(rootDirectory).toString() }
.toList().sorted()
assertPrints(directoryStructureAfterClean, "[, src, src/A.kt]")
//sampleEnd
}

As is usual for an experimental API, the new extensions require an opt-in: @OptIn(kotlin.io.path.ExperimentalPathApi::class) or
@kotlin.io.path.ExperimentalPathApi. Alternatively, you can use a compiler option: -opt-in=kotlin.io.path.ExperimentalPathApi.

We would appreciate your feedback on the walk() function and the visit extension functions in YouTrack.

Documentation
updates
Since the previous release, the Kotlin documentation has received some notable changes:

Revamped
and
improved
pages

Basic types overview − learn about the basic types used in Kotlin: numbers, Booleans, characters, strings, arrays, and unsigned integer
numbers.

IDEs for Kotlin development − see the list of IDEs with official Kotlin support and tools that have community-supported plugins.

New
articles
in
the
Kotlin
Multiplatform
journal

Native and cross-platform app development: how to choose? − check out our overview and advantages of cross-platform app
development and the native approach.

89
The six best cross-platform app development frameworks − read about the key aspects to help you choose the right framework for
your cross-platform project.

New
and
updated
tutorials

Get started with Kotlin Multiplatform Mobile − learn about cross-platform mobile development with Kotlin and create an app that works
on both Android and iOS.

Build a full-stack web app with Kotlin Multiplatform − create an app using Kotlin throughout the whole stack, with a Kotlin/JVM server
part and a Kotlin/JS web client.

Build a web application with React and Kotlin/JS − create a browser app exploring Kotlin's DSLs and features of a typical React
program.

Changes
in
release
documentation
We no longer provide a list of recommended kotlinx libraries for each release. This list included only the versions recommended and tested
with Kotlin itself. It didn't take into account that some libraries depend on each other and require a special kotlinx version, which may differ
from the recommended Kotlin version.

We're working on finding a way to provide information on how libraries interrelate and depend on each other so that it will be clear which
kotlinx library version you should use when you upgrade the Kotlin version in your project.

Install
Kotlin
1.7.20
IntelliJ IDEA 2021.3, 2022.1, and 2022.2 automatically suggest updating the Kotlin plugin to 1.7.20.

For Android Studio Dolphin (213), Electric Eel (221), and Flamingo (222), the Kotlin plugin 1.7.20 will be delivered with upcoming
Android Studios updates.

The new command-line compiler is available for download on the GitHub release page.

Compatibility
guide
for
Kotlin
1.7.20
Although Kotlin 1.7.20 is an incremental release, there are still incompatible changes we had to make to limit spread of the issues
introduced in Kotlin 1.7.0.

Find the detailed list of such changes in the Compatibility guide for Kotlin 1.7.20.

What's
new
in
Kotlin
1.7.0
Release date: 9 June 2022

Kotlin 1.7.0 has been released. It unveils the Alpha version of the new Kotlin/JVM K2 compiler, stabilizes language features, and brings
performance improvements for the JVM, JS, and Native platforms.

Here is a list of the major updates in this version:

The new Kotlin K2 compiler is in Alpha now, and it offers serious performance improvements. It is available only for the JVM, and none

90
of the compiler plugins, including kapt, work with it.

A new approach to the incremental compilation in Gradle. Incremental compilation is now also supported for changes made inside
dependent non-Kotlin modules and is compatible with Gradle.

We've stabilized opt-in requirement annotations, definitely non-nullable types, and builder inference.

There's now an underscore operator for type args. You can use it to automatically infer a type of argument when other types are
specified.

This release allows implementation by delegation to an inlined value of an inline class. You can now create lightweight wrappers that do
not allocate memory in most cases.

You can also find a short overview of the changes in this video:

Gif

Watch video online.

New
Kotlin
K2
compiler
for
the
JVM
in
Alpha
This Kotlin release introduces the Alpha version of the new Kotlin K2 compiler. The new compiler aims to speed up the development of
new language features, unify all of the platforms Kotlin supports, bring performance improvements, and provide an API for compiler
extensions.

We've already published some detailed explanations of our new compiler and its benefits:

The Road to the New Kotlin Compiler

K2 Compiler: a Top-Down View

It's important to point out that with the Alpha version of the new K2 compiler we were primarily focused on performance improvements,
and it only works with JVM projects. It doesn't support Kotlin/JS, Kotlin/Native, or other multi-platform projects, and none of compiler
plugins, including kapt, work with it.

Our benchmarks show some outstanding results on our internal projects:

Project Current Kotlin compiler performance New K2 Kotlin compiler performance Performance boost

91
Project Current Kotlin compiler performance New K2 Kotlin compiler performance Performance boost

Kotlin 2.2 KLOC/s 4.8 KLOC/s ~ x2.2

YouTrack 1.8 KLOC/s 4.2 KLOC/s ~ x2.3

IntelliJ IDEA 1.8 KLOC/s 3.9 KLOC/s ~ x2.2

Space 1.2 KLOC/s 2.8 KLOC/s ~ x2.3

The KLOC/s performance numbers stand for the number of thousands of lines of code that the compiler processes per second.

You can check out the performance boost on your JVM projects and compare it with the results of the old compiler. To enable the Kotlin
K2 compiler, use the following compiler option:

-Xuse-k2

Also, the K2 compiler includes a number of bugfixes. Please note that even issues with State: Open from this list are in fact fixed in K2.

The next Kotlin releases will improve the stability of the K2 compiler and provide more features, so stay tuned!

If you face any performance issues with the Kotlin K2 compiler, please report them to our issue tracker.

Language
Kotlin 1.7.0 introduces support for implementation by delegation and a new underscore operator for type arguments. It also stabilizes
several language features introduced as previews in previous releases:

Implementation by delegation to inlined value of inline class

Underscore operator for type arguments

Stable builder inference

Stable opt-in requirements

Stable definitely non-nullable types

Allow
implementation
by
delegation
to
an
inlined
value
of
an
inline
class
If you want to create a lightweight wrapper for a value or class instance, it's necessary to implement all interface methods by hand.
Implementation by delegation solves this issue, but it did not work with inline classes before 1.7.0. This restriction has been removed, so
you can now create lightweight wrappers that do not allocate memory in most cases.

interface Bar {

92
fun foo() = "foo"
}

@JvmInline
value class BarWrapper(val bar: Bar): Bar by bar

fun main() {
val bw = BarWrapper(object: Bar {})
println(bw.foo())
}

Underscore
operator
for
type
arguments
Kotlin 1.7.0 introduces an underscore operator, _, for type arguments. You can use it to automatically infer a type argument when other
types are specified:

abstract class SomeClass<T> {


abstract fun execute(): T
}

class SomeImplementation : SomeClass<String>() {


override fun execute(): String = "Test"
}

class OtherImplementation : SomeClass<Int>() {


override fun execute(): Int = 42
}

object Runner {
inline fun <reified S: SomeClass<T>, T> run(): T {
return S::class.java.getDeclaredConstructor().newInstance().execute()
}
}

fun main() {
// T is inferred as String because SomeImplementation derives from SomeClass<String>
val s = Runner.run<SomeImplementation, _>()
assert(s == "Test")

// T is inferred as Int because OtherImplementation derives from SomeClass<Int>


val n = Runner.run<OtherImplementation, _>()
assert(n == 42)
}

You can use the underscore operator in any position in the variables list to infer a type argument.

Stable
builder
inference
Builder inference is a special kind of type inference that is useful when calling generic builder functions. It helps the compiler infer the type
arguments of a call using the type information about other calls inside its lambda argument.

Starting with 1.7.0, builder inference is automatically activated if a regular type inference cannot get enough information about a type
without specifying the -Xenable-builder-inference compiler option, which was introduced in 1.6.0.

Learn how to write custom generic builders.

Stable
opt-in
requirements
Opt-in requirements are now Stable and do not require additional compiler configuration.

93
Before 1.7.0, the opt-in feature itself required the argument -opt-in=kotlin.RequiresOptIn to avoid a warning. It no longer requires this;
however, you can still use the compiler argument -opt-in to opt-in for other annotations, module-wise.

Stable
definitely
non-nullable
types
In Kotlin 1.7.0, definitely non-nullable types have been promoted to Stable. They provide better interoperability when extending generic
Java classes and interfaces.

You can mark a generic type parameter as definitely non-nullable at the use site with the new syntax T & Any. The syntactic form comes
from the notation for intersection types and is now limited to a type parameter with nullable upper bounds on the left side of & and a non-
nullable Any on the right side:

fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y

fun main() {
// OK
elvisLike<String>("", "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String>("", null).length

// OK
elvisLike<String?>(null, "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String?>(null, null).length
}

Learn more about definitely non-nullable types in this KEEP.

Kotlin/JVM
This release brings performance improvements for the Kotlin/JVM compiler and a new compiler option. Additionally, callable references to
functional interface constructors have become Stable. Note that since 1.7.0, the default target version for Kotlin/JVM compilations is now
1.8.

Compiler performance optimizations

New compiler option -Xjdk-release

Stable callable references to functional interface constructors

Removed the JVM target version 1.6

Compiler
performance
optimizations
Kotlin 1.7.0 introduces performance improvements for the Kotlin/JVM compiler. According to our benchmarks, compilation time has been
reduced by 10% on average compared to Kotlin 1.6.0. Projects with lots of usages of inline functions, for example, projects using
kotlinx.html, will compile faster thanks to the improvements to the bytecode postprocessing.

New
compiler
option:
-Xjdk-release
Kotlin 1.7.0 presents a new compiler option, -Xjdk-release. This option is similar to the javac's command-line --release option. The -Xjdk-
release option controls the target bytecode version and limits the API of the JDK in the classpath to the specified Java version. For
example, kotlinc -Xjdk-release=1.8 won't allow referencing java.lang.Module even if the JDK in the dependencies is version 9 or higher.

94
This option is not guaranteed to be effective for each JDK distribution.

Please leave your feedback on this YouTrack ticket.

Stable
callable
references
to
functional
interface
constructors
Callable references to functional interface constructors are now Stable. Learn how to migrate from an interface with a constructor function
to a functional interface using callable references.

Please report any issues you find in YouTrack.

Removed
JVM
target
version
1.6
The default target version for Kotlin/JVM compilations is 1.8. The 1.6 target has been removed.

Please migrate to JVM target 1.8 or above. Learn how to update the JVM target version for:

Gradle

Maven

The command-line compiler

Kotlin/Native
Kotlin 1.7.0 includes changes to Objective-C and Swift interoperability and stabilizes features that were introduced in previous releases. It
also brings performance improvements for the new memory manager along with other updates:

Performance improvements for the new memory manager

Unified compiler plugin ABI with JVM and JS IR backends

Support for standalone Android executables

Interop with Swift async/await: returning Void instead of KotlinUnit

Prohibited undeclared exceptions through Objective-C bridges

Improved CocoaPods integration

Overriding of the Kotlin/Native compiler download URL

Performance
improvements
for
the
new
memory
manager

The new Kotlin/Native memory manager is in Alpha. It may change incompatibly and require manual migration in the future. We
would appreciate your feedback in YouTrack.

The new memory manager is still in Alpha, but it is on its way to becoming Stable. This release delivers significant performance
improvements for the new memory manager, especially in garbage collection (GC). In particular, concurrent implementation of the sweep
phase, introduced in 1.6.20, is now enabled by default. This helps reduce the time the application is paused for GC. The new GC
scheduler is better at choosing the GC frequency, especially for larger heaps.

95
Also, we've specifically optimized debug binaries, ensuring that the proper optimization level and link-time optimizations are used in the
implementation code of the memory manager. This helped us improve execution time by roughly 30% for debug binaries on our
benchmarks.

Try using the new memory manager in your projects to see how it works, and share your feedback with us in YouTrack.

Unified
compiler
plugin
ABI
with
JVM
and
JS
IR
backends
Starting with Kotlin 1.7.0, the Kotlin Multiplatform Gradle plugin uses the embeddable compiler jar for Kotlin/Native by default. This feature
was announced in 1.6.0 as Experimental, and now it's stable and ready to use.

This improvement is very handy for library authors, as it improves the compiler plugin development experience. Before this release, you
had to provide separate artifacts for Kotlin/Native, but now you can use the same compiler plugin artifacts for Native and other supported
platforms.

This feature might require plugin developers to take migration steps for their existing plugins.

Learn how to prepare your plugin for the update in this YouTrack issue.

Support
for
standalone
Android
executables
Kotlin 1.7.0 provides full support for generating standard executables for Android Native targets. It was introduced in 1.6.20, and now it's
enabled by default.

If you want to roll back to the previous behavior when Kotlin/Native generated shared libraries, use the following setting:

binaryOptions["androidProgramType"] = "nativeActivity"

Interop
with
Swift
async/await:
returning
Void
instead
of
KotlinUnit
Kotlin suspend functions now return the Void type instead of KotlinUnit in Swift. This is the result of the improved interop with Swift's
async/await. This feature was introduced in 1.6.20, and this release enables this behavior by default.

You don't need to use the kotlin.native.binary.unitSuspendFunctionObjCExport=proper property anymore to return the proper type for
such functions.

Prohibited
undeclared
exceptions
through
Objective-C
bridges
When you call Kotlin code from Swift/Objective-C code (or vice versa) and this code throws an exception, it should be handled by the
code where the exception occurred, unless you specifically allowed the forwarding of exceptions between languages with proper
conversion (for example, using the @Throws annotation).

Previously, Kotlin had another unintended behavior where undeclared exceptions could "leak" from one language to another in some
cases. Kotlin 1.7.0 fixes that issue, and now such cases lead to program termination.

So, for example, if you have a { throw Exception() } lambda in Kotlin and call it from Swift, in Kotlin 1.7.0 it will terminate as soon as the
exception reaches the Swift code. In previous Kotlin versions, such an exception could leak to the Swift code.

The @Throws annotation continues to work as before.

Improved
CocoaPods
integration

96
Starting with Kotlin 1.7.0, you no longer need to install the cocoapods-generate plugin if you want to integrate CocoaPods in your projects.

Previously, you needed to install both the CocoaPods dependency manager and the cocoapods-generate plugin to use CocoaPods, for
example, to handle iOS dependencies in Kotlin Multiplatform Mobile projects.

Now setting up the CocoaPods integration is easier, and we've resolved the issue when cocoapods-generate couldn't be installed on
Ruby 3 and later. Now the newest Ruby versions that work better on Apple M1 are also supported.

See how to set up the initial CocoaPods integration.

Overriding
the
Kotlin/Native
compiler
download
URL
Starting with Kotlin 1.7.0, you can customize the download URL for the Kotlin/Native compiler. This is useful when external links on the CI
are forbidden.

To override the default base URL https://download.jetbrains.com/kotlin/native/builds, use the following Gradle property:

kotlin.native.distribution.baseDownloadUrl=https://example.com

The downloader will append the native version and target OS to this base URL to ensure it downloads the actual compiler
distribution.

Kotlin/JS
Kotlin/JS is receiving further improvements to the JS IR compiler backend along with other updates that can make your development
experience better:

Performance improvements for the new IR backend

Minification for member names when using IR

Support for older browsers via polyfills in the IR backend

Dynamically load JavaScript modules from js expressions

Specify environment variables for JavaScript test runners

Performance
improvements
for
the
new
IR
backend
This release has some major updates that should improve your development experience:

Incremental compilation performance of Kotlin/JS has been significantly improved. It takes less time to build your JS projects.
Incremental rebuilds should now be roughly on par with the legacy backend in many cases now.

The Kotlin/JS final bundle requires less space, as we have significantly reduced the size of the final artifacts. We've measured up to a
20% reduction in the production bundle size compared to the legacy backend for some large projects.

Type checking for interfaces has been improved by orders of magnitude.

Kotlin generates higher-quality JS code

Minification
for
member
names
when
using
IR

97
The Kotlin/JS IR compiler now uses its internal information about the relationships of your Kotlin classes and functions to apply more
efficient minification, shortening the names of functions, properties, and classes. This shrinks the resulting bundled applications.

This type of minification is automatically applied when you build your Kotlin/JS application in production mode and is enabled by default.
To disable member name minification, use the -Xir-minimized-member-names compiler flag:

kotlin {
js(IR) {
compilations.all {
compileKotlinTask.kotlinOptions.freeCompilerArgs += listOf("-Xir-minimized-member-names=false")
}
}
}

Support
for
older
browsers
via
polyfills
in
the
IR
backend
The IR compiler backend for Kotlin/JS now includes the same polyfills as the legacy backend. This allows code compiled with the new
compiler to run in older browsers that do not support all the methods from ES2015 used by the Kotlin standard library. Only those polyfills
actually used by the project are included in the final bundle, which minimizes their potential impact on the bundle size.

This feature is enabled by default when using the IR compiler, and you don't need to configure it.

Dynamically
load
JavaScript
modules
from
js
expressions
When working with the JavaScript modules, most applications use static imports, whose use is covered with the JavaScript module
integration. However, Kotlin/JS was missing a mechanism to load JavaScript modules dynamically at runtime in your applications.

Starting with Kotlin 1.7.0, the import statement from JavaScript is supported in js blocks, allowing you to dynamically bring packages into
your application at runtime:

val myPackage = js("import('my-package')")

Specify
environment
variables
for
JavaScript
test
runners
To tune Node.js package resolution or pass external information to Node.js tests, you can now specify environment variables used by the
JavaScript test runners. To define an environment variable, use the environment() function with a key-value pair inside the testTask block
in your build script:

kotlin {
js {
nodejs {
testTask {
environment("key", "value")
}
}
}
}

Standard
library
In Kotlin 1.7.0, the standard library has received a range of changes and improvements. They introduce new features, stabilize
experimental ones, and unify support for named capturing groups for Native, JS, and the JVM:

98
min() and max() collection functions return as non-nullable

Regular expression matching at specific indices

Extended support of previous language and API versions

Access to annotations via reflection

Stable deep recursive functions

Time marks based on inline classes for default time source

New experimental extension functions for Java Optionals

Support for named capturing groups in JS and Native

min()
and
max()
collection
functions
return
as
non-nullable
In Kotlin 1.4.0, we renamed the min() and max() collection functions to minOrNull() and maxOrNull(). These new names better reflect their
behavior – returning null if the receiver collection is empty. It also helped align the functions' behavior with naming conventions used
throughout the Kotlin collections API.

The same was true of minBy(), maxBy(), minWith(), and maxWith(), which all got their *OrNull() synonyms in Kotlin 1.4.0. Older functions
affected by this change were gradually deprecated.

Kotlin 1.7.0 reintroduces the original function names, but with a non-nullable return type. The new min(), max(), minBy(), maxBy(),
minWith(), and maxWith() functions now strictly return the collection element or throw an exception.

fun main() {
val numbers = listOf<Int>()
println(numbers.maxOrNull()) // "null"
println(numbers.max()) // "Exception in... Collection is empty."
}

Regular
expression
matching
at
specific
indices
The Regex.matchAt() and Regex.matchesAt() functions, introduced in 1.5.30, are now Stable. They provide a way to check whether a
regular expression has an exact match at a particular position in a String or CharSequence.

matchesAt() checks for a match and returns a boolean result:

fun main() {
val releaseText = "Kotlin 1.7.0 is on its way!"
// regular expression: one digit, dot, one digit, dot, one or more digits
val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()

println(versionRegex.matchesAt(releaseText, 0)) // "false"


println(versionRegex.matchesAt(releaseText, 7)) // "true"
}

matchAt() returns the match if it's found, or null if it isn't:

fun main() {
val releaseText = "Kotlin 1.7.0 is on its way!"
val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()

println(versionRegex.matchAt(releaseText, 0)) // "null"


println(versionRegex.matchAt(releaseText, 7)?.value) // "1.7.0"

99
}

We'd be grateful for your feedback on this YouTrack issue.

Extended
support
for
previous
language
and
API
versions
To support library authors developing libraries that are meant to be consumable in a wide range of previous Kotlin versions, and to
address the increased frequency of major Kotlin releases, we have extended our support for previous language and API versions.

With Kotlin 1.7.0, we're supporting three previous language and API versions rather than two. This means Kotlin 1.7.0 supports the
development of libraries targeting Kotlin versions down to 1.4.0. For more information on backward compatibility, see Compatibility
modes.

Access
to
annotations
via
reflection
The KAnnotatedElement.findAnnotations() extension function, which was first introduced in 1.6.0, is now Stable. This reflection function
returns all annotations of a given type on an element, including individually applied and repeated annotations.

@Repeatable
annotation class Tag(val name: String)

@Tag("First Tag")
@Tag("Second Tag")
fun taggedFunction() {
println("I'm a tagged function!")
}

fun main() {
val x = ::taggedFunction
val foo = x as KAnnotatedElement
println(foo.findAnnotations<Tag>())
// [@Tag(name=First Tag), @Tag(name=Second Tag)]
}

Stable
deep
recursive
functions
Deep recursive functions have been available as an experimental feature since Kotlin 1.4.0, and they are now Stable in Kotlin 1.7.0. Using
DeepRecursiveFunction, you can define a function that keeps its stack on the heap instead of using the actual call stack. This allows you
to run very deep recursive computations. To call a deep recursive function, invoke it.

In this example, a deep recursive function is used to calculate the depth of a binary tree recursively. Even though this sample function calls
itself recursively 100,000 times, no StackOverflowError is thrown:

class Tree(val left: Tree?, val right: Tree?)

val calculateDepth = DeepRecursiveFunction<Tree?, Int> { t ->


if (t == null) 0 else maxOf(
callRecursive(t.left),
callRecursive(t.right)
) + 1
}

fun main() {
// Generate a tree with a depth of 100_000
val deepTree = generateSequence(Tree(null, null)) { prev ->
Tree(prev, null)
}.take(100_000).last()

println(calculateDepth(deepTree)) // 100000

100
}

Consider using deep recursive functions in your code where your recursion depth exceeds 1000 calls.

Time
marks
based
on
inline
classes
for
default
time
source
Kotlin 1.7.0 improves the performance of time measurement functionality by changing the time marks returned by TimeSource.Monotonic
into inline value classes. This means that calling functions like markNow(), elapsedNow(), measureTime(), and measureTimedValue()
doesn't allocate wrapper classes for their TimeMark instances. Especially when measuring a piece of code that is part of a hot path, this
can help minimize the performance impact of the measurement:

@OptIn(ExperimentalTime::class)
fun main() {
val mark = TimeSource.Monotonic.markNow() // Returned `TimeMark` is inline class
val elapsedDuration = mark.elapsedNow()
}

This optimization is only available if the time source from which the TimeMark is obtained is statically known to be
TimeSource.Monotonic.

New
experimental
extension
functions
for
Java
Optionals
Kotlin 1.7.0 comes with new convenience functions that simplify working with Optional classes in Java. These new functions can be used
to unwrap and convert optional objects on the JVM and help make working with Java APIs more concise.

The getOrNull(), getOrDefault(), and getOrElse() extension functions allow you to get the value of an Optional if it's present. Otherwise, you
get a default value, null, or a value returned by a function, respectively:

val presentOptional = Optional.of("I'm here!")

println(presentOptional.getOrNull())
// "I'm here!"

val absentOptional = Optional.empty<String>()

println(absentOptional.getOrNull())
// null
println(absentOptional.getOrDefault("Nobody here!"))
// "Nobody here!"
println(absentOptional.getOrElse {
println("Optional was absent!")
"Default value!"
})
// "Optional was absent!"
// "Default value!"

The toList(), toSet(), and asSequence() extension functions convert the value of a present Optional to a list, set, or sequence, or return an
empty collection otherwise. The toCollection() extension function appends the Optional value to an already existing destination collection:

val presentOptional = Optional.of("I'm here!")


val absentOptional = Optional.empty<String>()
println(presentOptional.toList() + "," + absentOptional.toList())
// ["I'm here!"], []
println(presentOptional.toSet() + "," + absentOptional.toSet())
// ["I'm here!"], []
val myCollection = mutableListOf<String>()

101
absentOptional.toCollection(myCollection)
println(myCollection)
// []
presentOptional.toCollection(myCollection)
println(myCollection)
// ["I'm here!"]
val list = listOf(presentOptional, absentOptional).flatMap { it.asSequence() }
println(list)
// ["I'm here!"]

These extension functions are being introduced as Experimental in Kotlin 1.7.0. You can learn more about Optional extensions in this
KEEP. As always, we welcome your feedback in the Kotlin issue tracker.

Support
for
named
capturing
groups
in
JS
and
Native
Starting with Kotlin 1.7.0, named capturing groups are supported not only on the JVM, but on the JS and Native platforms as well.

To give a name to a capturing group, use the (?<name>group) syntax in your regular expression. To get the text matched by a group, call
the newly introduced MatchGroupCollection.get() function and pass the group name.

Retrieve matched group value by name


Consider this example for matching city coordinates. To get a collection of groups matched by the regular expression, use groups.
Compare retrieving a group's contents by its number (index) and by its name using value:

fun main() {
val regex = "\\b(?<city>[A-Za-z\\s]+),\\s(?<state>[A-Z]{2}):\\s(?<areaCode>[0-9]{3})\\b".toRegex()
val input = "Coordinates: Austin, TX: 123"
val match = regex.find(input)!!
println(match.groups["city"]?.value) // "Austin" — by name
println(match.groups[2]?.value) // "TX" — by number
}

Named backreferencing
You can now also use group names when backreferencing groups. Backreferences match the same text that was previously matched by a
capturing group. For this, use the \k<name> syntax in your regular expression:

fun backRef() {
val regex = "(?<title>\\w+), yes \\k<title>".toRegex()
val match = regex.find("Do you copy? Sir, yes Sir!")!!
println(match.value) // "Sir, yes Sir"
println(match.groups["title"]?.value) // "Sir"
}

Named groups in replacement expressions


Named group references can be used with replacement expressions. Consider the replace() function that substitutes all occurrences of the
specified regular expression in the input with a replacement expression, and the replaceFirst() function that swaps the first match only.

Occurrences of ${name} in the replacement string are substituted with the subsequences corresponding to the captured groups with the
specified name. You can compare replacements in group references by name and index:

fun dateReplace() {
val dateRegex = Regex("(?<dd>\\d{2})-(?<mm>\\d{2})-(?<yyyy>\\d{4})")
val input = "Date of birth: 27-04-2022"
println(dateRegex.replace(input, "\${yyyy}-\${mm}-\${dd}")) // "Date of birth: 2022-04-27" — by name
println(dateRegex.replace(input, "\$3-\$2-\$1")) // "Date of birth: 2022-04-27" — by number

102
}

Gradle
This release introduces new build reports, support for Gradle plugin variants, new statistics in kapt, and a lot more:

A new approach to incremental compilation

New build reports for tracking compiler performance

Changes to the minimum supported versions of Gradle and the Android Gradle plugin

Support for Gradle plugin variants

Updates in the Kotlin Gradle plugin API

Availability of the sam-with-receiver plugin via the plugins API

Changes in compile tasks

New statistics of generated files by each annotation processor in kapt

Deprecation of the kotlin.compiler.execution.strategy system property

Removal of deprecated options, methods, and plugins

A
new
approach
to
incremental
compilation

The new approach to incremental compilation is Experimental. It may be dropped or changed at any time. Opt-in is required
(see the details below). We encourage you to use it only for evaluation purposes, and we would appreciate your feedback in
YouTrack.

In Kotlin 1.7.0, we've reworked incremental compilation for cross-module changes. Now incremental compilation is also supported for
changes made inside dependent non-Kotlin modules, and it is compatible with the Gradle build cache. Support for compilation avoidance
has also been improved.

We expect you'll see the most significant benefit of the new approach if you use the build cache or frequently make changes in non-Kotlin
Gradle modules. Our tests for the Kotlin project on the kotlin-gradle-plugin module show an improvement of greater than 80% for the
changes after the cache hit.

To try this new approach, set the following option in your gradle.properties:

kotlin.incremental.useClasspathSnapshot=true

The new approach to incremental compilation is currently available for the JVM backend in the Gradle build system only.

Learn how the new approach to incremental compilation is implemented under the hood in this blog post.

Our plan is to stabilize this technology and add support for other backends (JS, for instance) and build systems. We'd appreciate your
reports in YouTrack about any issues or strange behavior you encounter in this compilation scheme. Thank you!

103
The Kotlin team is very grateful to Ivan Gavrilovic, Hung Nguyen, Cédric Champeau, and other external contributors for their help.

Build
reports
for
Kotlin
compiler
tasks

Kotlin build reports are Experimental. They may be dropped or changed at any time. Opt-in is required (see details below). Use
them only for evaluation purposes. We appreciate your feedback on them in YouTrack.

Kotlin 1.7.0 introduces build reports that help track compiler performance. Reports contain the durations of different compilation phases
and reasons why compilation couldn't be incremental.

Build reports come in handy when you want to investigate issues with compiler tasks, for example:

When the Gradle build takes too much time and you want to understand the root cause of the poor performance.

When the compilation time for the same project differs, sometimes taking seconds, sometimes taking minutes.

To enable build reports, declare where to save the build report output in gradle.properties:

kotlin.build.report.output=file

The following values (and their combinations) are available:

file saves build reports in a local file.

build_scan saves build reports in the custom values section of the build scan.

The Gradle Enterprise plugin limits the number of custom values and their length. In big projects, some values could be lost.

http posts build reports using HTTP(S). The POST method sends metrics in the JSON format. Data may change from version to version.
You can see the current version of the sent data in the Kotlin repository.

There are two common cases that analyzing build reports for long-running compilations can help you resolve:

The build wasn't incremental. Analyze the reasons and fix underlying problems.

The build was incremental, but took too much time. Try to reorganize source files — split big files, save separate classes in different
files, refactor large classes, declare top-level functions in different files, and so on.

Learn more about new build reports in this blog post.

You are welcome to try using build reports in your infrastructure. If you have any feedback, encounter any issues, or want to suggest
improvements, please don't hesitate to report them in our issue tracker. Thank you!

Bumping
minimum
supported
versions
Starting with Kotlin 1.7.0, the minimum supported Gradle version is 6.7.1. We had to raise the version to support Gradle plugin variants
and the new Gradle API. In the future, we should not have to raise the minimum supported version as often, thanks to the Gradle plugin
variants feature.

Also, the minimal supported Android Gradle plugin version is now 3.6.4.

104
Support
for
Gradle
plugin
variants
Gradle 7.0 introduced a new feature for Gradle plugin authors — plugins with variants. This feature makes it easier to add support for new
Gradle features while maintaining compatibility for Gradle versions below 7.1. Learn more about variant selection in Gradle.

With Gradle plugin variants, we can ship different Kotlin Gradle plugin variants for different Gradle versions. The goal is to support the base
Kotlin compilation in the main variant, which corresponds to the oldest supported versions of Gradle. Each variant will have
implementations for Gradle features from a corresponding release. The latest variant will support the widest Gradle feature set. With this
approach, we can extend support for older Gradle versions with limited functionality.

Currently, there are only two variants of the Kotlin Gradle plugin:

main for Gradle versions 6.7.1–6.9.2

gradle70 for Gradle versions 7.0 and higher

In future Kotlin releases, we may add more.

To check which variant your build uses, enable the --info log level and find a string in the output starting with Using Kotlin Gradle plugin,
for example, Using Kotlin Gradle plugin main variant.

Here are workarounds for some known issues with variant selection in Gradle:

ResolutionStrategy in pluginManagement is not working for plugins with multivariants

Plugin variants are ignored when a plugin is added as the buildSrc common dependency

Leave your feedback on this YouTrack ticket.

Updates
in
the
Kotlin
Gradle
plugin
API
The Kotlin Gradle plugin API artifact has received several improvements:

There are new interfaces for Kotlin/JVM and Kotlin/kapt tasks with user-configurable inputs.

There is a new KotlinBasePlugin interface that all Kotlin plugins inherit from. Use this interface when you want to trigger some
configuration action whenever any Kotlin Gradle plugin (JVM, JS, Multiplatform, Native, and other platforms) is applied:

project.plugins.withType<org.jetbrains.kotlin.gradle.plugin.KotlinBasePlugin>() {
// Configure your action here
}

You can leave your feedback about the KotlinBasePlugin in this YouTrack ticket.

We've laid the groundwork for the Android Gradle plugin to configure Kotlin compilation within itself, meaning you won't need to add
the Kotlin Android Gradle plugin to your build. Follow Android Gradle Plugin release announcements to learn about the added support
and try it out!

The
sam-with-receiver
plugin
is
available
via
the
plugins
API
The sam-with-receiver compiler plugin is now available via the Gradle plugins DSL:

plugins {
id("org.jetbrains.kotlin.plugin.sam.with.receiver") version "$kotlin_version"
}

105
Changes
in
compile
tasks
Compile tasks have received lots of changes in this release:

Kotlin compile tasks no longer inherit the Gradle AbstractCompile task. They inherit only the DefaultTask.

The AbstractCompile task has the sourceCompatibility and targetCompatibility inputs. Since the AbstractCompile task is no longer
inherited, these inputs are no longer available in Kotlin users' scripts.

The SourceTask.stableSources input is no longer available, and you should use the sources input. setSource(...) methods that are still
available.

All compile tasks now use the libraries input for a list of libraries required for compilation. The KotlinCompile task still has the
deprecated Kotlin property classpath, which will be removed in future releases.

Compile tasks still implement the PatternFilterable interface, which allows the filtering of Kotlin sources. The sourceFilesExtensions
input was removed in favor of using PatternFilterable methods.

The deprecated Gradle destinationDir: File output was replaced with the destinationDirectory: DirectoryProperty output.

The Kotlin/Native AbstractNativeCompile task now inherits the AbstractKotlinCompileTool base class. This is an initial step toward
integrating Kotlin/Native build tools into all the other tools.

Please leave your feedback in this YouTrack ticket.

Statistics
of
generated
files
by
each
annotation
processor
in
kapt
The kotlin-kapt Gradle plugin already reports performance statistics for each processor. Starting with Kotlin 1.7.0, it can also report
statistics on the number of generated files for each annotation processor.

This is useful to track if there are unused annotation processors as a part of the build. You can use the generated report to find modules
that trigger unnecessary annotation processors and update the modules to prevent that.

Enable the statistics in two steps:

Set the showProcessorStats flag to true in your build.gradle.kts:

kapt {
showProcessorStats = true
}

Set the kapt.verbose Gradle property to true in your gradle.properties:

kapt.verbose=true

You can also enable verbose output via the command line option verbose.

The statistics will appear in the logs with the info level. You'll see the Annotation processor stats: line followed by statistics on the
execution time of each annotation processor. After these lines, there will be the Generated files report: line followed by statistics on the
number of generated files for each annotation processor. For example:

106
[INFO] Annotation processor stats:
[INFO] org.mapstruct.ap.MappingProcessor: total: 290 ms, init: 1 ms, 3 round(s): 289 ms, 0 ms, 0 ms
[INFO] Generated files report:
[INFO] org.mapstruct.ap.MappingProcessor: total sources: 2, sources per round: 2, 0, 0

Please leave your feedback in this YouTrack ticket.

Deprecation
of
the
kotlin.compiler.execution.strategy
system
property
Kotlin 1.6.20 introduced new properties for defining a Kotlin compiler execution strategy. In Kotlin 1.7.0, a deprecation cycle has started
for the old system property kotlin.compiler.execution.strategy in favor of the new properties.

When using the kotlin.compiler.execution.strategy system property, you'll receive a warning. This property will be deleted in future
releases. To preserve the old behavior, replace the system property with the Gradle property of the same name. You can do this in
gradle.properties, for example:

kotlin.compiler.execution.strategy=out-of-process

You can also use the compile task property compilerExecutionStrategy. Learn more about this on the Gradle page.

Removal
of
deprecated
options,
methods,
and
plugins

Removal of the useExperimentalAnnotation method


In Kotlin 1.7.0, we completed the deprecation cycle for the useExperimentalAnnotation Gradle method. Use optIn() instead to opt in to
using an API in a module.

For example, if your Gradle module is multiplatform:

sourceSets {
all {
languageSettings.optIn("org.mylibrary.OptInAnnotation")
}
}

Learn more about opt-in requirements in Kotlin.

Removal of deprecated compiler options


We've completed the deprecation cycle for several compiler options:

The kotlinOptions.jdkHome compiler option was deprecated in 1.5.30 and has been removed in the current release. Gradle builds now
fail if they contain this option. We encourage you to use Java toolchains, which have been supported since Kotlin 1.5.30.

The deprecated 'noStdlib' compiler option has also been removed. The Gradle plugin uses the kotlin.stdlib.default.dependency=true
property to control whether the Kotlin standard library is present.

The compiler arguments -jdkHome and -no-stdlib are still available.

Removal of deprecated plugins


In Kotlin 1.4.0, the kotlin2js and kotlin-dce-plugin plugins were deprecated, and they have been removed in this release. Instead of
kotlin2js, use the new org.jetbrains.kotlin.js plugin. Dead code elimination (DCE) works when the Kotlin/JS Gradle plugin is properly

107
configured.

In Kotlin 1.6.0, we changed the deprecation level of the KotlinGradleSubplugin class to 'ERROR'. Developers used this class for writing
compiler plugins. In this release, this class has been removed. Use the KotlinCompilerPluginSupportPlugin class instead.

The best practice is to use Kotlin plugins with versions 1.7.0 and higher throughout your project.

Removal of the deprecated coroutines DSL option and property


We removed the deprecated kotlin.experimental.coroutines Gradle DSL option and the kotlin.coroutines property used in
gradle.properties. Now you can just use suspending functions or add the kotlinx.coroutines dependency to your build script.

Learn more about coroutines in the Coroutines guide.

Removal of the type cast in the toolchain extension method


Before Kotlin 1.7.0, you had to do the type cast into the JavaToolchainSpec class when configuring the Gradle toolchain with Kotlin DSL:

kotlin {
jvmToolchain {
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)
}
}

Now, you can omit the (this as JavaToolchainSpec) part:

kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)
}
}

Migrating
to
Kotlin
1.7.0

Install
Kotlin
1.7.0
IntelliJ IDEA 2022.1 and Android Studio Chipmunk (212) automatically suggest updating the Kotlin plugin to 1.7.0.

For IntelliJ IDEA 2022.2, and Android Studio Dolphin (213) or Android Studio Electric Eel (221), the Kotlin plugin 1.7.0 will be
delivered with upcoming IntelliJ IDEA and Android Studios updates.

The new command-line compiler is available for download on the GitHub release page.

Migrate
existing
or
start
a
new
project
with
Kotlin
1.7.0
To migrate existing projects to Kotlin 1.7.0, change the Kotlin version to 1.7.0 and reimport your Gradle or Maven project. Learn how to
update to Kotlin 1.7.0.

To start a new project with Kotlin 1.7.0, update the Kotlin plugin and run the Project Wizard from File | New | Project.

108
Compatibility
guide
for
Kotlin
1.7.0
Kotlin 1.7.0 is a feature release and can, therefore, bring changes that are incompatible with your code written for earlier versions of the
language. Find the detailed list of such changes in the Compatibility guide for Kotlin 1.7.0.

What's
new
in
Kotlin
1.6.20
Release date: 4 April 2022

Kotlin 1.6.20 reveals previews of the future language features, makes the hierarchical structure the default for multiplatform projects, and
brings evolutionary improvements to other components.

You can also find a short overview of the changes in this video:

Gif

Watch video online.

Language
In Kotlin 1.6.20, you can try two new language features:

Prototype of context receivers for Kotlin/JVM

Definitely non-nullable types

Prototype
of
context
receivers
for
Kotlin/JVM

The feature is a prototype available only for Kotlin/JVM. With -Xcontext-receivers enabled, the compiler will produce pre-release
binaries that cannot be used in production code. Use context receivers only in your toy projects. We appreciate your feedback in
YouTrack.

With Kotlin 1.6.20, you are no longer limited to having one receiver. If you need more, you can make functions, properties, and classes
context-dependent (or contextual) by adding context receivers to their declaration. A contextual declaration does the following:

109
It requires all declared context receivers to be present in a caller's scope as implicit receivers.

It brings declared context receivers into its body scope as implicit receivers.

interface LoggingContext {
val log: Logger // This context provides a reference to a logger
}

context(LoggingContext)
fun startBusinessOperation() {
// You can access the log property since LoggingContext is an implicit receiver
log.info("Operation has started")
}

fun test(loggingContext: LoggingContext) {


with(loggingContext) {
// You need to have LoggingContext in a scope as an implicit receiver
// to call startBusinessOperation()
startBusinessOperation()
}
}

To enable context receivers in your project, use the -Xcontext-receivers compiler option. You can find a detailed description of the feature
and its syntax in the KEEP.

Please note that the implementation is a prototype:

With -Xcontext-receivers enabled, the compiler will produce pre-release binaries that cannot be used in production code

The IDE support for context receivers is minimal for now

Try the feature in your toy projects and share your thoughts and experience with us in this YouTrack issue. If you run into any problems,
please file a new issue.

Definitely
non-nullable
types

Definitely non-nullable types are in Beta. They are almost stable, but migration steps may be required in the future. We'll do our
best to minimize any changes you have to make.

To provide better interoperability when extending generic Java classes and interfaces, Kotlin 1.6.20 allows you to mark a generic type
parameter as definitely non-nullable on the use site with the new syntax T & Any. The syntactic form comes from a notation of intersection
types and is now limited to a type parameter with nullable upper bounds on the left side of & and non-nullable Any on the right side:

fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y

fun main() {
// OK
elvisLike<String>("", "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String>("", null).length

// OK
elvisLike<String?>(null, "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String?>(null, null).length
}

110
Set the language version to 1.7 to enable the feature:

Kotlin

kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.7"
}
}
}

Groovy

kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.7'
}
}
}

Learn more about definitely non-nullable types in the KEEP.

Kotlin/JVM
Kotlin 1.6.20 introduces:

Compatibility improvements of default methods in JVM interfaces: new @JvmDefaultWithCompatibility annotation for interfaces and
compatibility changes in the -Xjvm-default modes

Support for parallel compilation of a single module in the JVM backend

Support for callable references to functional interface constructors

New
@JvmDefaultWithCompatibility
annotation
for
interfaces
Kotlin 1.6.20 introduces the new annotation @JvmDefaultWithCompatibility: use it along with the -Xjvm-default=all compiler option to
create the default method in JVM interface for any non-abstract member in any Kotlin interface.

If there are clients that use your Kotlin interfaces compiled without the -Xjvm-default=all option, they may be binary-incompatible with the
code compiled with this option. Before Kotlin 1.6.20, to avoid this compatibility issue, the recommended approach was to use the -Xjvm-
default=all-compatibility mode and also the @JvmDefaultWithoutCompatibility annotation for interfaces that didn't need this type of
compatibility.

This approach had some disadvantages:

You could easily forget to add the annotation when a new interface was added.

Usually there are more interfaces in non-public parts than in the public API, so you end up having this annotation in many places in your
code.

Now, you can use the -Xjvm-default=all mode and mark interfaces with the @JvmDefaultWithCompatibility annotation. This allows you to
add this annotation to all interfaces in the public API once, and you won't need to use any annotations for new non-public code.

111
Leave your feedback about this new annotation in this YouTrack ticket.

Compatibility
changes
in
the
-Xjvm-default
modes
Kotlin 1.6.20 adds the option to compile modules in the default mode (the -Xjvm-default=disable compiler option) against modules
compiled with the -Xjvm-default=all or -Xjvm-default=all-compatibility modes. As before, compilations will also be successful if all modules
have the -Xjvm-default=all or -Xjvm-default=all-compatibility modes. You can leave your feedback in this YouTrack issue.

Kotlin 1.6.20 deprecates the compatibility and enable modes of the compiler option -Xjvm-default. There are changes in other modes'
descriptions regarding the compatibility, but the overall logic remains the same. You can check out the updated descriptions.

For more information about default methods in the Java interop, see the interoperability documentation and this blog post.

Support
for
parallel
compilation
of
a
single
module
in
the
JVM
backend

Support for parallel compilation of a single module in the JVM backend is Experimental. It may be dropped or changed at any
time. Opt-in is required (see details below), and you should use it only for evaluation purposes. We would appreciate your
feedback on it in YouTrack.

We are continuing our work to improve the new JVM IR backend compilation time. In Kotlin 1.6.20, we added the experimental JVM IR
backend mode to compile all the files in a module in parallel. Parallel compilation can reduce the total compilation time by up to 15%.

Enable the experimental parallel backend mode with the compiler option -Xbackend-threads. Use the following arguments for this option:

N is the number of threads you want to use. It should not be greater than your number of CPU cores; otherwise, parallelization stops
being effective because of switching context between threads

0 to use a separate thread for each CPU core

Gradle can run tasks in parallel, but this type of parallelization doesn't help a lot when a project (or a major part of a project) is just one big
task from Gradle's perspective. If you have a very big monolithic module, use parallel compilation to compile more quickly. If your project
consists of lots of small modules and has a build parallelized by Gradle, adding another layer of parallelization may hurt performance
because of context switching.

Parallel compilation has some constraints:

It doesn't work with kapt because kapt disables the IR backend

It requires more JVM heap by design. The amount of heap is proportional to the number of threads

Support
for
callable
references
to
functional
interface
constructors

Support for callable references to functional interface constructors is Experimental. It may be dropped or changed at any time.
Opt-in is required (see details below), and you should use it only for evaluation purposes. We would appreciate your feedback
on it in YouTrack.

Support for callable references to functional interface constructors adds a source-compatible way to migrate from an interface with a

112
constructor function to a functional interface.

Consider the following code:

interface Printer {
fun print()
}

fun Printer(block: () -> Unit): Printer = object : Printer { override fun print() = block() }

With callable references to functional interface constructors enabled, this code can be replaced with just a functional interface declaration:

fun interface Printer {


fun print()
}

Its constructor will be created implicitly, and any code using the ::Printer function reference will compile. For example:

documentsStorage.addPrinter(::Printer)

Preserve the binary compatibility by marking the legacy function Printer with the @Deprecated annotation with DeprecationLevel.HIDDEN:

@Deprecated(message = "Your message about the deprecation", level = DeprecationLevel.HIDDEN)


fun Printer(...) {...}

Use the compiler option -XXLanguage:+KotlinFunInterfaceConstructorReference to enable this feature.

Kotlin/Native
Kotlin/Native 1.6.20 marks continued development of its new components. We've taken another step toward consistent experience with
Kotlin on other platforms:

An update on the new memory manager

Concurrent implementation for the sweep phase in new memory manager

Instantiation of annotation classes

Interop with Swift async/await: returning Swift's Void instead of KotlinUnit

Better stack traces with libbacktrace

Support for standalone Android executables

Performance improvements

Improved error handling during cinterop modules import

Support for Xcode 13 libraries

An
update
on
the
new
memory
manager

113
The new Kotlin/Native memory manager is in Alpha. It may change incompatibly and require manual migration in the future. We
would appreciate your feedback on it in YouTrack.

With Kotlin 1.6.20, you can try the Alpha version of the new Kotlin/Native memory manager. It eliminates the differences between the JVM
and Native platforms to provide a consistent developer experience in multiplatform projects. For example, you'll have a much easier time
creating new cross-platform mobile applications that work on both Android and iOS.

The new Kotlin/Native memory manager lifts restrictions on object-sharing between threads. It also provides leak-free concurrent
programming primitives that are safe and don't require any special management or annotations.

The new memory manager will become the default in future versions, so we encourage you to try it now. Check out our blog post to learn
more about the new memory manager and explore demo projects, or jump right to the migration instructions to try it yourself.

Try using the new memory manager on your projects to see how it works and share feedback in our issue tracker, YouTrack.

Concurrent
implementation
for
the
sweep
phase
in
new
memory
manager
If you have already switched to our new memory manager, which was announced in Kotlin 1.6, you might notice a huge execution time
improvement: our benchmarks show 35% improvement on average. Starting with 1.6.20, there is also a concurrent implementation for the
sweep phase available for the new memory manager. This should also improve the performance and decrease the duration of garbage
collector pauses.

To enable the feature for the new Kotlin/Native memory manager, pass the following compiler option:

-Xgc=cms

Feel free to share your feedback on the new memory manager performance in this YouTrack issue.

Instantiation
of
annotation
classes
In Kotlin 1.6.0, instantiation of annotation classes became Stable for Kotlin/JVM and Kotlin/JS. The 1.6.20 version delivers support for
Kotlin/Native.

Learn more about instantiation of annotation classes.

Interop
with
Swift
async/await:
returning
Void
instead
of
KotlinUnit

Concurrency interoperability with Swift async/await is Experimental. It may be dropped or changed at any time. You should use
it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

We've continued working on the experimental interop with Swift's async/await (available since Swift 5.5). Kotlin 1.6.20 differs from
previous versions in the way it works with suspend functions with the Unit return type.

Previously, such functions were presented in Swift as async functions returning KotlinUnit. However, the proper return type for them is
Void, similar to non-suspending functions.

To avoid breaking the existing code, we're introducing a Gradle property that makes the compiler translate Unit-returning suspend
functions to async Swift with the Void return type:

# gradle.properties

114
kotlin.native.binary.unitSuspendFunctionObjCExport=proper

We plan to make this behavior the default in future Kotlin releases.

Better
stack
traces
with
libbacktrace

Using libbacktrace for resolving source locations is Experimental. It may be dropped or changed at any time. You should use it
only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

Kotlin/Native is now able to produce detailed stack traces with file locations and line numbers for better debugging of linux* (except
linuxMips32 and linuxMipsel32) and androidNative* targets.

This feature uses the libbacktrace library under the hood. Take a look at the following code to see an example of the difference:

fun main() = bar()


fun bar() = baz()
inline fun baz() {
error("")
}

Before 1.6.20:

Uncaught Kotlin exception: kotlin.IllegalStateException: at 0 example.kexe 0x227190 kfun:kotlin.Throwable#<init>


(kotlin.String?){} + 96 at 1 example.kexe 0x221e4c kfun:kotlin.Exception#<init>(kotlin.String?){} + 92 at 2 example.kexe
0x221f4c kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 92 at 3 example.kexe 0x22234c
kfun:kotlin.IllegalStateException#<init>(kotlin.String?){} + 92 at 4 example.kexe 0x25d708 kfun:#bar(){} + 104 at 5
example.kexe 0x25d68c kfun:#main(){} + 12
1.6.20 with libbacktrace:

Uncaught Kotlin exception: kotlin.IllegalStateException: at 0 example.kexe 0x229550 kfun:kotlin.Throwable#<init>


(kotlin.String?){} + 96 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Throwable.kt:24:37) at 1 example.kexe 0x22420c kfun:kotlin.Exception#<init>
(kotlin.String?){} + 92 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:44) at 2 example.kexe 0x22430c kfun:kotlin.RuntimeException#
<init>(kotlin.String?){} + 92 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:44) at 3 example.kexe 0x22470c
kfun:kotlin.IllegalStateException#<init>(kotlin.String?){} + 92 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:70:44) at 4 example.kexe 0x25fac8 kfun:#bar(){} + 104 [inlined]
(/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/libraries/stdlib/src/kotlin/util/Preconditions.kt:143:56) at 5
example.kexe 0x25fac8 kfun:#bar(){} + 104 [inlined] (/private/tmp/backtrace/src/commonMain/kotlin/app.kt:4:5) at 6
example.kexe 0x25fac8 kfun:#bar(){} + 104 (/private/tmp/backtrace/src/commonMain/kotlin/app.kt:2:13) at 7
example.kexe 0x25fa4c kfun:#main(){} + 12 (/private/tmp/backtrace/src/commonMain/kotlin/app.kt:1:14)
On Apple targets, which already had file locations and line numbers in stack traces, libbacktrace provides more details for inline function
calls:

Before 1.6.20:

Uncaught Kotlin exception: kotlin.IllegalStateException: at 0 example.kexe 0x10a85a8f8 kfun:kotlin.Throwable#<init>


(kotlin.String?){} + 88 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Throwable.kt:24:37) at 1 example.kexe 0x10a855846 kfun:kotlin.Exception#<init>
(kotlin.String?){} + 86 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:44) at 2 example.kexe 0x10a855936
kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 86 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:44) at 3 example.kexe 0x10a855c86
kfun:kotlin.IllegalStateException#<init>(kotlin.String?){} + 86 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:70:44) at 4 example.kexe 0x10a8489a5 kfun:#bar(){} + 117
(/private/tmp/backtrace/src/commonMain/kotlin/app.kt:2:1) at 5 example.kexe 0x10a84891c kfun:#main(){} + 12
(/private/tmp/backtrace/src/commonMain/kotlin/app.kt:1:14) ...
1.6.20 with libbacktrace:

Uncaught Kotlin exception: kotlin.IllegalStateException: at 0 example.kexe 0x10669bc88 kfun:kotlin.Throwable#<init>

115
(kotlin.String?){} + 88 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Throwable.kt:24:37) at 1 example.kexe 0x106696bd6 kfun:kotlin.Exception#<init>
(kotlin.String?){} + 86 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:44) at 2 example.kexe 0x106696cc6
kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 86 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:44) at 3 example.kexe 0x106697016
kfun:kotlin.IllegalStateException#<init>(kotlin.String?){} + 86 (/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/kotlin-
native/runtime/src/main/kotlin/kotlin/Exceptions.kt:70:44) at 4 example.kexe 0x106689d35 kfun:#bar(){} + 117 [inlined]
(/opt/buildAgent/work/c3a91df21e46e2c8/kotlin/libraries/stdlib/src/kotlin/util/Preconditions.kt:143:56) >> at 5
example.kexe 0x106689d35 kfun:#bar(){} + 117 [inlined] (/private/tmp/backtrace/src/commonMain/kotlin/app.kt:4:5) at
6 example.kexe 0x106689d35 kfun:#bar(){} + 117 (/private/tmp/backtrace/src/commonMain/kotlin/app.kt:2:13) at 7
example.kexe 0x106689cac kfun:#main(){} + 12 (/private/tmp/backtrace/src/commonMain/kotlin/app.kt:1:14) ...
To produce better stack traces with libbacktrace, add the following line to gradle.properties:

# gradle.properties
kotlin.native.binary.sourceInfoType=libbacktrace

Please tell us how debugging Kotlin/Native with libbacktrace works for you in this YouTrack issue.

Support
for
standalone
Android
executables
Previously, Android Native executables in Kotlin/Native were not actually executables but shared libraries that you could use as a
NativeActivity. Now there's an option to generate standard executables for Android Native targets.

For that, in the build.gradle(.kts) part of your project, configure the executable block of your androidNative target. Add the following binary
option:

kotlin {
androidNativeX64("android") {
binaries {
executable {
binaryOptions["androidProgramType"] = "standalone"
}
}
}
}

Note that this feature will become the default in Kotlin 1.7.0. If you want to preserve the current behavior, use the following setting:

binaryOptions["androidProgramType"] = "nativeActivity"

Thanks to Mattia Iavarone for the implementation!

Performance
improvements
We are working hard on Kotlin/Native to speed up the compilation process and improve your developing experience.

Kotlin 1.6.20 brings some performance updates and bug fixes that affect the LLVM IR that Kotlin generates. According to the benchmarks
on our internal projects, we achieved the following performance boosts on average:

15% reduction in execution time

20% reduction in the code size of both release and debug binaries

26% reduction in the compilation time of release binaries

These changes also provide a 10% reduction in compilation time for a debug binary on a large internal project.

To achieve this, we've implemented static initialization for some of the compiler-generated synthetic objects, improved the way we

116
structure LLVM IR for every function, and optimized the compiler caches.

Improved
error
handling
during
cinterop
modules
import
This release introduces improved error handling for cases where you import an Objective-C module using the cinterop tool (as is typical for
CocoaPods pods). Previously, if you got an error while trying to work with an Objective-C module (for instance, when dealing with a
compilation error in a header), you received an uninformative error message, such as fatal error: could not build module $name. We
expanded upon this part of the cinterop tool, so you'll get an error message with an extended description.

Support
for
Xcode
13
libraries
Libraries delivered with Xcode 13 have full support as of this release. Feel free to access them from anywhere in your Kotlin code.

Kotlin
Multiplatform
1.6.20 brings the following notable updates to Kotlin Multiplatform:

Hierarchical structure support is now default for all new multiplatform projects

Kotlin CocoaPods Gradle plugin received several useful features for CocoaPods integration

Hierarchical
structure
support
for
multiplatform
projects
Kotlin 1.6.20 comes with hierarchical structure support enabled by default. Since introducing it in Kotlin 1.4.0, we've significantly improved
the frontend and made IDE import stable.

Previously, there were two ways to add code in a multiplatform project. The first was to insert it in a platform-specific source set, which is
limited to one target and can't be reused by other platforms. The second is to use a common source set shared across all the platforms
that are currently supported by Kotlin.

Now you can share source code among several similar native targets that reuse a lot of the common logic and third-party APIs. The
technology will provide the correct default dependencies and find the exact API available in the shared code. This eliminates a complex
build setup and having to use workarounds to get IDE support for sharing source sets among native targets. It also helps prevent unsafe
API usages meant for a different target.

The technology will come in handy for library authors, too, as a hierarchical project structure allows them to publish and consume libraries
with common APIs for a subset of targets.

By default, libraries published with the hierarchical project structure are compatible only with hierarchical structure projects. Learn more
about project-library compatibility.

Better code-sharing in your project


Without hierarchical structure support, there is no straightforward way to share code across some but not all Kotlin targets. One popular
example is sharing code across all iOS targets and having access to iOS-specific dependencies, like Foundation.

Thanks to the hierarchical project structure support, you can now achieve this out of the box. In the new structure, source sets form a
hierarchy. You can use platform-specific language features and dependencies available for each target that a given source set compiles
to.

For example, consider a typical multiplatform project with two targets — iosArm64 and iosX64 for iOS devices and simulators. The Kotlin
tooling understands that both targets have the same function and allows you to access that function from the intermediate source set,
iosMain.

117
iOS hierarchy example

The Kotlin toolchain provides the correct default dependencies, like Kotlin/Native stdlib or native libraries. Moreover, Kotlin tooling will try
its best to find exactly the API surface area available in the shared code. This prevents such cases as, for example, the use of a macOS-
specific function in code shared for Windows.

More opportunities for library authors


When a multiplatform library is published, the API of its intermediate source sets is now properly published alongside it, making it available
for consumers. Again, the Kotlin toolchain will automatically figure out the API available in the consumer source set while carefully
watching out for unsafe usages, like using an API meant for the JVM in JS code. Learn more about sharing code in libraries.

Configuration and setup


Starting with Kotlin 1.6.20, all your new multiplatform projects will have a hierarchical project structure. No additional setup is required.

If you've already turned it on manually, you can remove the deprecated options from gradle.properties:

# gradle.properties
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false // or 'true', depending on your previous setup

For Kotlin 1.6.20, we recommend using Android Studio 2021.1.1 (Bumblebee) or later to get the best experience.

You can also opt-out. To disable hierarchical structure support, set the following options ingradle.properties:

# gradle.properties
kotlin.mpp.hierarchicalStructureSupport=false

Leave your feedback


This is a significant change to the whole ecosystem. We would appreciate your feedback to help make it even better.

Try it now and report any difficulties you encounter to our issue tracker.

118
Kotlin
CocoaPods
Gradle
plugin
To simplify CocoaPods integration, Kotlin 1.6.20 delivers the following features:

The CocoaPods plugin now has tasks that build XCFrameworks with all registered targets and generate the Podspec file. This can be
useful when you don't want to integrate with Xcode directly, but you want to build artifacts and deploy them to your local CocoaPods
repository.

Learn more about building XCFrameworks.

If you use CocoaPods integration in your projects, you're used to specifying the required Pod version for the entire Gradle project. Now
you have more options:

Specify the Pod version directly in the cocoapods block

Continue using a Gradle project version

If none of these properties is configured, you'll get an error.

You can now configure the CocoaPod name in the cocoapods block instead of changing the name of the whole Gradle project.

The CocoaPods plugin introduces a new extraSpecAttributes property, which you can use to configure properties in a Podspec file that
were previously hard-coded, like libraries or vendored_frameworks.

kotlin {
cocoapods {
version = "1.0"
name = "MyCocoaPod"
extraSpecAttributes["social_media_url"] = 'https://twitter.com/kotlin'
extraSpecAttributes["vendored_frameworks"] = 'CustomFramework.xcframework'
extraSpecAttributes["libraries"] = 'xml'
}
}

See the full Kotlin CocoaPods Gradle plugin DSL reference.

Kotlin/JS
Kotlin/JS improvements in 1.6.20 mainly affect the IR compiler:

Incremental compilation for development binaries (IR)

Lazy initialization of top-level properties by default (IR)

Separate JS files for project modules by default (IR)

Char class optimization (IR)

Export improvements (both IR and legacy backends)

@AfterTest guarantees for asynchronous tests

Incremental
compilation
for
development
binaries
with
IR
compiler
To make Kotlin/JS development with the IR compiler more efficient, we're introducing a new incremental compilation mode.

When building development binaries with the compileDevelopmentExecutableKotlinJs Gradle task in this mode, the compiler caches the
results of previous compilations on the module level. It uses the cached compilation results for unchanged source files during subsequent
compilations, making them complete more quickly, especially with small changes. Note that this improvement exclusively targets the

119
development process (shortening the edit-build-debug cycle) and doesn't affect the building of production artifacts.

To enable incremental compilation for development binaries, add the following line to the project's gradle.properties:

# gradle.properties
kotlin.incremental.js.ir=true // false by default

In our test projects, the new mode made incremental compilation up to 30% faster. However, the clean build in this mode became slower
because of the need to create and populate the caches.

Please tell us what you think of using incremental compilation with your Kotlin/JS projects in this YouTrack issue.

Lazy
initialization
of
top-level
properties
by
default
with
IR
compiler
In Kotlin 1.4.30, we presented a prototype of lazy initialization of top-level properties in the JS IR compiler. By eliminating the need to
initialize all properties when the application launches, lazy initialization reduces the startup time. Our measurements showed about a 10%
speed-up on a real-life Kotlin/JS application.

Now, having polished and properly tested this mechanism, we're making lazy initialization the default for top-level properties in the IR
compiler.

// lazy initialization
val a = run {
val result = // intensive computations
println(result)
result
} // run is executed upon the first usage of the variable

If for some reason you need to initialize a property eagerly (upon the application start), mark it with the @EagerInitialization annotation.

Separate
JS
files
for
project
modules
by
default
with
IR
compiler
Previously, the JS IR compiler offered an ability to generate separate .js files for project modules. This was an alternative to the default
option – a single .js file for the whole project. This file might be too large and inconvenient to use, because whenever you want to use a
function from your project, you have to include the entire JS file as a dependency. Having multiple files adds flexibility and decreases the
size of such dependencies. This feature was available with the -Xir-per-module compiler option.

Starting from 1.6.20, the JS IR compiler generates separate .js files for project modules by default.

Compiling the project into a single .js file is now available with the following Gradle property:

# gradle.properties
kotlin.js.ir.output.granularity=whole-program // `per-module` is the default

In previous releases, the experimental per-module mode (available via the -Xir-per-module=true flag) invoked main() functions in each
module. This is inconsistent with the regular 'single .js' mode. Starting with 1.6.20, the main() function will be invoked in the main module
only in both cases. If you do need to run some code when a module is loaded, you can use top-local properties annotated with the
@EagerInitialization annotation. See Lazy initialization of top-level properties by default (IR).

Char
class
optimization
The Char class is now handled by the Kotlin/JS compiler without introducing boxing (similar to inline classes). This speeds up operations
on chars in Kotlin/JS code.

120
Aside from the performance improvement, this changes the way Char is exported to JavaScript: it's now translated to Number.

Improvements
to
export
and
TypeScript
declaration
generation
Kotlin 1.6.20 is bringing multiple fixes and improvements to the export mechanism (the @JsExport annotation), including the generation of
TypeScript declarations (.d.ts). We've added the ability to export interfaces and enums, and we've fixed the export behavior in some
corner cases that were reported to us previously. For more details, see the list of export improvements in YouTrack.

Learn more about using Kotlin code from JavaScript.

@AfterTest
guarantees
for
asynchronous
tests
Kotlin 1.6.20 makes @AfterTest functions work properly with asynchronous tests on Kotlin/JS. If a test function's return type is statically
resolved to Promise, the compiler now schedules the execution of the @AfterTest function to the corresponding then() callback.

Security
Kotlin 1.6.20 introduces a couple of features to improve the security of your code:

Using relative paths in klibs

Persisting yarn.lock for Kotlin/JS Gradle projects

Installation of npm dependencies with --ignore-scripts by default

Using
relative
paths
in
klibs
A library in klib format contains a serialized IR representation of source files, which also includes their paths for generating proper debug
information. Before Kotlin 1.6.20, stored file paths were absolute. Since the library author may not want to share absolute paths, the 1.6.20
version comes with an alternative option.

If you are publishing a klib and want to use only relative paths of source files in the artifact, you can now pass the -Xklib-relative-path-base
compiler option with one or multiple base paths of source files:

Kotlin

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class).configureEach {
// $base is a base path of source files
kotlinOptions.freeCompilerArgs += "-Xklib-relative-path-base=$base"
}

Groovy

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
// $base is a base path of source files
freeCompilerArgs += "-Xklib-relative-path-base=$base"
}
}

Persisting
yarn.lock
for
Kotlin/JS
Gradle
projects

121
The feature was backported to Kotlin 1.6.10.

The Kotlin/JS Gradle plugin now provides an ability to persist the yarn.lock file, making it possible to lock the versions of the npm
dependencies for your project without additional Gradle configuration. The feature brings changes to the default project structure by
adding the auto-generated kotlin-js-store directory to the project root. It holds the yarn.lock file inside.

We strongly recommend committing the kotlin-js-store directory and its contents to your version control system. Committing lockfiles to
your version control system is a recommended practice because it ensures your application is being built with the exact same dependency
tree on all machines, regardless of whether those are development environments on other machines or CI/CD services. Lockfiles also
prevent your npm dependencies from being silently updated when a project is checked out on a new machine, which is a security
concern.

Tools like Dependabot can also parse the yarn.lock files of your Kotlin/JS projects, and provide you with warnings if any npm package you
depend on is compromised.

If needed, you can change both directory and lockfile names in the build script:

Kotlin

rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().lockFileDirectory =
project.rootDir.resolve("my-kotlin-js-store")
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().lockFileName = "my-
yarn.lock"
}

Groovy

rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin) {

rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).lockFileDirectory
=
file("my-kotlin-js-store")

rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).lockFileName =
'my-yarn.lock'
}

Changing the name of the lockfile may cause dependency inspection tools to no longer pick up the file.

Installation
of
npm
dependencies
with
--ignore-scripts
by
default

The feature was backported to Kotlin 1.6.10.

The Kotlin/JS Gradle plugin now prevents the execution of lifecycle scripts during the installation of npm dependencies by default. The
change is aimed at reducing the likelihood of executing malicious code from compromised npm packages.

To roll back to the old configuration, you can explicitly enable lifecycle scripts execution by adding the following lines to build.gradle(.kts):

122
Kotlin

rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().ignoreScripts = false
}

Groovy

rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin) {

rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).ignoreScripts =
false
}

Learn more about npm dependencies of a Kotlin/JS Gradle project.

Gradle
Kotlin 1.6.20 brings the following changes for the Kotlin Gradle Plugin:

New properties kotlin.compiler.execution.strategy and compilerExecutionStrategy for defining a Kotlin compiler execution strategy

Deprecation of the options kapt.use.worker.api, kotlin.experimental.coroutines, and kotlin.coroutines

Removal of the kotlin.parallel.tasks.in.project build option

Properties
for
defining
Kotlin
compiler
execution
strategy
Before Kotlin 1.6.20, you used the system property -Dkotlin.compiler.execution.strategy to define a Kotlin compiler execution strategy.
This property might have been inconvenient in some cases. Kotlin 1.6.20 introduces a Gradle property with the same name,
kotlin.compiler.execution.strategy, and the compile task property compilerExecutionStrategy.

The system property still works, but it will be removed in future releases.

The current priority of properties is the following:

The task property compilerExecutionStrategy takes priority over the system property and the Gradle property
kotlin.compiler.execution.strategy.

The Gradle property takes priority over the system property.

There are three compiler execution strategies that you can assign to these properties:

Strategy Where Kotlin compiler is Incremental Other characteristics


executed compilation

Daemon Inside its own daemon process Yes The default strategy. Can be shared between different Gradle
daemons

123
Strategy Where Kotlin compiler is Incremental Other characteristics
executed compilation

In process Inside the Gradle daemon No May share the heap with the Gradle daemon
process

Out of In a separate process for each No —


process call

Accordingly, the available values for kotlin.compiler.execution.strategy properties (both system and Gradle's) are:

1. daemon (default)

2. in-process

3. out-of-process

Use the Gradle property kotlin.compiler.execution.strategy in gradle.properties:

# gradle.properties
kotlin.compiler.execution.strategy=out-of-process

The available values for the compilerExecutionStrategy task property are:

1. org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.DAEMON (default)

2. org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.IN_PROCESS

3. org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy.OUT_OF_PROCESS

Use the task property compilerExecutionStrategy in the build.gradle.kts buildscript:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilerExecutionStrategy

// …

tasks.withType<KotlinCompile>().configureEach {
compilerExecutionStrategy.set(KotlinCompilerExecutionStrategy.IN_PROCESS)
}

Please leave your feedback in this YouTrack task.

Deprecation
of
build
options
for
kapt
and
coroutines
In Kotlin 1.6.20, we changed deprecation levels of the properties:

We deprecated the ability to run kapt via the Kotlin daemon with kapt.use.worker.api – now it produces a warning to Gradle's output.
By default, kapt has been using Gradle workers since the 1.3.70 release, and we recommend sticking to this method.

We are going to remove the option kapt.use.worker.api in future releases.

We deprecated the kotlin.experimental.coroutines Gradle DSL option and the kotlin.coroutines property used in gradle.properties. Just

124
use suspending functions or add the kotlinx.coroutines dependency to your build.gradle(.kts) file.

Learn more about coroutines in the Coroutines guide.

Removal
of
the
kotlin.parallel.tasks.in.project
build
option
In Kotlin 1.5.20, we announced the deprecation of the build option kotlin.parallel.tasks.in.project. This option has been removed in Kotlin
1.6.20.

Depending on the project, parallel compilation in the Kotlin daemon may require more memory. To reduce memory consumption, increase
the heap size for the Kotlin daemon.

Learn more about the currently supported compiler options in the Kotlin Gradle plugin.

What's
new
in
Kotlin
1.6.0
Release date: 16 November 2021

Kotlin 1.6.0 introduces new language features, optimizations and improvements to existing features, and a lot of improvements to the
Kotlin standard library.

You can also find an overview of the changes in the release blog post.

Language
Kotlin 1.6.0 brings stabilization to several language features introduced for preview in the previous 1.5.30 release:

Stable exhaustive when statements for enum, sealed and Boolean subjects

Stable suspending functions as supertypes

Stable suspend conversions

Stable instantiation of annotation classes

It also includes various type inference improvements and support for annotations on class type parameters:

Improved type inference for recursive generic types

Changes to builder inference

Support for annotations on class type parameters

Stable
exhaustive
when
statements
for
enum,
sealed,
and
Boolean
subjects
An exhaustive when statement contains branches for all possible types or values of its subject, or for some types plus an else branch. It
covers all possible cases, making your code safer.

We will soon prohibit non-exhaustive when statements to make the behavior consistent with when expressions. To ensure smooth
migration, Kotlin 1.6.0 reports warnings about non-exhaustive when statements with an enum, sealed, or Boolean subject. These warnings
will become errors in future releases.

sealed class Contact {


data class PhoneCall(val number: String) : Contact()

125
data class TextMessage(val number: String) : Contact()
}

fun Contact.messageCost(): Int =


when(this) { // Error: 'when' expression must be exhaustive
is Contact.PhoneCall -> 42
}

fun sendMessage(contact: Contact, message: String) {


// Starting with 1.6.0

// Warning: Non exhaustive 'when' statements on Boolean will be


// prohibited in 1.7, add 'false' branch or 'else' branch instead
when(message.isEmpty()) {
true -> return
}
// Warning: Non exhaustive 'when' statements on sealed class/interface will be
// prohibited in 1.7, add 'is TextMessage' branch or 'else' branch instead
when(contact) {
is Contact.PhoneCall -> TODO()
}
}

See this YouTrack ticket for a more detailed explanation of the change and its effects.

Stable
suspending
functions
as
supertypes
Implementation of suspending functional types has become Stable in Kotlin 1.6.0. A preview was available in 1.5.30.

The feature can be useful when designing APIs that use Kotlin coroutines and accept suspending functional types. You can now
streamline your code by enclosing the desired behavior in a separate class that implements a suspending functional type.

class MyClickAction : suspend () -> Unit {


override suspend fun invoke() { TODO() }
}

fun launchOnClick(action: suspend () -> Unit) {}

You can use an instance of this class where only lambdas and suspending function references were allowed previously:
launchOnClick(MyClickAction()).

There are currently two limitations coming from implementation details:

You can't mix ordinary functional types and suspending ones in the list of supertypes.

You can't use multiple suspending functional supertypes.

Stable
suspend
conversions
Kotlin 1.6.0 introduces Stable conversions from regular to suspending functional types. Starting from 1.4.0, the feature supported
functional literals and callable references. With 1.6.0, it works with any form of expression. As a call argument, you can now pass any
expression of a suitable regular functional type where suspending is expected. The compiler will perform an implicit conversion
automatically.

fun getSuspending(suspending: suspend () -> Unit) {}

fun suspending() {}

fun test(regular: () -> Unit) {


getSuspending { } // OK

126
getSuspending(::suspending) // OK
getSuspending(regular) // OK
}

Stable
instantiation
of
annotation
classes
Kotlin 1.5.30 introduced experimental support for instantiation of annotation classes on the JVM platform. With 1.6.0, the feature is
available by default both for Kotlin/JVM and Kotlin/JS.

Learn more about instantiation of annotation classes in this KEEP.

Improved
type
inference
for
recursive
generic
types
Kotlin 1.5.30 introduced an improvement to type inference for recursive generic types, which allowed their type arguments to be inferred
based only on the upper bounds of the corresponding type parameters. The improvement was available with the compiler option. In
version 1.6.0 and later, it is enabled by default.

// Before 1.5.30
val containerA = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13-alpine")).apply {
withDatabaseName("db")
withUsername("user")
withPassword("password")
withInitScript("sql/schema.sql")
}

// With compiler option in 1.5.30 or by default starting with 1.6.0


val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
.withDatabaseName("db")
.withUsername("user")
.withPassword("password")
.withInitScript("sql/schema.sql")

Changes
to
builder
inference
Builder inference is a type inference flavor which is useful when calling generic builder functions. It can infer the type arguments of a call
with the help of type information from calls inside its lambda argument.

We're making multiple changes that are bringing us closer to fully stable builder inference. Starting with 1.6.0:

You can make calls returning an instance of a not yet inferred type inside a builder lambda without specifying the -Xunrestricted-
builder-inference compiler option introduced in 1.5.30.

With -Xenable-builder-inference, you can write your own builders without applying the @BuilderInference annotation.

Note that clients of these builders will need to specify the same -Xenable-builder-inference compiler option.

With the -Xenable-builder-inference, builder inference automatically activates if a regular type inference cannot get enough information
about a type.

Learn how to write custom generic builders.

Support
for
annotations
on
class
type
parameters
Support for annotations on class type parameters looks like this:

127
@Target(AnnotationTarget.TYPE_PARAMETER)
annotation class BoxContent

class Box<@BoxContent T> {}

Annotations on all type parameters are emitted into JVM bytecode so annotation processors are able to use them.

For the motivating use case, read this YouTrack ticket.

Learn more about annotations.

Supporting
previous
API
versions
for
a
longer
period
Starting with Kotlin 1.6.0, we will support development for three previous API versions instead of two, along with the current stable one.
Currently, we support versions 1.3, 1.4, 1.5, and 1.6.

Kotlin/JVM
For Kotlin/JVM, starting with 1.6.0, the compiler can generate classes with a bytecode version corresponding to JVM 17. The new
language version also includes optimized delegated properties and repeatable annotations, which we had on the roadmap:

Repeatable annotations with runtime retention for 1.8 JVM target

Optimize delegated properties which call get/set on the given KProperty instance

Repeatable
annotations
with
runtime
retention
for
1.8
JVM
target
Java 8 introduced repeatable annotations, which can be applied multiple times to a single code element. The feature requires two
declarations to be present in the Java code: the repeatable annotation itself marked with @java.lang.annotation.Repeatable and the
containing annotation to hold its values.

Kotlin also has repeatable annotations, but requires only @kotlin.annotation.Repeatable to be present on an annotation declaration to
make it repeatable. Before 1.6.0, the feature supported only SOURCE retention and was incompatible with Java's repeatable annotations.
Kotlin 1.6.0 removes these limitations. @kotlin.annotation.Repeatable now accepts any retention and makes the annotation repeatable
both in Kotlin and Java. Java's repeatable annotations are now also supported from the Kotlin side.

While you can declare a containing annotation, it's not necessary. For example:

If an annotation @Tag is marked with @kotlin.annotation.Repeatable, the Kotlin compiler automatically generates a containing
annotation class under the name of @Tag.Container:

@Repeatable
annotation class Tag(val name: String)

// The compiler generates @Tag.Container containing annotation

To set a custom name for a containing annotation, apply the @kotlin.jvm.JvmRepeatable meta-annotation and pass the explicitly
declared containing annotation class as an argument:

@JvmRepeatable(Tags::class)
annotation class Tag(val name: String)

annotation class Tags(val value: Array<Tag>)

128
Kotlin reflection now supports both Kotlin's and Java's repeatable annotations via a new function, KAnnotatedElement.findAnnotations().

Learn more about Kotlin repeatable annotations in this KEEP.

Optimize
delegated
properties
which
call
get/set
on
the
given
KProperty
instance
We optimized the generated JVM bytecode by omitting the $delegate field and generating immediate access to the referenced property.

For example, in the following code

class Box<T> {
private var impl: T = ...

var content: T by ::impl


}

Kotlin no longer generates the field content$delegate. Property accessors of the content variable invoke the impl variable directly, skipping
the delegated property's getValue/setValue operators and thus avoiding the need for the property reference object of the KProperty type.

Thanks to our Google colleagues for the implementation!

Learn more about delegated properties.

Kotlin/Native
Kotlin/Native is receiving multiple improvements and component updates, some of them in the preview state:

Preview of the new memory manager

Support for Xcode 13

Compilation of Windows targets on any host

LLVM and linker updates

Performance improvements

Unified compiler plugin ABI with JVM and JS IR backends

Detailed error messages for klib linkage failures

Reworked unhandled exception handling API

Preview
of
the
new
memory
manager

The new Kotlin/Native memory manager is Experimental. It may be dropped or changed at any time. Opt-in is required (see
details below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

With Kotlin 1.6.0, you can try the development preview of the new Kotlin/Native memory manager. It moves us closer to eliminating the
differences between the JVM and Native platforms to provide a consistent developer experience in multiplatform projects.

One of the notable changes is the lazy initialization of top-level properties, like in Kotlin/JVM. A top-level property gets initialized when a
top-level property or function from the same file is accessed for the first time. This mode also includes global interprocedural optimization

129
(enabled only for release binaries), which removes redundant initialization checks.

We've recently published a blog post about the new memory manager. Read it to learn about the current state of the new memory
manager and find some demo projects, or jump right to the migration instructions to try it yourself. Please check how the new memory
manager works on your projects and share feedback in our issue tracker, YouTrack.

Support
for
Xcode
13
Kotlin/Native 1.6.0 supports Xcode 13 – the latest version of Xcode. Feel free to update your Xcode and continue working on your Kotlin
projects for Apple operating systems.

New libraries added in Xcode 13 aren't available for use in Kotlin 1.6.0, but we're going to add support for them in upcoming
versions.

Compilation
of
Windows
targets
on
any
host
Starting from 1.6.0, you don't need a Windows host to compile the Windows targets mingwX64 and mingwX86. They can be compiled on
any host that supports Kotlin/Native.

LLVM
and
linker
updates
We've reworked the LLVM dependency that Kotlin/Native uses under the hood. This brings various benefits, including:

Updated LLVM version to 11.1.0.

Decreased dependency size. For example, on macOS it's now about 300 MB instead of 1200 MB in the previous version.

Excluded dependency on the ncurses5 library that isn't available in modern Linux distributions.

In addition to the LLVM update, Kotlin/Native now uses the LLD linker (a linker from the LLVM project) for MingGW targets. It provides
various benefits over the previously used ld.bfd linker, and will allow us to improve runtime performance of produced binaries and support
compiler caches for MinGW targets. Note that LLD requires import libraries for DLL linkage. Learn more in this Stack Overflow thread.

Performance
improvements
Kotlin/Native 1.6.0 delivers the following performance improvements:

Compilation time: compiler caches are enabled by default for linuxX64 and iosArm64 targets. This speeds up most compilations in
debug mode (except the first one). Measurements showed about a 200% speed increase on our test projects. The compiler caches
have been available for these targets since Kotlin 1.5.0 with additional Gradle properties; you can remove them now.

Runtime: iterating over arrays with for loops is now up to 12% faster thanks to optimizations in the produced LLVM code.

Unified
compiler
plugin
ABI
with
JVM
and
JS
IR
backends

The option to use the common IR compiler plugin ABI for Kotlin/Native is Experimental. It may be dropped or changed at any
time. Opt-in is required (see details below), and you should use it only for evaluation purposes. We would appreciate your
feedback on it in YouTrack.

In previous versions, authors of compiler plugins had to provide separate artifacts for Kotlin/Native because of the differences in the ABI.

130
Starting from 1.6.0, the Kotlin Multiplatform Gradle plugin is able to use the embeddable compiler jar – the one used for the JVM and JS IR
backends – for Kotlin/Native. This is a step toward unification of the compiler plugin development experience, as you can now use the
same compiler plugin artifacts for Native and other supported platforms.

This is a preview version of such support, and it requires an opt-in. To start using generic compiler plugin artifacts for Kotlin/Native, add
the following line to gradle.properties: kotlin.native.useEmbeddableCompilerJar=true.

We're planning to use the embeddable compiler jar for Kotlin/Native by default in the future, so it's vital for us to hear how the preview
works for you.

If you are an author of a compiler plugin, please try this mode and check if it works for your plugin. Note that depending on your plugin's
structure, migration steps may be required. See this YouTrack issue for migration instructions and leave your feedback in the comments.

Detailed
error
messages
for
klib
linkage
failures
The Kotlin/Native compiler now provides detailed error messages for klib linkage errors. The messages now have clear error descriptions,
and they also include information about possible causes and ways to fix them.

For example:

1.5.30:

e: java.lang.IllegalStateException: IrTypeAliasSymbol expected: Unbound public symbol for public


kotlinx.coroutines/CancellationException|null[0]
<stack trace>

1.6.0:

e: The symbol of unexpected type encountered during IR deserialization: IrClassPublicSymbolImpl,


kotlinx.coroutines/CancellationException|null[0].
IrTypeAliasSymbol is expected.

This could happen if there are two libraries, where one library was compiled against the different version of
the other library than the one currently used in the project.
Please check that the project configuration is correct and has consistent versions of dependencies.

The list of libraries that depend on "org.jetbrains.kotlinx:kotlinx-coroutines-core


(org.jetbrains.kotlinx:kotlinx-coroutines-core-macosx64)" and may lead to conflicts:
<list of libraries and potential version mismatches>

Project dependencies:
<dependencies tree>

Reworked
unhandled
exception
handling
API
We've unified the processing of unhandled exceptions throughout the Kotlin/Native runtime and exposed the default processing as the
function processUnhandledException(throwable: Throwable) for use by custom execution environments, like kotlinx.coroutines. This
processing is also applied to exceptions that escape operation in Worker.executeAfter(), but only for the new memory manager.

API improvements also affected the hooks that have been set by setUnhandledExceptionHook(). Previously such hooks were reset after
the Kotlin/Native runtime called the hook with an unhandled exception, and the program would always terminate right after. Now these
hooks may be used more than once, and if you want the program to always terminate on an unhandled exception, either do not set an
unhandled exception hook (setUnhandledExceptionHook()), or make sure to call terminateWithUnhandledException() at the end of your
hook. This will help you send exceptions to a third-party crash reporting service (like Firebase Crashlytics) and then terminate the program.
Exceptions that escape main() and exceptions that cross the interop boundary will always terminate the program, even if the hook did not
call terminateWithUnhandledException().

131
Kotlin/JS
We're continuing to work on stabilizing the IR backend for the Kotlin/JS compiler. Kotlin/JS now has an option to disable downloading of
Node.js and Yarn.

Option
to
use
pre-installed
Node.js
and
Yarn
You can now disable downloading Node.js and Yarn when building Kotlin/JS projects and use the instances already installed on the host.
This is useful for building on servers without internet connectivity, such as CI servers.

To disable downloading external components, add the following lines to your build.gradle(.kts):

Yarn:

Kotlin

rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension>().download = false // or
true for default behavior
}

Groovy

rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin) {
rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.yarn.YarnRootExtension).download
= false
}

Node.js:

Kotlin

rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().download = false //
or true for default behavior
}

Groovy

rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin) {

rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension).download
= false
}

Kotlin
Gradle
plugin
In Kotlin 1.6.0, we changed the deprecation level of the KotlinGradleSubplugin class to 'ERROR'. This class was used for writing compiler
plugins. In the following releases, we'll remove this class. Use the class KotlinCompilerPluginSupportPlugin instead.

132
We removed the kotlin.useFallbackCompilerSearch build option and the noReflect and includeRuntime compiler options. The useIR
compiler option has been hidden and will be removed in upcoming releases.

Learn more about the currently supported compiler options in the Kotlin Gradle plugin.

Standard
library
The new 1.6.0 version of the standard library stabilizes experimental features, introduces new ones, and unifies its behavior across the
platforms:

New readline functions

Stable typeOf()

Stable collection builders

Stable Duration API

Splitting Regex into a sequence

Bit rotation operations on integers

Changes for replace() and replaceFirst() in JS

Improvements to the existing API

Deprecations

New
readline
functions
Kotlin 1.6.0 offers new functions for handling standard input: readln() and readlnOrNull().

For now, new functions are available for the JVM and Native target platforms only.

Earlier versions 1.6.0 alternative Usage

readLine()!! readln() Reads a line from stdin and returns it, or throws a RuntimeException if EOF has been reached.

readLine() readlnOrNull() Reads a line from stdin and returns it, or returns null if EOF has been reached.

We believe that eliminating the need to use !! when reading a line will improve the experience for newcomers and simplify teaching Kotlin.
To make the read-line operation name consistent with its println() counterpart, we've decided to shorten the names of new functions to
'ln'.

println("What is your nickname?")


val nickname = readln()
println("Hello, $nickname!")

fun main() {

133
//sampleStart
var sum = 0
while (true) {
val nextLine = readlnOrNull().takeUnless {
it.isNullOrEmpty()
} ?: break
sum += nextLine.toInt()
}
println(sum)
//sampleEnd
}

The existing readLine() function will get a lower priority than readln() and readlnOrNull() in your IDE code completion. IDE inspections will
also recommend using new functions instead of the legacy readLine().

We're planning to gradually deprecate the readLine() function in future releases.

Stable
typeOf()
Version 1.6.0 brings a Stable typeOf() function, closing one of the major roadmap items.

Since 1.3.40, typeOf() was available on the JVM platform as an experimental API. Now you can use it in any Kotlin platform and get KType
representation of any Kotlin type that the compiler can infer:

inline fun <reified T> renderType(): String {


val type = typeOf<T>()
return type.toString()
}

fun main() {
val fromExplicitType = typeOf<Int>()
val fromReifiedType = renderType<List<Int>>()
}

Stable
collection
builders
In Kotlin 1.6.0, collection builder functions have been promoted to Stable. Collections returned by collection builders are now serializable
in their read-only state.

You can now use buildMap(), buildList(), and buildSet() without the opt-in annotation:

fun main() {
//sampleStart
val x = listOf('b', 'c')
val y = buildList {
add('a')
addAll(x)
add('d')
}
println(y) // [a, b, c, d]
//sampleEnd
}

Stable
Duration
API
The Duration class for representing duration amounts in different time units has been promoted to Stable. In 1.6.0, the Duration API has
received the following changes:

The first component of the toComponents() function that decomposes the duration into days, hours, minutes, seconds, and

134
nanoseconds now has the Long type instead of Int. Before, if the value didn't fit into the Int range, it was coerced into that range. With
the Long type, you can decompose any value in the duration range without cutting off the values that don't fit into Int.

The DurationUnit enum is now standalone and not a type alias of java.util.concurrent.TimeUnit on the JVM. We haven't found any
convincing cases in which having typealias DurationUnit = TimeUnit could be useful. Also, exposing the TimeUnit API through a type
alias might confuse DurationUnit users.

In response to community feedback, we're bringing back extension properties like Int.seconds. But we'd like to limit their applicability,
so we put them into the companion of the Duration class. While the IDE can still propose extensions in completion and automatically
insert an import from the companion, in the future we plan to limit this behavior to cases when the Duration type is expected.

import kotlin.time.Duration.Companion.seconds

fun main() {
//sampleStart
val duration = 10000
println("There are ${duration.seconds.inWholeMinutes} minutes in $duration seconds")
// There are 166 minutes in 10000 seconds
//sampleEnd
}

We suggest replacing previously introduced companion functions, such as Duration.seconds(Int), and deprecated top-level extensions
like Int.seconds with new extensions in Duration.Companion.

Such a replacement may cause ambiguity between old top-level extensions and new companion extensions. Be sure to use
the wildcard import of the kotlin.time package – import kotlin.time.* – before doing automated migration.

Splitting
Regex
into
a
sequence
The Regex.splitToSequence(CharSequence) and CharSequence.splitToSequence(Regex) functions are promoted to Stable. They split the
string around matches of the given regex, but return the result as a Sequence so that all operations on this result are executed lazily:

fun main() {
//sampleStart
val colorsText = "green, red, brown&blue, orange, pink&green"
val regex = "[,\\s]+".toRegex()
val mixedColor = regex.splitToSequence(colorsText)
// or
// val mixedColor = colorsText.splitToSequence(regex)
.onEach { println(it) }
.firstOrNull { it.contains('&') }
println(mixedColor) // "brown&blue"
//sampleEnd
}

Bit
rotation
operations
on
integers
In Kotlin 1.6.0, the rotateLeft() and rotateRight() functions for bit manipulations became Stable. The functions rotate the binary
representation of the number left or right by a specified number of bits:

fun main() {
//sampleStart
val number: Short = 0b10001
println(number
.rotateRight(2)
.toString(radix = 2)) // 100000000000100

135
println(number
.rotateLeft(2)
.toString(radix = 2)) // 1000100
//sampleEnd
}

Changes
for
replace()
and
replaceFirst()
in
JS
Before Kotlin 1.6.0, the replace() and replaceFirst() Regex functions behaved differently in Java and JS when the replacement string
contained a group reference. To make the behavior consistent across all target platforms, we've changed their implementation in JS.

Occurrences of ${name} or $index in the replacement string are substituted with the subsequences corresponding to the captured groups
with the specified index or a name:

$index – the first digit after '$' is always treated as a part of the group reference. Subsequent digits are incorporated into the index only
if they form a valid group reference.Only digits '0'–'9' are considered potential components of the group reference. Note that indexes of
captured groups start from '1'. The group with index '0' stands for the whole match.

${name} – the name can consist of Latin letters 'a'–'z', 'A'–'Z', or digits '0'–'9'. The first character must be a letter.

Named groups in replacement patterns are currently supported only on the JVM.

To include the succeeding character as a literal in the replacement string, use the backslash character \:

fun main() {
//sampleStart
println(Regex("(.+)").replace("Kotlin", """\$ $1""")) // $ Kotlin
println(Regex("(.+)").replaceFirst("1.6.0", """\\ $1""")) // \ 1.6.0
//sampleEnd
}

You can use Regex.escapeReplacement() if the replacement string has to be treated as a literal string.

Improvements
to
the
existing
API
Version 1.6.0 added the infix extension function for Comparable.compareTo(). You can now use the infix form for comparing two
objects for order:

class WrappedText(val text: String) : Comparable<WrappedText> {


override fun compareTo(other: WrappedText): Int =
this.text compareTo other.text
}

Regex.replace() in JS is now also not inline to unify its implementation across all platforms.

The compareTo() and equals() String functions, as well as the isBlank() CharSequence function now behave in JS exactly the same way
they do on the JVM. Previously there were deviations when it came to non-ASCII characters.

Deprecations
In Kotlin 1.6.0, we're starting the deprecation cycle with a warning for some JS-only stdlib API.

136
concat(), match(), and matches() string functions

To concatenate the string with the string representation of a given other object, use plus() instead of concat().

To find all occurrences of a regular expression within the input, use findAll() of the Regex class instead of String.match(regex: String).

To check if the regular expression matches the entire input, use matches() of the Regex class instead of String.matches(regex: String).

sort() on arrays taking comparison functions


We've deprecated the Array<out T>.sort() function and the inline functions ByteArray.sort(), ShortArray.sort(), IntArray.sort(),
LongArray.sort(), FloatArray.sort(), DoubleArray.sort(), and CharArray.sort(), which sorted arrays following the order passed by the
comparison function. Use other standard library functions for array sorting.

See the collection ordering section for reference.

Tools

Kover

a
code
coverage
tool
for
Kotlin

The Kover Gradle plugin is Experimental. We would appreciate your feedback on it in GitHub.

With Kotlin 1.6.0, we're introducing Kover – a Gradle plugin for the IntelliJ and JaCoCo Kotlin code coverage agents. It works with all
language constructs, including inline functions.

Learn more about Kover on its GitHub repository or in this video:

Gif

Watch video online.

Coroutines
1.6.0-RC
kotlinx.coroutines 1.6.0-RC is out with multiple features and improvements:

137
Support for the new Kotlin/Native memory manager

Introduction of dispatcher views API, which allows limiting parallelism without creating additional threads

Migrating from Java 6 to Java 8 target

kotlinx-coroutines-test with the new reworked API and multiplatform support

Introduction of CopyableThreadContextElement, which gives coroutines a thread-safe write access to ThreadLocal variables

Learn more in the changelog.

Migrating
to
Kotlin
1.6.0
IntelliJ IDEA and Android Studio will suggest updating the Kotlin plugin to 1.6.0 once it is available.

To migrate existing projects to Kotlin 1.6.0, change the Kotlin version to 1.6.0 and reimport your Gradle or Maven project. Learn how to
update to Kotlin 1.6.0.

To start a new project with Kotlin 1.6.0, update the Kotlin plugin and run the Project Wizard from File | New | Project.

The new command-line compiler is available for download on the GitHub release page.

Kotlin 1.6.0 is a feature release and can, therefore, bring changes that are incompatible with your code written for earlier versions of the
language. Find the detailed list of such changes in the Compatibility Guide for Kotlin 1.6.

What's
new
in
Kotlin
1.5.30
Release date: 24 August 2021

Kotlin 1.5.30 offers language updates including previews of future changes, various improvements in platform support and tooling, and
new standard library functions.

Here are some major improvements:

Language features, including experimental sealed when statements, changes in using opt-in requirement, and others

Native support for Apple silicon

Kotlin/JS IR backend reaches Beta

Improved Gradle plugin experience

You can also find a short overview of the changes in the release blog post and this video:

138
Gif

Watch video online.

Language
features
Kotlin 1.5.30 is presenting previews of future language changes and bringing improvements to the opt-in requirement mechanism and
type inference:

Exhaustive when statements for sealed and Boolean subjects

Suspending functions as supertypes

Requiring opt-in on implicit usages of experimental APIs

Changes to using opt-in requirement annotations with different targets

Improvements to type inference for recursive generic types

Eliminating builder inference restrictions

Exhaustive
when
statements
for
sealed
and
Boolean
subjects

Support for sealed (exhaustive) when statements is Experimental. It may be dropped or changed at any time. Opt-in is required
(see the details below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in
YouTrack.

An exhaustive when statement contains branches for all possible types or values of its subject or for some types plus an else branch. In
other words, it covers all possible cases.

We're planning to prohibit non-exhaustive when statements soon to make the behavior consistent with when expressions. To ensure
smooth migration, you can configure the compiler to report warnings about non-exhaustive when statements with a sealed class or a
Boolean. Such warnings will appear by default in Kotlin 1.6 and will become errors later.

139
Enums already get a warning.

sealed class Mode {


object ON : Mode()
object OFF : Mode()
}

fun main() {
val x: Mode = Mode.ON
when (x) {
Mode.ON -> println("ON")
}
// WARNING: Non exhaustive 'when' statements on sealed classes/interfaces
// will be prohibited in 1.7, add an 'OFF' or 'else' branch instead

val y: Boolean = true


when (y) {
true -> println("true")
}
// WARNING: Non exhaustive 'when' statements on Booleans will be prohibited
// in 1.7, add a 'false' or 'else' branch instead
}

To enable this feature in Kotlin 1.5.30, use language version 1.6. You can also change the warnings to errors by enabling progressive
mode.

Kotlin

kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.6"
//progressiveMode = true // false by default
}
}
}

Groovy

kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.6'
//progressiveMode = true // false by default
}
}
}

Suspending
functions
as
supertypes

Support for suspending functions as supertypes is Experimental. It may be dropped or changed at any time. Opt-in is required
(see the details below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in
YouTrack.

140
Kotlin 1.5.30 provides a preview of the ability to use a suspend functional type as a supertype with some limitations.

class MyClass: suspend () -> Unit {


override suspend fun invoke() { TODO() }
}

Use the -language-version 1.6 compiler option to enable the feature:

Kotlin

kotlin {
sourceSets.all {
languageSettings.apply {
languageVersion = "1.6"
}
}
}

Groovy

kotlin {
sourceSets.all {
languageSettings {
languageVersion = '1.6'
}
}
}

The feature has the following restrictions:

You can't mix an ordinary functional type and a suspend functional type as supertype. This is because of the implementation details of
suspend functional types in the JVM backend. They are represented in it as ordinary functional types with a marker interface. Because
of the marker interface, there is no way to tell which of the superinterfaces are suspended and which are ordinary.

You can't use multiple suspend functional supertypes. If there are type checks, you also can't use multiple ordinary functional
supertypes.

Requiring
opt-in
on
implicit
usages
of
experimental
APIs

The opt-in requirement mechanism is Experimental. It may change at any time. See how to opt-in. Use it only for evaluation
purposes. We would appreciate your feedback on it in YouTrack.

The author of a library can mark an experimental API as requiring opt-in to inform users about its experimental state. The compiler raises a
warning or error when the API is used and requires explicit consent to suppress it.

In Kotlin 1.5.30, the compiler treats any declaration that has an experimental type in the signature as experimental. Namely, it requires
opt-in even for implicit usages of an experimental API. For example, if the function's return type is marked as an experimental API
element, a usage of the function requires you to opt-in even if the declaration is not marked as requiring an opt-in explicitly.

// Library code

@RequiresOptIn(message = "This API is experimental.")

141
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.CLASS)
annotation class MyDateTime // Opt-in requirement annotation

@MyDateTime
class DateProvider // A class requiring opt-in

// Client code

// Warning: experimental API usage


fun createDateSource(): DateProvider { /* ... */ }

fun getDate(): Date {


val dateSource = createDateSource() // Also warning: experimental API usage
// ...
}

Learn more about opt-in requirements.

Changes
to
using
opt-in
requirement
annotations
with
different
targets

The opt-in requirement mechanism is Experimental. It may change at any time. See how to opt-in. Use it only for evaluation
purposes. We would appreciate your feedback on it in YouTrack.

Kotlin 1.5.30 presents new rules for using and declaring opt-in requirement annotations on different targets. The compiler now reports an
error for use cases that are impractical to handle at compile time. In Kotlin 1.5.30:

Marking local variables and value parameters with opt-in requirement annotations is forbidden at the use site.

Marking override is allowed only if its basic declaration is also marked.

Marking backing fields and getters is forbidden. You can mark the basic property instead.

Setting TYPE and TYPE_PARAMETER annotation targets is forbidden at the opt-in requirement annotation declaration site.

Learn more about opt-in requirements.

Improvements
to
type
inference
for
recursive
generic
types
In Kotlin and Java, you can define a recursive generic type, which references itself in its type parameters. In Kotlin 1.5.30, the Kotlin
compiler can infer a type argument based only on upper bounds of the corresponding type parameter if it is a recursive generic. This
makes it possible to create various patterns with recursive generic types that are often used in Java to make builder APIs.

// Kotlin 1.5.20
val containerA = PostgreSQLContainer<Nothing>(DockerImageName.parse("postgres:13-alpine")).apply {
withDatabaseName("db")
withUsername("user")
withPassword("password")
withInitScript("sql/schema.sql")
}

// Kotlin 1.5.30
val containerB = PostgreSQLContainer(DockerImageName.parse("postgres:13-alpine"))
.withDatabaseName("db")
.withUsername("user")
.withPassword("password")
.withInitScript("sql/schema.sql")

142
You can enable the improvements by passing the -Xself-upper-bound-inference or the -language-version 1.6 compiler options. See other
examples of newly supported use cases in this YouTrack ticket.

Eliminating
builder
inference
restrictions
Builder inference is a special kind of type inference that allows you to infer the type arguments of a call based on type information from
other calls inside its lambda argument. This can be useful when calling generic builder functions such as buildList() or sequence(): buildList
{ add("string") }.

Inside such a lambda argument, there was previously a limitation on using the type information that the builder inference tries to infer. This
means you can only specify it and cannot get it. For example, you cannot call get() inside a lambda argument of buildList() without
explicitly specified type arguments.

Kotlin 1.5.30 removes these limitations with the -Xunrestricted-builder-inference compiler option. Add this option to enable previously
prohibited calls inside a lambda argument of generic builder functions:

@kotlin.ExperimentalStdlibApi
val list = buildList {
add("a")
add("b")
set(1, null)
val x = get(1)
if (x != null) {
removeAt(1)
}
}

@kotlin.ExperimentalStdlibApi
val map = buildMap {
put("a", 1)
put("b", 1.1)
put("c", 2f)
}

Also, you can enable this feature with the -language-version 1.6 compiler option.

Kotlin/JVM
With Kotlin 1.5.30, Kotlin/JVM receives the following features:

Instantiation of annotation classes

Improved nullability annotation support configuration

See the Gradle section for Kotlin Gradle plugin updates on the JVM platform.

Instantiation
of
annotation
classes

Instantiation of annotation classes is Experimental. It may be dropped or changed at any time. Opt-in is required (see the details
below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

With Kotlin 1.5.30 you can now call constructors of annotation classes in arbitrary code to obtain a resulting instance. This feature covers
the same use cases as the Java convention that allows the implementation of an annotation interface.

143
annotation class InfoMarker(val info: String)

fun processInfo(marker: InfoMarker) = ...

fun main(args: Array<String>) {


if (args.size != 0)
processInfo(getAnnotationReflective(args))
else
processInfo(InfoMarker("default"))
}

Use the -language-version 1.6 compiler option to enable this feature. Note that all current annotation class limitations, such as restrictions
to define non-val parameters or members different from secondary constructors, remain intact.

Learn more about instantiation of annotation classes in this KEEP

Improved
nullability
annotation
support
configuration
The Kotlin compiler can read various types of nullability annotations to get nullability information from Java. This information allows it to
report nullability mismatches in Kotlin when calling Java code.

In Kotlin 1.5.30, you can specify whether the compiler reports a nullability mismatch based on the information from specific types of
nullability annotations. Just use the compiler option -Xnullability-annotations=@<package-name>:<report-level>. In the argument, specify
the fully qualified nullability annotations package and one of these report levels:

ignore to ignore nullability mismatches

warn to report warnings

strict to report errors.

See the full list of supported nullability annotations along with their fully qualified package names.

Here is an example showing how to enable error reporting for the newly supported RxJava 3 nullability annotations: -Xnullability-
[email protected]:strict. Note that all such nullability mismatches are warnings by default.

Kotlin/Native
Kotlin/Native has received various changes and improvements:

Apple silicon support

Improved Kotlin DSL for the CocoaPods Gradle plugin

Experimental interoperability with Swift 5.5 async/await

Improved Swift/Objective-C mapping for objects and companion objects

Deprecation of linkage against DLLs without import libraries for MinGW targets

Apple
silicon
support
Kotlin 1.5.30 introduces native support for Apple silicon.

Previously, the Kotlin/Native compiler and tooling required the Rosetta translation environment for working on Apple silicon hosts. In Kotlin
1.5.30, the translation environment is no longer needed – the compiler and tooling can run on Apple silicon hardware without requiring any
additional actions.

144
We've also introduced new targets that make Kotlin code run natively on Apple silicon:

macosArm64

iosSimulatorArm64

watchosSimulatorArm64

tvosSimulatorArm64

They are available on both Intel-based and Apple silicon hosts. All existing targets are available on Apple silicon hosts as well.

Note that in 1.5.30 we provide only basic support for Apple silicon targets in the kotlin-multiplatform Gradle plugin. Particularly, the new
simulator targets aren't included in the ios, tvos, and watchos target shortcuts. Learn how to use Apple silicon targets with the target
shortcuts. We will keep working to improve the user experience with the new targets.

Improved
Kotlin
DSL
for
the
CocoaPods
Gradle
plugin

New parameters for Kotlin/Native frameworks


Kotlin 1.5.30 introduces the improved CocoaPods Gradle plugin DSL for Kotlin/Native frameworks. In addition to the name of the
framework, you can specify other parameters in the pod configuration:

Specify the dynamic or static version of the framework

Enable export dependencies explicitly

Enable Bitcode embedding

To use the new DSL, update your project to Kotlin 1.5.30, and specify the parameters in the cocoapods section of your build.gradle(.kts)
file:

cocoapods {
frameworkName = "MyFramework" // This property is deprecated
// and will be removed in future versions
// New DSL for framework configuration:
framework {
// All Framework properties are supported
// Framework name configuration. Use this property instead of
// deprecated 'frameworkName'
baseName = "MyFramework"
// Dynamic framework support
isStatic = false
// Dependency export
export(project(":anotherKMMModule"))
transitiveExport = false // This is default.
// Bitcode embedding
embedBitcode(BITCODE)
}
}

Support custom names for Xcode configuration


The Kotlin CocoaPods Gradle plugin supports custom names in the Xcode build configuration. It will also help you if you're using special
names for the build configuration in Xcode, for example Staging.

To specify a custom name, use the xcodeConfigurationToNativeBuildType parameter in the cocoapods section of your build.gradle(.kts)
file:

145
cocoapods {
// Maps custom Xcode configuration to NativeBuildType
xcodeConfigurationToNativeBuildType["CUSTOM_DEBUG"] = NativeBuildType.DEBUG
xcodeConfigurationToNativeBuildType["CUSTOM_RELEASE"] = NativeBuildType.RELEASE
}

This parameter will not appear in the Podspec file. When Xcode runs the Gradle build process, the Kotlin CocoaPods Gradle plugin will
select the necessary native build type.

There's no need to declare the Debug and Release configurations because they are supported by default.

Experimental
interoperability
with
Swift
5.5
async/await

Concurrency interoperability with Swift async/await is Experimental. It may be dropped or changed at any time. You should use
it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

We added support for calling Kotlin's suspending functions from Objective-C and Swift in 1.4.0, and now we're improving it to keep up
with a new Swift 5.5 feature – concurrency with async and await modifiers.

The Kotlin/Native compiler now emits the _Nullable_result attribute in the generated Objective-C headers for suspending functions with
nullable return types. This makes it possible to call them from Swift as async functions with the proper nullability.

Note that this feature is experimental and can be affected in the future by changes in both Kotlin and Swift. For now, we're offering a
preview of this feature that has certain limitations, and we are eager to hear what you think. Learn more about its current state and leave
your feedback in this YouTrack issue.

Improved
Swift/Objective-C
mapping
for
objects
and
companion
objects
Getting objects and companion objects can now be done in a way that is more intuitive for native iOS developers. For example, if you have
the following objects in Kotlin:

object MyObject {
val x = "Some value"
}

class MyClass {
companion object {
val x = "Some value"
}
}

To access them in Swift, you can use the shared and companion properties:

MyObject.shared
MyObject.shared.x
MyClass.companion
MyClass.Companion.shared

Learn more about Swift/Objective-C interoperability.

146
Deprecation
of
linkage
against
DLLs
without
import
libraries
for
MinGW
targets
LLD is a linker from the LLVM project, which we plan to start using in Kotlin/Native for MinGW targets because of its benefits over the
default ld.bfd – primarily its better performance.

However, the latest stable version of LLD doesn't support direct linkage against DLL for MinGW (Windows) targets. Such linkage requires
using import libraries. Although they aren't needed with Kotlin/Native 1.5.30, we're adding a warning to inform you that such usage is
incompatible with LLD that will become the default linker for MinGW in the future.

Please share your thoughts and concerns about the transition to the LLD linker in this YouTrack issue.

Kotlin
Multiplatform
1.5.30 brings the following notable updates to Kotlin Multiplatform:

Ability to use custom cinterop libraries in shared native code

Support for XCFrameworks

New default publishing setup for Android artifacts

Ability
to
use
custom
cinterop
libraries
in
shared
native
code
Kotlin Multiplatform gives you an option to use platform-dependent interop libraries in shared source sets. Before 1.5.30, this worked only
with platform libraries shipped with Kotlin/Native distribution. Starting from 1.5.30, you can use it with your custom cinterop libraries. To
enable this feature, add the kotlin.mpp.enableCInteropCommonization=true property in your gradle.properties:

kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.native.enableDependencyPropagation=false
kotlin.mpp.enableCInteropCommonization=true

Support
for
XCFrameworks
All Kotlin Multiplatform projects can now have XCFrameworks as an output format. Apple introduced XCFrameworks as a replacement for
universal (fat) frameworks. With the help of XCFrameworks you:

Can gather logic for all the target platforms and architectures in a single bundle.

Don't need to remove all unnecessary architectures before publishing the application to the App Store.

XCFrameworks is useful if you want to use your Kotlin framework for devices and simulators on Apple M1.

To use XCFrameworks, update your build.gradle(.kts) script:

Kotlin

import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework

plugins {
kotlin("multiplatform")
}

kotlin {
val xcf = XCFramework()

ios {
binaries.framework {

147
baseName = "shared"
xcf.add(this)
}
}
watchos {
binaries.framework {
baseName = "shared"
xcf.add(this)
}
}
tvos {
binaries.framework {
baseName = "shared"
xcf.add(this)
}
}
}

Groovy

import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFrameworkConfig

plugins {
id 'org.jetbrains.kotlin.multiplatform'
}

kotlin {
def xcf = new XCFrameworkConfig(project)

ios {
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
watchos {
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
tvos {
binaries.framework {
baseName = "shared"
xcf.add(it)
}
}
}

When you declare XCFrameworks, these new Gradle tasks will be registered:

assembleXCFramework

assembleDebugXCFramework (additionally debug artifact that contains dSYMs)

assembleReleaseXCFramework

Learn more about XCFrameworks in this WWDC video.

New
default
publishing
setup
for
Android
artifacts
Using the maven-publish Gradle plugin, you can publish your multiplatform library for the Android target by specifying Android variant
names in the build script. The Kotlin Gradle plugin will generate publications automatically.

148
Before 1.5.30, the generated publication metadata included the build type attributes for every published Android variant, making it
compatible only with the same build type used by the library consumer. Kotlin 1.5.30 introduces a new default publishing setup:

If all Android variants that the project publishes have the same build type attribute, then the published variants won't have the build
type attribute and will be compatible with any build type.

If the published variants have different build type attributes, then only those with the release value will be published without the build
type attribute. This makes the release variants compatible with any build type on the consumer side, while non-release variants will only
be compatible with the matching consumer build types.

To opt-out and keep the build type attributes for all variants, you can set this Gradle property: kotlin.android.buildTypeAttribute.keep=true.

Kotlin/JS
Two major improvements are coming to Kotlin/JS with 1.5.30:

JS IR compiler backend reaches Beta

Better debugging experience for applications with the Kotlin/JS IR backend

JS
IR
compiler
backend
reaches
Beta
The IR-based compiler backend for Kotlin/JS, which was introduced in 1.4.0 in Alpha, has reached Beta.

Previously, we published the migration guide for the JS IR backend to help you migrate your projects to the new backend. Now we would
like to present the Kotlin/JS Inspection Pack IDE plugin, which displays the required changes directly in IntelliJ IDEA.

Better
debugging
experience
for
applications
with
the
Kotlin/JS
IR
backend
Kotlin 1.5.30 brings JavaScript source map generation for the Kotlin/JS IR backend. This will improve the Kotlin/JS debugging experience
when the IR backend is enabled, with full debugging support that includes breakpoints, stepping, and readable stack traces with proper
source references.

Learn how to debug Kotlin/JS in the browser or IntelliJ IDEA Ultimate.

Gradle
As a part of our mission to improve the Kotlin Gradle plugin user experience, we've implemented the following features:

Support for Java toolchains, which includes an ability to specify a JDK home with the UsesKotlinJavaToolchain interface for older
Gradle versions

An easier way to explicitly specify the Kotlin daemon's JVM arguments

Support
for
Java
toolchains
Gradle 6.7 introduced the "Java toolchains support" feature. Using this feature, you can:

Run compilations, tests, and executables using JDKs and JREs that are different from the Gradle ones.

Compile and test code with an unreleased language version.

With toolchains support, Gradle can autodetect local JDKs and install missing JDKs that Gradle requires for the build. Now Gradle itself
can run on any JDK and still reuse the build cache feature.

149
The Kotlin Gradle plugin supports Java toolchains for Kotlin/JVM compilation tasks. A Java toolchain:

Sets the jdkHome option available for JVM targets.

The ability to set the jdkHome option directly has been deprecated.

Sets the kotlinOptions.jvmTarget to the toolchain's JDK version if the user didn't set the jvmTarget option explicitly. If the toolchain is
not configured, the jvmTarget field uses the default value. Learn more about JVM target compatibility.

Affects which JDK kapt workers are running on.

Use the following code to set a toolchain. Replace the placeholder <MAJOR_JDK_VERSION> with the JDK version you would like to use:

Kotlin

kotlin {
jvmToolchain {
(this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
}
}

Groovy

kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
}
}

Note that setting a toolchain via the kotlin extension will update the toolchain for Java compile tasks as well.

You can set a toolchain via the java extension, and Kotlin compilation tasks will use it:

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(<MAJOR_JDK_VERSION>)) // "8"
}
}

For information about setting any JDK version for KotlinCompile tasks, look through the docs about setting the JDK version with the Task
DSL.

For Gradle versions from 6.1 to 6.6, use the UsesKotlinJavaToolchain interface to set the JDK home.

Ability
to
specify
JDK
home
with
UsesKotlinJavaToolchain
interface
All Kotlin tasks that support setting the JDK via kotlinOptions now implement the UsesKotlinJavaToolchain interface. To set the JDK
home, put a path to your JDK and replace the <JDK_VERSION> placeholder:

Kotlin

project.tasks

150
.withType<UsesKotlinJavaToolchain>()
.configureEach {
it.kotlinJavaToolchain.jdk.use(
"/path/to/local/jdk",
JavaVersion.<LOCAL_JDK_VERSION>
)
}

Groovy

project.tasks
.withType(UsesKotlinJavaToolchain.class)
.configureEach {
it.kotlinJavaToolchain.jdk.use(
'/path/to/local/jdk',
JavaVersion.<LOCAL_JDK_VERSION>
)
}

Use the UsesKotlinJavaToolchain interface for Gradle versions from 6.1 to 6.6. Starting from Gradle 6.7, use the Java toolchains instead.

When using this feature, note that kapt task workers will only use process isolation mode, and the kapt.workers.isolation property will be
ignored.

Easier
way
to
explicitly
specify
Kotlin
daemon
JVM
arguments
In Kotlin 1.5.30, there's a new logic for the Kotlin daemon's JVM arguments. Each of the options in the following list overrides the ones
that came before it:

If nothing is specified, the Kotlin daemon inherits arguments from the Gradle daemon (as before). For example, in the gradle.properties
file:

org.gradle.jvmargs=-Xmx1500m -Xms=500m

If the Gradle daemon's JVM arguments have the kotlin.daemon.jvm.options system property, use it as before:

org.gradle.jvmargs=-Dkotlin.daemon.jvm.options=-Xmx1500m -Xms=500m

You can add thekotlin.daemon.jvmargs property in the gradle.properties file:

kotlin.daemon.jvmargs=-Xmx1500m -Xms=500m

You can specify arguments in the kotlin extension:

Kotlin

kotlin {
kotlinDaemonJvmArgs = listOf("-Xmx486m", "-Xms256m", "-XX:+UseParallelGC")
}

Groovy

kotlin {

151
kotlinDaemonJvmArgs = ["-Xmx486m", "-Xms256m", "-XX:+UseParallelGC"]
}

You can specify arguments for a specific task:

Kotlin

tasks
.matching { it.name == "compileKotlin" && it is CompileUsingKotlinDaemon }
.configureEach {
(this as CompileUsingKotlinDaemon).kotlinDaemonJvmArguments.set(listOf("-Xmx486m", "-Xms256m", "-
XX:+UseParallelGC"))
}

Groovy

tasks
.matching {
it.name == "compileKotlin" && it instanceof CompileUsingKotlinDaemon
}
.configureEach {
kotlinDaemonJvmArguments.set(["-Xmx1g", "-Xms512m"])
}

In this case a new Kotlin daemon instance can start on task execution. Learn more about the Kotlin daemon's interactions
with JVM arguments.

For more information about the Kotlin daemon, see the Kotlin daemon and using it with Gradle.

Standard
library
Kotlin 1.5.30 is bringing improvements to the standard library's Duration and Regex APIs:

Changing Duration.toString() output

Parsing Duration from String

Matching with Regex at a particular position

Splitting Regex to a sequence

Changing
Duration.toString()
output

The Duration API is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes. We would
appreciate hearing your feedback on it in YouTrack.

Before Kotlin 1.5.30, the Duration.toString() function would return a string representation of its argument expressed in the unit that yielded
the most compact and readable number value. From now on, it will return a string value expressed as a combination of numeric

152
components, each in its own unit. Each component is a number followed by the unit's abbreviated name: d, h, m, s. For example:

Example of function call Previous output Current output

Duration.days(45).toString() 45.0d 45d

Duration.days(1.5).toString() 36.0h 1d 12h

Duration.minutes(1230).toString() 20.5h 20h 30m

Duration.minutes(2415).toString() 40.3h 1d 16h 15m

Duration.minutes(920).toString() 920m 15h 20m

Duration.seconds(1.546).toString() 1.55s 1.546s

Duration.milliseconds(25.12).toString() 25.1ms 25.12ms

The way negative durations are represented has also been changed. A negative duration is prefixed with a minus sign (-), and if it consists
of multiple components, it is surrounded with parentheses: -12m and -(1h 30m).

Note that small durations of less than one second are represented as a single number with one of the subsecond units. For example, ms
(milliseconds), us (microseconds), or ns (nanoseconds): 140.884ms, 500us, 24ns. Scientific notation is no longer used to represent them.

If you want to express duration in a single unit, use the overloaded Duration.toString(unit, decimals) function.

We recommend using Duration.toIsoString() in certain cases, including serialization and interchange. Duration.toIsoString() uses
the stricter ISO-8601 format instead of Duration.toString().

Parsing
Duration
from
String

The Duration API is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes. We would
appreciate hearing your feedback on it in this issue.

In Kotlin 1.5.30, there are new functions in the Duration API:

parse(), which supports parsing the outputs of:

toString().

toString(unit, decimals).

153
toIsoString().

parseIsoString(), which only parses from the format produced by toIsoString().

parseOrNull() and parseIsoStringOrNull(), which behave like the functions above but return null instead of throwing
IllegalArgumentException on invalid duration formats.

Here are some examples of parse() and parseOrNull() usages:

import kotlin.time.Duration
import kotlin.time.ExperimentalTime

@ExperimentalTime
fun main() {
//sampleStart
val isoFormatString = "PT1H30M"
val defaultFormatString = "1h 30m"
val singleUnitFormatString = "1.5h"
val invalidFormatString = "1 hour 30 minutes"
println(Duration.parse(isoFormatString)) // "1h 30m"
println(Duration.parse(defaultFormatString)) // "1h 30m"
println(Duration.parse(singleUnitFormatString)) // "1h 30m"
//println(Duration.parse(invalidFormatString)) // throws exception
println(Duration.parseOrNull(invalidFormatString)) // "null"
//sampleEnd
}

And here are some examples of parseIsoString() and parseIsoStringOrNull() usages:

import kotlin.time.Duration
import kotlin.time.ExperimentalTime

@ExperimentalTime
fun main() {
//sampleStart
val isoFormatString = "PT1H30M"
val defaultFormatString = "1h 30m"
println(Duration.parseIsoString(isoFormatString)) // "1h 30m"
//println(Duration.parseIsoString(defaultFormatString)) // throws exception
println(Duration.parseIsoStringOrNull(defaultFormatString)) // "null"
//sampleEnd
}

Matching
with
Regex
at
a
particular
position

Regex.matchAt() and Regex.matchesAt() functions are Experimental. They may be dropped or changed at any time. Use them
only for evaluation purposes. We would appreciate hearing your feedback on them in YouTrack.

The new Regex.matchAt() and Regex.matchesAt() functions provide a way to check whether a regex has an exact match at a particular
position in a String or CharSequence.

matchesAt() returns a boolean result:

fun main(){
//sampleStart
val releaseText = "Kotlin 1.5.30 is released!"
// regular expression: one digit, dot, one digit, dot, one or more digits

154
val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()
println(versionRegex.matchesAt(releaseText, 0)) // "false"
println(versionRegex.matchesAt(releaseText, 7)) // "true"
//sampleEnd
}

matchAt() returns the match if one is found or null if one isn't:

fun main(){
//sampleStart
val releaseText = "Kotlin 1.5.30 is released!"
val versionRegex = "\\d[.]\\d[.]\\d+".toRegex()
println(versionRegex.matchAt(releaseText, 0)) // "null"
println(versionRegex.matchAt(releaseText, 7)?.value) // "1.5.30"
//sampleEnd
}

Splitting
Regex
to
a
sequence

Regex.splitToSequence() and CharSequence.splitToSequence(Regex) functions are Experimental. They may be dropped or


changed at any time. Use them only for evaluation purposes. We would appreciate hearing your feedback on them in YouTrack.

The new Regex.splitToSequence() function is a lazy counterpart of split(). It splits the string around matches of the given regex, but it
returns the result as a Sequence so that all operations on this result are executed lazily.

fun main(){
//sampleStart
val colorsText = "green, red , brown&blue, orange, pink&green"
val regex = "[,\\s]+".toRegex()
val mixedColor = regex.splitToSequence(colorsText)
.onEach { println(it) }
.firstOrNull { it.contains('&') }
println(mixedColor) // "brown&blue"
//sampleEnd
}

A similar function was also added to CharSequence:

val mixedColor = colorsText.splitToSequence(regex)

Serialization
1.3.0-RC
kotlinx.serialization 1.3.0-RC is here with new JSON serialization capabilities:

Java IO streams serialization

Property-level control over default values

An option to exclude null values from serialization

Custom class discriminators in polymorphic serialization

Learn more in the changelog.

155
What's
new
in
Kotlin
1.5.20
Release date: 24 June 2021

Kotlin 1.5.20 has fixes for issues discovered in the new features of 1.5.0, and it also includes various tooling improvements.

You can find an overview of the changes in the release blog post and this video:

Gif

Watch video online.

Kotlin/JVM
Kotlin 1.5.20 is receiving the following updates on the JVM platform:

String concatenation via invokedynamic

Support for JSpecify nullness annotations

Support for calling Java's Lombok-generated methods within modules that have Kotlin and Java code

String
concatenation
via
invokedynamic
Kotlin 1.5.20 compiles string concatenations into dynamic invocations (invokedynamic) on JVM 9+ targets, thereby keeping up with
modern Java versions. More precisely, it uses StringConcatFactory.makeConcatWithConstants() for string concatenation.

To switch back to concatenation via StringBuilder.append() used in previous versions, add the compiler option -Xstring-concat=inline.

Learn how to add compiler options in Gradle, Maven, and the command-line compiler.

Support
for
JSpecify
nullness
annotations
The Kotlin compiler can read various types of nullability annotations to pass nullability information from Java to Kotlin. Version 1.5.20
introduces support for the JSpecify project, which includes the standard unified set of Java nullness annotations.

With JSpecify, you can provide more detailed nullability information to help Kotlin keep null-safety interoperating with Java. You can set
default nullability for the declaration, package, or module scope, specify parametric nullability, and more. You can find more details about

156
this in the JSpecify user guide.

Here is the example of how Kotlin can handle JSpecify annotations:

// JavaClass.java
import *;

@NullMarked
public class JavaClass {
public String notNullableString() { return ""; }
public @Nullable String nullableString() { return ""; }
}

// Test.kt
fun kotlinFun() = with(JavaClass()) {
notNullableString().length // OK
nullableString().length // Warning: receiver nullability mismatch
}

In 1.5.20, all nullability mismatches according to the JSpecify-provided nullability information are reported as warnings. Use the -Xjspecify-
annotations=strict and -Xtype-enhancement-improvements-strict-mode compiler options to enable strict mode (with error reporting) when
working with JSpecify. Please note that the JSpecify project is under active development. Its API and implementation can change
significantly at any time.

Learn more about null-safety and platform types.

Support
for
calling
Java's
Lombok-generated
methods
within
modules
that
have
Kotlin
and
Java
code

The Lombok compiler plugin is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes. We
would appreciate your feedback on it in YouTrack.

Kotlin 1.5.20 introduces an experimental Lombok compiler plugin. This plugin makes it possible to generate and use Java's Lombok
declarations within modules that have Kotlin and Java code. Lombok annotations work only in Java sources and are ignored if you use
them in Kotlin code.

The plugin supports the following annotations:

@Getter, @Setter

@NoArgsConstructor, @RequiredArgsConstructor, and @AllArgsConstructor

@Data

@With

@Value

We're continuing to work on this plugin. To find out the detailed current state, visit the Lombok compiler plugin's README.

Currently, we don't have plans to support the @Builder annotation. However, we can consider this if you vote for @Builder in YouTrack.

Learn how to configure the Lombok compiler plugin.

157
Kotlin/Native
Kotlin/Native 1.5.20 offers a preview of the new feature and the tooling improvements:

Opt-in export of KDoc comments to generated Objective-C headers

Compiler bug fixes

Improved performance of Array.copyInto() inside one array

Opt-in
export
of
KDoc
comments
to
generated
Objective-C
headers

The ability to export KDoc comments to generated Objective-C headers is Experimental. It may be dropped or changed at any
time. Opt-in is required (see the details below), and you should use it only for evaluation purposes. We would appreciate your
feedback on it in YouTrack.

You can now set the Kotlin/Native compiler to export the documentation comments (KDoc) from Kotlin code to the Objective-C
frameworks generated from it, making them visible to the frameworks' consumers.

For example, the following Kotlin code with KDoc:

/**
* Prints the sum of the arguments.
* Properly handles the case when the sum doesn't fit in 32-bit integer.
*/
fun printSum(a: Int, b: Int) = println(a.toLong() + b)

produces the following Objective-C headers:

/**
* Prints the sum of the arguments.
* Properly handles the case when the sum doesn't fit in 32-bit integer.
*/
+ (void)printSumA:(int32_t)a b:(int32_t)b __attribute__((swift_name("printSum(a:b:)")));

This also works well with Swift.

To try out this ability to export KDoc comments to Objective-C headers, use the -Xexport-kdoc compiler option. Add the following lines to
build.gradle(.kts) of the Gradle projects you want to export comments from:

Kotlin

kotlin {
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
compilations.get("main").kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"
}
}

Groovy

kotlin {
targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget) {
compilations.get("main").kotlinOptions.freeCompilerArgs += "-Xexport-kdoc"

158
}
}

We would be very grateful if you would share your feedback with us using this YouTrack ticket.

Compiler
bug
fixes
The Kotlin/Native compiler has received multiple bug fixes in 1.5.20. You can find the complete list in the changelog.

There is an important bug fix that affects compatibility: in previous versions, string constants that contained incorrect UTF surrogate pairs
were losing their values during compilation. Now such values are preserved. Application developers can safely update to 1.5.20 – nothing
will break. However, libraries compiled with 1.5.20 are incompatible with earlier compiler versions. See this YouTrack issue for details.

Improved
performance
of
Array.copyInto()
inside
one
array
We've improved the way Array.copyInto() works when its source and destination are the same array. Now such operations finish up to 20
times faster (depending on the number of objects being copied) due to memory management optimizations for this use case.

Kotlin/JS
With 1.5.20, we're publishing a guide that will help you migrate your projects to the new IR-based backend for Kotlin/JS.

Migration
guide
for
the
JS
IR
backend
The new migration guide for the JS IR backend identifies issues you may encounter during migration and provides solutions for them. If
you find any issues that aren't covered in the guide, please report them to our issue tracker.

Gradle
Kotlin 1.5.20 introduces the following features that can improve the Gradle experience:

Caching for annotation processors classloaders in kapt

Deprecation of the kotlin.parallel.tasks.in.project build property

Caching
for
annotation
processors'
classloaders
in
kapt

Caching for annotation processors' classloaders in kapt is Experimental. It may be dropped or changed at any time. Use it only
for evaluation purposes. We would appreciate your feedback on it in YouTrack.

There is now a new experimental feature that makes it possible to cache the classloaders of annotation processors in kapt. This feature
can increase the speed of kapt for consecutive Gradle runs.

To enable this feature, use the following properties in your gradle.properties file:

# positive value will enable caching


# use the same value as the number of modules that use kapt
kapt.classloaders.cache.size=5

159
# disable for caching to work
kapt.include.compile.classpath=false

Learn more about kapt.

Deprecation
of
the
kotlin.parallel.tasks.in.project
build
property
With this release, Kotlin parallel compilation is controlled by the Gradle parallel execution flag --parallel. Using this flag, Gradle executes
tasks concurrently, increasing the speed of compiling tasks and utilizing the resources more efficiently.

You no longer need to use the kotlin.parallel.tasks.in.project property. This property has been deprecated and will be removed in the next
major release.

Standard
library
Kotlin 1.5.20 changes the platform-specific implementations of several functions for working with characters and as a result brings
unification across platforms:

Support for all Unicode digits in Char.digitToInt() for Kotlin/Native and Kotlin/JS.

Unification of Char.isLowerCase()/isUpperCase() implementations across platforms.

Support
for
all
Unicode
digits
in
Char.digitToInt()
in
Kotlin/Native
and
Kotlin/JS
Char.digitToInt() returns the numeric value of the decimal digit that the character represents. Before 1.5.20, the function supported all
Unicode digit characters only for Kotlin/JVM: implementations on the Native and JS platforms supported only ASCII digits.

From now, both with Kotlin/Native and Kotlin/JS, you can call Char.digitToInt() on any Unicode digit character and get its numeric
representation.

fun main() {
//sampleStart
val ten = '\u0661'.digitToInt() + '\u0039'.digitToInt() // ARABIC-INDIC DIGIT ONE + DIGIT NINE
println(ten)
//sampleEnd
}

Unification
of
Char.isLowerCase()/isUpperCase()
implementations
across
platforms
The functions Char.isUpperCase() and Char.isLowerCase() return a boolean value depending on the case of the character. For Kotlin/JVM,
the implementation checks both the General_Category and the Other_Uppercase/Other_Lowercase Unicode properties.

Prior to 1.5.20, implementations for other platforms worked differently and considered only the general category. In 1.5.20,
implementations are unified across platforms and use both properties to determine the character case:

fun main() {
//sampleStart
val latinCapitalA = 'A' // has "Lu" general category
val circledLatinCapitalA = 'Ⓐ' // has "Other_Uppercase" property
println(latinCapitalA.isUpperCase() && circledLatinCapitalA.isUpperCase())
//sampleEnd
}

160
What's
new
in
Kotlin
1.5.0
Release date: 5 May 2021

Kotlin 1.5.0 introduces new language features, stable IR-based JVM compiler backend, performance improvements, and evolutionary
changes such as stabilizing experimental features and deprecating outdated ones.

You can also find an overview of the changes in the release blog post.

Language
features
Kotlin 1.5.0 brings stable versions of the new language features presented for preview in 1.4.30:

JVM records support

Sealed interfaces and sealed class improvements

Inline classes

Detailed descriptions of these features are available in this blog post and the corresponding pages of Kotlin documentation.

JVM
records
support
Java is evolving fast, and to make sure Kotlin remains interoperable with it, we've introduced support for one of its latest features – record
classes.

Kotlin's support for JVM records includes bidirectional interoperability:

In Kotlin code, you can use Java record classes like you would use typical classes with properties.

To use a Kotlin class as a record in Java code, make it a data class and mark it with the @JvmRecord annotation.

@JvmRecord
data class User(val name: String, val age: Int)

Learn more about using JVM records in Kotlin.

Gif

161
Watch video online.

Sealed
interfaces
Kotlin interfaces can now have the sealed modifier, which works on interfaces in the same way it works on classes: all implementations of
a sealed interface are known at compile time.

sealed interface Polygon

You can rely on that fact, for example, to write exhaustive when expressions.

fun draw(polygon: Polygon) = when (polygon) {


is Rectangle -> // ...
is Triangle -> // …
// else is not needed - all possible implementations are covered
}

Additionally, sealed interfaces enable more flexible restricted class hierarchies because a class can directly inherit more than one sealed
interface.

class FilledRectangle: Polygon, Fillable

Learn more about sealed interfaces.

Gif

Watch video online.

Package-wide
sealed
class
hierarchies
Sealed classes can now have subclasses in all files of the same compilation unit and the same package. Previously, all subclasses had to
appear in the same file.

Direct subclasses may be top-level or nested inside any number of other named classes, named interfaces, or named objects.

The subclasses of a sealed class must have a name that is properly qualified – they cannot be local or anonymous objects.

162
Learn more about sealed class hierarchies.

Inline
classes
Inline classes are a subset of value-based classes that only hold values. You can use them as wrappers for a value of a certain type
without the additional overhead that comes from using memory allocations.

Inline classes can be declared with the value modifier before the name of the class:

value class Password(val s: String)

The JVM backend also requires a special @JvmInline annotation:

@JvmInline
value class Password(val s: String)

The inline modifier is now deprecated with a warning.

Learn more about inline classes.

Gif

Watch video online.

Kotlin/JVM
Kotlin/JVM has received a number of improvements, both internal and user-facing. Here are the most notable among them:

Stable JVM IR backend

New default JVM target: 1.8

SAM adapters via invokedynamic

Lambdas via invokedynamic

Deprecation of @JvmDefault and old Xjvm-default modes

163
Improvements to handling nullability annotations

Stable
JVM
IR
backend
The IR-based backend for the Kotlin/JVM compiler is now Stable and enabled by default.

Starting from Kotlin 1.4.0, early versions of the IR-based backend were available for preview, and it has now become the default for
language version 1.5. The old backend is still used by default for earlier language versions.

You can find more details about the benefits of the IR backend and its future development in this blog post.

If you need to use the old backend in Kotlin 1.5.0, you can add the following lines to the project's configuration file:

In Gradle:

Kotlin

tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile> {
kotlinOptions.useOldBackend = true
}

Groovy

tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) {
kotlinOptions.useOldBackend = true
}

In Maven:

<configuration>
<args>
<arg>-Xuse-old-backend</arg>
</args>
</configuration>

New
default
JVM
target:
1.8
The default target version for Kotlin/JVM compilations is now 1.8. The 1.6 target is deprecated.

If you need a build for JVM 1.6, you can still switch to this target. Learn how:

in Gradle

in Maven

in the command-line compiler

SAM
adapters
via
invokedynamic
Kotlin 1.5.0 now uses dynamic invocations (invokedynamic) for compiling SAM (Single Abstract Method) conversions:

Over any expression if the SAM type is a Java interface

Over lambda if the SAM type is a Kotlin functional interface

164
The new implementation uses LambdaMetafactory.metafactory() and auxiliary wrapper classes are no longer generated during
compilation. This decreases the size of the application's JAR, which improves the JVM startup performance.

To roll back to the old implementation scheme based on anonymous class generation, add the compiler option -Xsam-conversions=class.

Learn how to add compiler options in Gradle, Maven, and the command-line compiler.

Lambdas
via
invokedynamic

Compiling plain Kotlin lambdas into invokedynamic is Experimental. It may be dropped or changed at any time. Opt-in is
required (see details below), and you should use it only for evaluation purposes. We would appreciate hearing your feedback on
it in YouTrack.

Kotlin 1.5.0 is introducing experimental support for compiling plain Kotlin lambdas (which are not converted to an instance of a functional
interface) into dynamic invocations (invokedynamic). The implementation produces lighter binaries by using
LambdaMetafactory.metafactory(), which effectively generates the necessary classes at runtime. Currently, it has three limitations
compared to ordinary lambda compilation:

A lambda compiled into invokedynamic is not serializable.

Calling toString() on such a lambda produces a less readable string representation.

Experimental reflect API does not support lambdas created with LambdaMetafactory.

To try this feature, add the -Xlambdas=indy compiler option. We would be grateful if you could share your feedback on it using this
YouTrack ticket.

Learn how to add compiler options in Gradle, Maven, and command-line compiler.

Deprecation
of
@JvmDefault
and
old
Xjvm-default
modes
Prior to Kotlin 1.4.0, there was the @JvmDefault annotation along with -Xjvm-default=enable and -Xjvm-default=compatibility modes. They
served to create the JVM default method for any particular non-abstract member in the Kotlin interface.

In Kotlin 1.4.0, we introduced the new Xjvm-default modes, which switch on default method generation for the whole project.

In Kotlin 1.5.0, we are deprecating @JvmDefault and the old Xjvm-default modes: -Xjvm-default=enable and -Xjvm-default=compatibility.

Learn more about default methods in the Java interop.

Improvements
to
handling
nullability
annotations
Kotlin supports handling type nullability information from Java with nullability annotations. Kotlin 1.5.0 introduces a number of
improvements for the feature:

It reads nullability annotations on type arguments in compiled Java libraries that are used as dependencies.

It supports nullability annotations with the TYPE_USE target for:

Arrays

Varargs

Fields

165
Type parameters and their bounds

Type arguments of base classes and interfaces

If a nullability annotation has multiple targets applicable to a type, and one of these targets is TYPE_USE, then TYPE_USE is preferred.
For example, the method signature @Nullable String[] f() becomes fun f(): Array<String?>! if @Nullable supports both TYPE_USE and
METHODas targets.

For these newly supported cases, using the wrong type nullability when calling Java from Kotlin produces warnings. Use the -Xtype-
enhancement-improvements-strict-mode compiler option to enable strict mode for these cases (with error reporting).

Learn more about null-safety and platform types.

Kotlin/Native
Kotlin/Native is now more performant and stable. The notable changes are:

Performance improvements

Deactivation of the memory leak checker

Performance
improvements
In 1.5.0, Kotlin/Native is receiving a set of performance improvements that speed up both compilation and execution.

Compiler caches are now supported in debug mode for linuxX64 (only on Linux hosts) and iosArm64 targets. With compiler caches
enabled, most debug compilations complete much faster, except for the first one. Measurements showed about a 200% speed increase
on our test projects.

To use compiler caches for new targets, opt in by adding the following lines to the project's gradle.properties:

For linuxX64: kotlin.native.cacheKind.linuxX64=static

For iosArm64: kotlin.native.cacheKind.iosArm64=static

If you encounter any issues after enabling the compiler caches, please report them to our issue tracker YouTrack.

Other improvements speed up the execution of Kotlin/Native code:

Trivial property accessors are inlined.

trimIndent() on string literals is evaluated during the compilation.

Deactivation
of
the
memory
leak
checker
The built-in Kotlin/Native memory leak checker has been disabled by default.

It was initially designed for internal use, and it is able to find leaks only in a limited number of cases, not all of them. Moreover, it later
turned out to have issues that can cause application crashes. So we've decided to turn off the memory leak checker.

The memory leak checker can still be useful for certain cases, for example, unit testing. For these cases, you can enable it by adding the
following line of code:

Platform.isMemoryLeakCheckerActive = true

Note that enabling the checker for the application runtime is not recommended.

166
Kotlin/JS
Kotlin/JS is receiving evolutionary changes in 1.5.0. We're continuing our work on moving the JS IR compiler backend towards stable and
shipping other updates:

Upgrade of webpack to version 5

Frameworks and libraries for the IR compiler

Upgrade
to
webpack
5
The Kotlin/JS Gradle plugin now uses webpack 5 for browser targets instead of webpack 4. This is a major webpack upgrade that brings
incompatible changes. If you're using a custom webpack configuration, be sure to check the webpack 5 release notes.

Learn more about bundling Kotlin/JS projects with webpack.

Frameworks
and
libraries
for
the
IR
compiler

The Kotlin/JS IR compiler is in Alpha. It may change incompatibly and require manual migration in the future. We would
appreciate your feedback on it in YouTrack.

Along with working on the IR-based backend for Kotlin/JS compiler, we encourage and help library authors to build their projects in both
mode. This means they are able to produce artifacts for both Kotlin/JS compilers, therefore growing the ecosystem for the new compiler.

Many well-known frameworks and libraries are already available for the IR backend: KVision, fritz2, doodle, and others. If you're using
them in your project, you can already build it with the IR backend and see the benefits it brings.

If you're writing your own library, compile it in the 'both' mode so that your clients can also use it with the new compiler.

Kotlin
Multiplatform
In Kotlin 1.5.0, choosing a testing dependency for each platform has been simplified and it is now done automatically by the Gradle
plugin.

A new API for getting a char category is now available in multiplatform projects.

Standard
library
The standard library has received a range of changes and improvements, from stabilizing experimental parts to adding new features:

Stable unsigned integer types

Stable locale-agnostic API for uppercase/lowercase text

Stable Char-to-integer conversion API

Stable Path API

Floored division and the mod operator

Duration API changes

167
New API for getting a char category now available in multiplatform code

New collections function firstNotNullOf()

Strict version of String?.toBoolean()

You can learn more about the standard library changes in this blog post.

Gif

Watch video online.

Stable
unsigned
integer
types
The UInt, ULong, UByte, UShort unsigned integer types are now Stable. The same goes for operations on these types, ranges, and
progressions of them. Unsigned arrays and operations on them remain in Beta.

Learn more about unsigned integer types.

Stable
locale-agnostic
API
for
upper/lowercasing
text
This release brings a new locale-agnostic API for uppercase/lowercase text conversion. It provides an alternative to the toLowerCase(),
toUpperCase(), capitalize(), and decapitalize() API functions, which are locale-sensitive. The new API helps you avoid errors due to different
locale settings.

Kotlin 1.5.0 provides the following fully Stable alternatives:

For String functions:

Earlier versions 1.5.0 alternative

String.toUpperCase() String.uppercase()

String.toLowerCase() String.lowercase()

168
Earlier versions 1.5.0 alternative

String.capitalize() String.replaceFirstChar { it.uppercase() }

String.decapitalize() String.replaceFirstChar { it.lowercase() }

For Char functions:

Earlier versions 1.5.0 alternative

Char.toUpperCase() Char.uppercaseChar(): Char


Char.uppercase(): String

Char.toLowerCase() Char.lowercaseChar(): Char


Char.lowercase(): String

Char.toTitleCase() Char.titlecaseChar(): Char


Char.titlecase(): String

For Kotlin/JVM, there are also overloaded uppercase(), lowercase(), and titlecase() functions with an explicit Locale parameter.

The old API functions are marked as deprecated and will be removed in a future release.

See the full list of changes to the text processing functions in KEEP.

Stable
char-to-integer
conversion
API
Starting from Kotlin 1.5.0, new char-to-code and char-to-digit conversion functions are Stable. These functions replace the current API
functions, which were often confused with the similar string-to-Int conversion.

The new API removes this naming confusion, making the code behavior more transparent and unambiguous.

This release introduces Char conversions that are divided into the following sets of clearly named functions:

Functions to get the integer code of Char and to construct Char from the given code:

fun Char(code: Int): Char


fun Char(code: UShort): Char
val Char.code: Int

Functions to convert Char to the numeric value of the digit it represents:

fun Char.digitToInt(radix: Int): Int

169
fun Char.digitToIntOrNull(radix: Int): Int?

An extension function for Int to convert the non-negative single digit it represents to the corresponding Char representation:

fun Int.digitToChar(radix: Int): Char

The old conversion APIs, including Number.toChar() with its implementations (all except Int.toChar()) and Char extensions for conversion
to a numeric type, like Char.toInt(), are now deprecated.

Learn more about the char-to-integer conversion API in KEEP.

Stable
Path
API
The experimental Path API with extensions for java.nio.file.Path is now Stable.

// construct path with the div (/) operator


val baseDir = Path("/base")
val subDir = baseDir / "subdirectory"

// list files in a directory


val kotlinFiles: List<Path> = Path("/home/user").listDirectoryEntries("*.kt")

Learn more about the Path API.

Floored
division
and
the
mod
operator
New operations for modular arithmetics have been added to the standard library:

floorDiv() returns the result of floored division. It is available for integer types.

mod() returns the remainder of floored division (modulus). It is available for all numeric types.

These operations look quite similar to the existing division of integers and rem() function (or the %operator), but they work differently on
negative numbers:

a.floorDiv(b) differs from a regular / in that floorDiv rounds the result down (towards the lesser integer), whereas / truncates the result to
the integer closer to 0.

a.mod(b) is the difference between a and a.floorDiv(b) * b. It's either zero or has the same sign as b, while a % b can have a different
one.

fun main() {
//sampleStart
println("Floored division -5/3: ${(-5).floorDiv(3)}")
println( "Modulus: ${(-5).mod(3)}")

println("Truncated division -5/3: ${-5 / 3}")
println( "Remainder: ${-5 % 3}")
//sampleEnd
}

Duration
API
changes

170
The Duration API is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes. We would
appreciate hearing your feedback on it in YouTrack.

There is an experimental Duration class for representing duration amounts in different time units. In 1.5.0, the Duration API has received
the following changes:

Internal value representation now uses Long instead of Double to provide better precision.

There is a new API for conversion to a particular time unit in Long. It comes to replace the old API, which operates with Double values
and is now deprecated. For example, Duration.inWholeMinutes returns the value of the duration expressed as Long and replaces
Duration.inMinutes.

There are new companion functions for constructing a Duration from a number. For example, Duration.seconds(Int) creates a Duration
object representing an integer number of seconds. Old extension properties like Int.seconds are now deprecated.

import kotlin.time.Duration
import kotlin.time.ExperimentalTime

@ExperimentalTime
fun main() {
//sampleStart
val duration = Duration.milliseconds(120000)
println("There are ${duration.inWholeSeconds} seconds in ${duration.inWholeMinutes} minutes")
//sampleEnd
}

New
API
for
getting
a
char
category
now
available
in
multiplatform
code
Kotlin 1.5.0 introduces the new API for getting a character's category according to Unicode in multiplatform projects. Several functions are
now available in all the platforms and in the common code.

Functions for checking whether a char is a letter or a digit:

Char.isDigit()

Char.isLetter()

Char.isLetterOrDigit()

fun main() {
//sampleStart
val chars = listOf('a', '1', '+')
val (letterOrDigitList, notLetterOrDigitList) = chars.partition { it.isLetterOrDigit() }
println(letterOrDigitList) // [a, 1]
println(notLetterOrDigitList) // [+]
//sampleEnd
}

Functions for checking the case of a char:

Char.isLowerCase()

Char.isUpperCase()

Char.isTitleCase()

fun main() {

171
//sampleStart
val chars = listOf('Dž', 'Lj', 'Nj', 'Dz', '1', 'A', 'a', '+')
val (titleCases, notTitleCases) = chars.partition { it.isTitleCase() }
println(titleCases) // [Dž, Lj, Nj, Dz]
println(notTitleCases) // [1, A, a, +]
//sampleEnd
}

Some other functions:

Char.isDefined()

Char.isISOControl()

The property Char.category and its return type enum class CharCategory, which indicates a char's general category according to Unicode,
are now also available in multiplatform projects.

Learn more about characters.

New
collections
function
firstNotNullOf()
The new firstNotNullOf() and firstNotNullOfOrNull() functions combine mapNotNull() with first() or firstOrNull(). They map the original
collection with the custom selector function and return the first non-null value. If there is no such value, firstNotNullOf() throws an
exception, and firstNotNullOfOrNull() returns null.

fun main() {
//sampleStart
val data = listOf("Kotlin", "1.5")
println(data.firstNotNullOf(String::toDoubleOrNull))
println(data.firstNotNullOfOrNull(String::toIntOrNull))
//sampleEnd
}

Strict
version
of
String?.toBoolean()
Two new functions introduce case-sensitive strict versions of the existing String?.toBoolean():

String.toBooleanStrict() throws an exception for all inputs except the literals true and false.

String.toBooleanStrictOrNull() returns null for all inputs except the literals true and false.

fun main() {
//sampleStart
println("true".toBooleanStrict())
println("1".toBooleanStrictOrNull())
// println("1".toBooleanStrict()) // Exception
//sampleEnd
}

kotlin-test
library
The kotlin-test library introduces some new features:

Simplified test dependencies usage in multiplatform projects

Automatic selection of a testing framework for Kotlin/JVM source sets

172
Assertion function updates

Simplified
test
dependencies
usage
in
multiplatform
projects
Now you can use the kotlin-test dependency to add dependencies for testing in the commonTest source set, and the Gradle plugin will
infer the corresponding platform dependencies for each test source set:

kotlin-test-junit for JVM source sets, see automatic choice of a testing framework for Kotlin/JVM source sets

kotlin-test-js for Kotlin/JS source sets

kotlin-test-common and kotlin-test-annotations-common for common source sets

No extra artifact for Kotlin/Native source sets

Additionally, you can use the kotlin-test dependency in any shared or platform-specific source set.

An existing kotlin-test setup with explicit dependencies will continue to work both in Gradle and in Maven.

Learn more about setting dependencies on test libraries.

Automatic
selection
of
a
testing
framework
for
Kotlin/JVM
source
sets
The Gradle plugin now chooses and adds a dependency on a testing framework automatically. All you need to do is add the dependency
kotlin-test in the common source set.

Gradle uses JUnit 4 by default. Therefore, the kotlin("test") dependency resolves to the variant for JUnit 4, namely kotlin-test-junit:

Kotlin

kotlin {
sourceSets {
val commonTest by getting {
dependencies {
implementation(kotlin("test")) // This brings the dependency
// on JUnit 4 transitively
}
}
}
}

Groovy

kotlin {
sourceSets {
commonTest {
dependencies {
implementation kotlin("test") // This brings the dependency
// on JUnit 4 transitively
}
}
}
}

You can choose JUnit 5 or TestNG by calling useJUnitPlatform() or useTestNG() in the test task:

tasks {

173
test {
// enable TestNG support
useTestNG()
// or
// enable JUnit Platform (a.k.a. JUnit 5) support
useJUnitPlatform()
}
}

You can disable automatic testing framework selection by adding the line kotlin.test.infer.jvm.variant=false to the project's
gradle.properties.

Learn more about setting dependencies on test libraries.

Assertion
function
updates
This release brings new assertion functions and improves the existing ones.

The kotlin-test library now has the following features:

Checking the type of a value

You can use the new assertIs<T> and assertIsNot<T> to check the type of a value:

@Test
fun testFunction() {
val s: Any = "test"
assertIs<String>(s) // throws AssertionError mentioning the actual type of s if the assertion fails
// can now print s.length because of contract in assertIs
println("${s.length}")
}

Because of type erasure, this assert function only checks whether the value is of the List type in the following example and doesn't
check whether it's a list of the particular String element type: assertIs<List<String>>(value).

Comparing the container content for arrays, sequences, and arbitrary iterables

There is a new set of overloaded assertContentEquals() functions for comparing content for different collections that don't implement
structural equality:

@Test
fun test() {
val expectedArray = arrayOf(1, 2, 3)
val actualArray = Array(3) { it + 1 }
assertContentEquals(expectedArray, actualArray)
}

New overloads to assertEquals() and assertNotEquals() for Double and Float numbers

There are new overloads for the assertEquals() function that make it possible to compare two Double or Float numbers with absolute
precision. The precision value is specified as the third parameter of the function:

@Test
fun test() {
val x = sin(PI)

// precision parameter
val tolerance = 0.000001

assertEquals(0.0, x, tolerance)

174
}

New functions for checking the content of collections and elements

You can now check whether the collection or element contains something with the assertContains() function. You can use it with Kotlin
collections and elements that have the contains() operator, such as IntRange, String, and others:

@Test
fun test() {
val sampleList = listOf<String>("sample", "sample2")
val sampleString = "sample"
assertContains(sampleList, sampleString) // element in collection
assertContains(sampleString, "amp") // substring in string
}

assertTrue(), assertFalse(), expect() functions are now inline

From now on, you can use these as inline functions, so it's possible to call suspend functions inside a lambda expression:

@Test
fun test() = runBlocking<Unit> {
val deferred = async { "Kotlin is nice" }
assertTrue("Kotlin substring should be present") {
deferred.await() .contains("Kotlin")
}
}

kotlinx
libraries
Along with Kotlin 1.5.0, we are releasing new versions of the kotlinx libraries:

kotlinx.coroutines 1.5.0-RC

kotlinx.serialization 1.2.1

kotlinx-datetime 0.2.0

Coroutines
1.5.0-RC
kotlinx.coroutines 1.5.0-RC is here with:

New channels API

Stable reactive integrations

And more

Starting with Kotlin 1.5.0, experimental coroutines are disabled and the -Xcoroutines=experimental flag is no longer supported.

Learn more in the changelog and the kotlinx.coroutines 1.5.0 release blog post.

175
Gif

Watch video online.

Serialization
1.2.1
kotlinx.serialization 1.2.1 is here with:

Improvements to JSON serialization performance

Support for multiple names in JSON serialization

Experimental .proto schema generation from @Serializable classes

And more

Learn more in the changelog and the kotlinx.serialization 1.2.1 release blog post.

Gif

Watch video online.

176
dateTime
0.2.0
kotlinx-datetime 0.2.0 is here with:

@Serializable Datetime objects

Normalized API of DateTimePeriod and DatePeriod

And more

Learn more in the changelog and the kotlinx-datetime 0.2.0 release blog post.

Migrating
to
Kotlin
1.5.0
IntelliJ IDEA and Android Studio will suggest updating the Kotlin plugin to 1.5.0 once it is available.

To migrate existing projects to Kotlin 1.5.0, just change the Kotlin version to 1.5.0 and re-import your Gradle or Maven project. Learn how
to update to Kotlin 1.5.0.

To start a new project with Kotlin 1.5.0, update the Kotlin plugin and run the Project Wizard from File | New | Project.

The new command-line compiler is available for downloading on the GitHub release page.

Kotlin 1.5.0 is a feature release and therefore can bring incompatible changes to the language. Find the detailed list of such changes in the
Compatibility Guide for Kotlin 1.5.

What's
new
in
Kotlin
1.4.30
Release date: 3 February 2021

Kotlin 1.4.30 offers preview versions of new language features, promotes the new IR backend of the Kotlin/JVM compiler to Beta, and
ships various performance and functional improvements.

You can also learn about new features in this blog post.

Language
features
Kotlin 1.5.0 is going to deliver new language features – JVM records support, sealed interfaces, and Stable inline classes. In Kotlin 1.4.30,
you can try these features and improvements in preview mode. We would be very grateful if you share your feedback with us in the
corresponding YouTrack tickets, as that will allow us to address it before the release of 1.5.0.

JVM records support

Sealed interfaces and sealed class improvements

Improved inline classes

To enable these language features and improvements in preview mode, you need to opt in by adding specific compiler options. See the
sections below for details.

Learn more about the new features preview in this blog post.

JVM
records
support

177
The JVM records feature is Experimental. It may be dropped or changed at any time. Opt-in is required (see the details below),
and you should use it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

The JDK 16 release includes plans to stabilize a new Java class type called record. To provide all the benefits of Kotlin and maintain its
interoperability with Java, Kotlin is introducing experimental record class support.

You can use record classes that are declared in Java just like classes with properties in Kotlin. No additional steps are required.

Starting with 1.4.30, you can declare the record class in Kotlin using the @JvmRecord annotation for a data class:

@JvmRecord
data class User(val name: String, val age: Int)

To try the preview version of JVM records, add the compiler options -Xjvm-enable-preview and -language-version 1.5.

We're continuing to work on JVM records support, and we would be very grateful if you would share your feedback with us using this
YouTrack ticket.

Learn more about implementation, restrictions, and the syntax in KEEP.

Sealed
interfaces

Sealed interfaces are Experimental. They may be dropped or changed at any time. Opt-in is required (see the details below), and
you should use them only for evaluation purposes. We would appreciate your feedback on them in YouTrack.

In Kotlin 1.4.30, we're shipping the prototype of sealed interfaces. They complement sealed classes and make it possible to build more
flexible restricted class hierarchies.

They can serve as "internal" interfaces that cannot be implemented outside the same module. You can rely on that fact, for example, to
write exhaustive when expressions.

sealed interface Polygon

class Rectangle(): Polygon


class Triangle(): Polygon

// when() is exhaustive: no other polygon implementations can appear


// after the module is compiled
fun draw(polygon: Polygon) = when (polygon) {
is Rectangle -> // ...
is Triangle -> // ...
}

Another use-case: with sealed interfaces, you can inherit a class from two or more sealed superclasses.

sealed interface Fillable {


fun fill()
}
sealed interface Polygon {
val vertices: List<Point>
}

178
class Rectangle(override val vertices: List<Point>): Fillable, Polygon {
override fun fill() { /*...*/ }
}

To try the preview version of sealed interfaces, add the compiler option -language-version 1.5. Once you switch to this version, you'll be
able to use the sealed modifier on interfaces. We would be very grateful if you would share your feedback with us using this YouTrack
ticket.

Learn more about sealed interfaces.

Package-wide
sealed
class
hierarchies

Package-wide hierarchies of sealed classes are Experimental. They may be dropped or changed at any time. Opt-in is required
(see the details below), and you should use them only for evaluation purposes. We would appreciate your feedback on them in
YouTrack.

Sealed classes can now form more flexible hierarchies. They can have subclasses in all files of the same compilation unit and the same
package. Previously, all subclasses had to appear in the same file.

Direct subclasses may be top-level or nested inside any number of other named classes, named interfaces, or named objects. The
subclasses of a sealed class must have a name that is properly qualified – they cannot be local nor anonymous objects.

To try package-wide hierarchies of sealed classes, add the compiler option -language-version 1.5. We would be very grateful if you would
share your feedback with us using this YouTrack ticket.

Learn more about package-wide hierarchies of sealed classes.

Improved
inline
classes

Inline value classes are in Beta. They are almost stable, but migration steps may be required in the future. We'll do our best to
minimize any changes you have to make. We would appreciate your feedback on the inline classes feature in YouTrack.

Kotlin 1.4.30 promotes inline classes to Beta and brings the following features and improvements to them:

Since inline classes are value-based, you can define them using the value modifier. The inline and value modifiers are now equivalent to
each other. In future Kotlin versions, we're planning to deprecate the inline modifier.

From now on, Kotlin requires the @JvmInline annotation before a class declaration for the JVM backend:

inline class Name(private val s: String)

value class Name(private val s: String)

// For JVM backends


@JvmInline
value class Name(private val s: String)

Inline classes can have init blocks. You can add code to be executed right after the class is instantiated:

@JvmInline

179
value class Negative(val x: Int) {
init {
require(x < 0) { }
}
}

Calling functions with inline classes from Java code: before Kotlin 1.4.30, you couldn't call functions that accept inline classes from
Java because of mangling. From now on, you can disable mangling manually. To call such functions from Java code, you should add
the @JvmName annotation before the function declaration:

inline class UInt(val x: Int)

fun compute(x: Int) { }

@JvmName("computeUInt")
fun compute(x: UInt) { }

In this release, we've changed the mangling scheme for functions to fix the incorrect behavior. These changes led to ABI changes.

Starting with 1.4.30, the Kotlin compiler uses a new mangling scheme by default. Use the -Xuse-14-inline-classes-mangling-scheme
compiler flag to force the compiler to use the old 1.4.0 mangling scheme and preserve binary compatibility.

Kotlin 1.4.30 promotes inline classes to Beta and we are planning to make them Stable in future releases. We'd be very grateful if you
would share your feedback with us using this YouTrack ticket.

To try the preview version of inline classes, add the compiler option -Xinline-classes or -language-version 1.5.

Learn more about the mangling algorithm in KEEP.

Learn more about inline classes.

Kotlin/JVM

JVM
IR
compiler
backend
reaches
Beta
The IR-based compiler backend for Kotlin/JVM, which was presented in 1.4.0 in Alpha, has reached Beta. This is the last pre-stable level
before the IR backend becomes the default for the Kotlin/JVM compiler.

We're now dropping the restriction on consuming binaries produced by the IR compiler. Previously, you could use code compiled by the
new JVM IR backend only if you had enabled the new backend. Starting from 1.4.30, there is no such limitation, so you can use the new
backend to build components for third-party use, such as libraries. Try the Beta version of the new backend and share your feedback in
our issue tracker.

To enable the new JVM IR backend, add the following lines to the project's configuration file:

In Gradle:

Kotlin

tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile::class) {
kotlinOptions.useIR = true
}

Groovy

180
tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile) {
kotlinOptions.useIR = true
}

In Maven:

<configuration>
<args>
<arg>-Xuse-ir</arg>
</args>
</configuration>

Learn more about the changes that the JVM IR backend brings in this blog post.

Kotlin/Native

Performance
improvements
Kotlin/Native has received a variety of performance improvements in 1.4.30, which has resulted in faster compilation times. For example,
the time required to rebuild the framework in the Networking and data storage with Kotlin Multiplatform Mobile sample has decreased from
9.5 seconds (in 1.4.10) to 4.5 seconds (in 1.4.30).

Apple
watchOS
64-bit
simulator
target
The x86 simulator target has been deprecated for watchOS since version 7.0. To keep up with the latest watchOS versions, Kotlin/Native
has the new target watchosX64 for running the simulator on 64-bit architecture.

Support
for
Xcode
12.2
libraries
We have added support for the new libraries delivered with Xcode 12.2. You can now use them from Kotlin code.

Kotlin/JS

Lazy
initialization
of
top-level
properties

Lazy initialization of top-level properties is Experimental. It may be dropped or changed at any time. Opt-in is required (see the
details below), and you should use it only for evaluation purposes. We would appreciate your feedback on it in YouTrack.

The IR backend for Kotlin/JS is receiving a prototype implementation of lazy initialization for top-level properties. This reduces the need to
initialize all top-level properties when the application starts, and it should significantly improve application start-up times.

We'll keep working on the lazy initialization, and we ask you to try the current prototype and share your thoughts and results in this
YouTrack ticket or the #javascript channel in the official Kotlin Slack (get an invite here).

To use the lazy initialization, add the -Xir-property-lazy-initialization compiler option when compiling the code with the JS IR compiler.

181
Gradle
project
improvements

Support
the
Gradle
configuration
cache
Starting with 1.4.30, the Kotlin Gradle plugin supports the configuration cache feature. It speeds up the build process: once you run the
command, Gradle executes the configuration phase and calculates the task graph. Gradle caches the result and reuses it for subsequent
builds.

To start using this feature, you can use the Gradle command or set up the IntelliJ based IDE.

Standard
library

Locale-agnostic
API
for
upper/lowercasing
text

The locale-agnostic API feature is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes.
We would appreciate your feedback on it in YouTrack.

This release introduces the experimental locale-agnostic API for changing the case of strings and characters. The current toLowerCase(),
toUpperCase(), capitalize(), decapitalize() API functions are locale-sensitive. This means that different platform locale settings can affect
code behavior. For example, in the Turkish locale, when the string "kotlin" is converted using toUpperCase, the result is "KOTLİN", not
"KOTLIN".

// current API
println("Needs to be capitalized".toUpperCase()) // NEEDS TO BE CAPITALIZED

// new API
println("Needs to be capitalized".uppercase()) // NEEDS TO BE CAPITALIZED

Kotlin 1.4.30 provides the following alternatives:

For String functions:

Earlier versions 1.4.30 alternative

String.toUpperCase() String.uppercase()

String.toLowerCase() String.lowercase()

String.capitalize() String.replaceFirstChar { it.uppercase() }

String.decapitalize() String.replaceFirstChar { it.lowercase() }

For Char functions:

182
Earlier versions 1.4.30 alternative

Char.toUpperCase() Char.uppercaseChar(): Char


Char.uppercase(): String

Char.toLowerCase() Char.lowercaseChar(): Char


Char.lowercase(): String

Char.toTitleCase() Char.titlecaseChar(): Char


Char.titlecase(): String

For Kotlin/JVM, there are also overloaded uppercase(), lowercase(), and titlecase() functions with an explicit Locale parameter.

See the full list of changes to the text processing functions in KEEP.

Clear
Char-to-code
and
Char-to-digit
conversions

The unambiguous API for the Char conversion feature is Experimental. It may be dropped or changed at any time. Use it only for
evaluation purposes. We would appreciate your feedback on it in YouTrack.

The current Char to numbers conversion functions, which return UTF-16 codes expressed in different numeric types, are often confused
with the similar String-to-Int conversion, which returns the numeric value of a string:

"4".toInt() // returns 4
'4'.toInt() // returns 52
// and there was no common function that would return the numeric value 4 for Char '4'

To avoid this confusion we've decided to separate Char conversions into two following sets of clearly named functions:

Functions to get the integer code of Char and to construct Char from the given code:

fun Char(code: Int): Char


fun Char(code: UShort): Char
val Char.code: Int

Functions to convert Char to the numeric value of the digit it represents:

fun Char.digitToInt(radix: Int): Int


fun Char.digitToIntOrNull(radix: Int): Int?

An extension function for Int to convert the non-negative single digit it represents to the corresponding Char representation:

fun Int.digitToChar(radix: Int): Char

183
See more details in KEEP.

Serialization
updates
Along with Kotlin 1.4.30, we are releasing kotlinx.serialization 1.1.0-RC, which includes some new features:

Inline classes serialization support

Unsigned primitive type serialization support

Inline
classes
serialization
support
Starting with Kotlin 1.4.30, you can make inline classes serializable:

@Serializable
inline class Color(val rgb: Int)

The feature requires the new 1.4.30 IR compiler.

The serialization framework does not box serializable inline classes when they are used in other serializable classes.

Learn more in the kotlinx.serialization docs.

Unsigned
primitive
type
serialization
support
Starting from 1.4.30, you can use standard JSON serializers of kotlinx.serialization for unsigned primitive types: UInt, ULong, UByte, and
UShort:

@Serializable
class Counter(val counted: UByte, val description: String)
fun main() {
val counted = 239.toUByte()
println(Json.encodeToString(Counter(counted, "tries")))
}

Learn more in the kotlinx.serialization docs.

What's
new
in
Kotlin
1.4.20
Release date: 23 November 2020

Kotlin 1.4.20 offers a number of new experimental features and provides fixes and improvements for existing features, including those
added in 1.4.0.

You can also learn about new features with more examples in this blog post.

Kotlin/JVM

184
Improvements of Kotlin/JVM are intended to keep it up with the features of modern Java versions:

Java 15 target

invokedynamic string concatenation

Java
15
target
Now Java 15 is available as a Kotlin/JVM target.

invokedynamic
string
concatenation

invokedynamic string concatenation is Experimental. It may be dropped or changed at any time. Opt-in is required (see details
below). Use it only for evaluation purposes. We appreciate your feedback on it in YouTrack.

Kotlin 1.4.20 can compile string concatenations into dynamic invocations on JVM 9+ targets, therefore improving the performance.

Currently, this feature is experimental and covers the following cases:

String.plus in the operator (a + b), explicit (a.plus(b)), and reference ((a::plus)(b)) form.

toString on inline and data classes.

string templates except for ones with a single non-constant argument (see KT-42457).

To enable invokedynamic string concatenation, add the -Xstring-concat compiler option with one of the following values:

indy-with-constants to perform invokedynamic concatenation on strings with StringConcatFactory.makeConcatWithConstants().

indy to perform invokedynamic concatenation on strings with StringConcatFactory.makeConcat().

inline to switch back to the classic concatenation via StringBuilder.append().

Kotlin/JS
Kotlin/JS keeps evolving fast, and in 1.4.20 you can find a number experimental features and improvements:

Gradle DSL changes

New Wizard templates

Ignoring compilation errors with IR compiler

Gradle
DSL
changes
The Gradle DSL for Kotlin/JS receives a number of updates which simplify project setup and customization. This includes webpack
configuration adjustments, modifications to the auto-generated package.json file, and improved control over transitive dependencies.

Single point for webpack configuration


A new configuration block commonWebpackConfig is available for the browser target. Inside it, you can adjust common settings from a
single point, instead of having to duplicate configurations for the webpackTask, runTask, and testTask.

185
To enable CSS support by default for all three tasks, add the following snippet in the build.gradle(.kts) of your project:

browser {
commonWebpackConfig {
cssSupport.enabled = true
}
binaries.executable()
}

Learn more about configuring webpack bundling.

package.json customization from Gradle


For more control over your Kotlin/JS package management and distribution, you can now add properties to the project file package.json
via the Gradle DSL.

To add custom fields to your package.json, use the customField function in the compilation's packageJson block:

kotlin {
js(BOTH) {
compilations["main"].packageJson {
customField("hello", mapOf("one" to 1, "two" to 2))
}
}
}

Learn more about package.json customization.

Selective yarn dependency resolutions

Support for selective yarn dependency resolutions is Experimental. It may be dropped or changed at any time. Use it only for
evaluation purposes. We appreciate your feedback on it in YouTrack.

Kotlin 1.4.20 provides a way of configuring Yarn's selective dependency resolutions - the mechanism for overriding dependencies of the
packages you depend on.

You can use it through the YarnRootExtension inside the YarnPlugin in Gradle. To affect the resolved version of a package for your project,
use the resolution function passing in the package name selector (as specified by Yarn) and the version to which it should resolve.

rootProject.plugins.withType<YarnPlugin> {
rootProject.the<YarnRootExtension>().apply {
resolution("react", "16.0.0")
resolution("processor/decamelize", "3.0.0")
}
}

Here, all of your npm dependencies which require react will receive version 16.0.0, and processor will receive its dependency decamelize
as version 3.0.0.

Disabling granular workspaces

186
Disabling granular workspaces is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes.
We appreciate your feedback on it in YouTrack.

To speed up build times, the Kotlin/JS Gradle plugin only installs the dependencies which are required for a particular Gradle task. For
example, the webpack-dev-server package is only installed when you execute one of the *Run tasks, and not when you execute the
assemble task. Such behavior can potentially bring problems when you run multiple Gradle processes in parallel. When the dependency
requirements clash, the two installations of npm packages can cause errors.

To resolve this issue, Kotlin 1.4.20 includes an option to disable these so-called granular workspaces. This feature is currently available
through the YarnRootExtension inside the YarnPlugin in Gradle. To use it, add the following snippet to your build.gradle.kts file:

rootProject.plugins.withType<YarnPlugin> {
rootProject.the<YarnRootExtension>().disableGranularWorkspaces()
}

New
Wizard
templates
To give you more convenient ways to customize your project during creation, the project wizard for Kotlin comes with new templates for
Kotlin/JS applications:

Browser Application - a minimal Kotlin/JS Gradle project that runs in the browser.

React Application - a React app that uses the appropriate kotlin-wrappers. It provides options to enable integrations for style-sheets,
navigational components, or state containers.

Node.js Application - a minimal project for running in a Node.js runtime. It comes with the option to directly include the experimental
kotlinx-nodejs package.

Learn how to create Kotlin/JS applications from templates.

Ignoring
compilation
errors
with
IR
compiler

Ignore compilation errors mode is Experimental. It may be dropped or changed at any time. Opt-in is required (see details
below). Use it only for evaluation purposes. We appreciate your feedback on it in YouTrack.

The IR compiler for Kotlin/JS comes with a new experimental mode - compilation with errors. In this mode, you can run you code even if it
contains errors, for example, if you want to try certain things it when the whole application is not ready yet.

There are two tolerance policies for this mode:

SEMANTIC: the compiler will accept code which is syntactically correct, but doesn't make sense semantically, such as val x: String = 3.

SYNTAX: the compiler will accept any code, even if it contains syntax errors.

To allow compilation with errors, add the -Xerror-tolerance-policy= compiler option with one of the values listed above.

Learn more about ignoring compilation errors with Kotlin/JS IR compiler.

Kotlin/Native

187
Kotlin/Native's priorities in 1.4.20 are performance and polishing existing features. These are the notable improvements:

Escape analysis

Performance improvements and bug fixes

Opt-in wrapping of Objective-C exceptions

CocoaPods plugin improvements

Support for Xcode 12 libraries

Escape
analysis

The escape analysis mechanism is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes.
We appreciate your feedback on it in YouTrack.

Kotlin/Native receives a prototype of the new escape analysis mechanism. It improves the runtime performance by allocating certain
objects on the stack instead of the heap. This mechanism shows a 10% average performance increase on our benchmarks, and we
continue improving it so that it speeds up the program even more.

The escape analysis runs in a separate compilation phase for the release builds (with the -opt compiler option).

If you want to disable the escape analysis phase, use the -Xdisable-phases=EscapeAnalysis compiler option.

Performance
improvements
and
bug
fixes
Kotlin/Native receives performance improvements and bug fixes in various components, including the ones added in 1.4.0, for example,
the code sharing mechanism.

Opt-in
wrapping
of
Objective-C
exceptions

The Objective-C exception wrapping mechanism is Experimental. It may be dropped or changed at any time. Opt-in is required
(see details below). Use it only for evaluation purposes. We appreciate your feedback on it in YouTrack.

Kotlin/Native now can handle exceptions thrown from Objective-C code in runtime to avoid program crashes.

You can opt in to wrap NSException's into Kotlin exceptions of type ForeignException. They hold the references to the original
NSException's. This lets you get the information about the root cause and handle it properly.

To enable wrapping of Objective-C exceptions, specify the -Xforeign-exception-mode objc-wrap option in the cinterop call or add
foreignExceptionMode = objc-wrap property to .def file. If you use CocoaPods integration, specify the option in the pod {} build script
block of a dependency like this:

pod("foo") {
extraOpts = listOf("-Xforeign-exception-mode", "objc-wrap")
}

The default behavior remains unchanged: the program terminates when an exception is thrown from the Objective-C code.

188
CocoaPods
plugin
improvements
Kotlin 1.4.20 continues the set of improvements in CocoaPods integration. Namely, you can try the following new features:

Improved task execution

Extended DSL

Updated integration with Xcode

Improved task execution


CocoaPods plugin gets an improved task execution flow. For example, if you add a new CocoaPods dependency, existing dependencies
are not rebuilt. Adding an extra target also doesn't affect rebuilding dependencies for existing ones.

Extended DSL
The DSL of adding CocoaPods dependencies to your Kotlin project receives new capabilites.

In addition to local Pods and Pods from the CocoaPods repository, you can add dependencies on the following types of libraries:

A library from a custom spec repository.

A remote library from a Git repository.

A library from an archive (also available by arbitrary HTTP address).

A static library.

A library with custom cinterop options.

Learn more about adding CocoaPods dependencies in Kotlin projects. Find examples in the Kotlin with CocoaPods sample.

Updated integration with Xcode


To work correctly with Xcode, Kotlin requires some Podfile changes:

If your Kotlin Pod has any Git, HTTP, or specRepo Pod dependency, you should also specify it in the Podfile.

When you add a library from the custom spec, you also should specify the location of specs at the beginning of your Podfile.

Now integration errors have a detailed description in IDEA. So if you have problems with your Podfile, you will immediately know how to fix
them.

Learn more about creating Kotlin pods.

Support
for
Xcode
12
libraries
We have added support for new libraries delivered with Xcode 12. Now you can use them from the Kotlin code.

Kotlin
Multiplatform

Updated
structure
of
multiplatform
library
publications
Starting from Kotlin 1.4.20, there is no longer a separate metadata publication. Metadata artifacts are now included in the root publication
which stands for the whole library and is automatically resolved to the appropriate platform-specific artifacts when added as a
dependency to the common source set.

189
Learn more about publishing a multiplatform library.

Compatibility with earlier versions


This change of structure breaks the compatibility between projects with hierarchical project structure. If a multiplatform project and a
library it depends on both have the hierarchical project structure, then you need to update them to Kotlin 1.4.20 or higher simultaneously.
Libraries published with Kotlin 1.4.20 are not available for using from project published with earlier versions.

Projects and libraries without the hierarchical project structure remain compatible.

Standard
library
The standard library of Kotlin 1.4.20 offers new extensions for working with files and a better performance.

Extensions for java.nio.file.Path

Improved String.replace function performance

Extensions
for
java.nio.file.Path

Extensions for java.nio.file.Path are Experimental. They may be dropped or changed at any time. Opt-in is required (see details
below). Use them only for evaluation purposes. We appreciate your feedback on them in YouTrack.

Now the standard library provides experimental extensions for java.nio.file.Path. Working with the modern JVM file API in an idiomatic
Kotlin way is now similar to working with java.io.File extensions from the kotlin.io package.

// construct path with the div (/) operator


val baseDir = Path("/base")
val subDir = baseDir / "subdirectory"

// list files in a directory


val kotlinFiles: List<Path> = Path("/home/user").listDirectoryEntries("*.kt")

The extensions are available in the kotlin.io.path package in the kotlin-stdlib-jdk7 module. To use the extensions, opt-in to the
experimental annotation @ExperimentalPathApi.

Improved
String.replace
function
performance
The new implementation of String.replace() speeds up the function execution. The case-sensitive variant uses a manual replacement loop
based on indexOf, while the case-insensitive one uses regular expression matching.

Kotlin
Android
Extensions
In 1.4.20 the Kotlin Android Extensions plugin becomes deprecated and Parcelable implementation generator moves to a separate plugin.

Deprecation of synthetic views

New plugin for Parcelable implementation generator

190
Deprecation
of
synthetic
views
Synthetic views were presented in the Kotlin Android Extensions plugin a while ago to simplify the interaction with UI elements and reduce
boilerplate. Now Google offers a native mechanism that does the same - Android Jetpack's view bindings, and we're deprecating
synthetic views in favor of those.

We extract the Parcelable implementations generator from kotlin-android-extensions and start the deprecation cycle for the rest of it -
synthetic views. For now, they will keep working with a deprecation warning. In the future, you'll need to switch your project to another
solution. Here are the guidelines that will help you migrate your Android project from synthetics to view bindings.

New
plugin
for
Parcelable
implementation
generator
The Parcelable implementation generator is now available in the new kotlin-parcelize plugin. Apply this plugin instead of kotlin-android-
extensions.

kotlin-parcelize and kotlin-android-extensions can't be applied together in one module.

The @Parcelize annotation is moved to the kotlinx.parcelize package.

Learn more about Parcelable implementation generator in the Android documentation.

What's
new
in
Kotlin
1.4
Release date: 17 August 2020

In Kotlin 1.4.0, we ship a number of improvements in all of its components, with the focus on quality and performance. Below you will find
the list of the most important changes in Kotlin 1.4.0.

Language
features
and
improvements
Kotlin 1.4.0 comes with a variety of different language features and improvements. They include:

SAM conversions for Kotlin interfaces

Explicit API mode for library authors

Mixing named and positional arguments

Trailing comma

Callable reference improvements

break and continue inside when included in loops

SAM
conversions
for
Kotlin
interfaces
Before Kotlin 1.4.0, you could apply SAM (Single Abstract Method) conversions only when working with Java methods and Java interfaces
from Kotlin. From now on, you can use SAM conversions for Kotlin interfaces as well. To do so, mark a Kotlin interface explicitly as
functional with the fun modifier.

SAM conversion applies if you pass a lambda as an argument when an interface with only one single abstract method is expected as a
parameter. In this case, the compiler automatically converts the lambda to an instance of the class that implements the abstract member

191
function.

fun interface IntPredicate {


fun accept(i: Int): Boolean
}

val isEven = IntPredicate { it % 2 == 0 }

fun main() {
println("Is 7 even? - ${isEven.accept(7)}")
}

Learn more about Kotlin functional interfaces and SAM conversions.

Explicit
API
mode
for
library
authors
Kotlin compiler offers explicit API mode for library authors. In this mode, the compiler performs additional checks that help make the
library's API clearer and more consistent. It adds the following requirements for declarations exposed to the library's public API:

Visibility modifiers are required for declarations if the default visibility exposes them to the public API. This helps ensure that no
declarations are exposed to the public API unintentionally.

Explicit type specifications are required for properties and functions that are exposed to the public API. This guarantees that API users
are aware of the types of API members they use.

Depending on your configuration, these explicit APIs can produce errors (strict mode) or warnings (warning mode). Certain kinds of
declarations are excluded from such checks for the sake of readability and common sense:

primary constructors

properties of data classes

property getters and setters

override methods

Explicit API mode analyzes only the production sources of a module.

To compile your module in the explicit API mode, add the following lines to your Gradle build script:

Kotlin

kotlin {
// for strict mode
explicitApi()
// or
explicitApi = ExplicitApiMode.Strict

// for warning mode
explicitApiWarning()
// or
explicitApi = ExplicitApiMode.Warning
}

Groovy

kotlin {
// for strict mode
explicitApi()

192
// or
explicitApi = 'strict'

// for warning mode
explicitApiWarning()
// or
explicitApi = 'warning'
}

When using the command-line compiler, switch to explicit API mode by adding the -Xexplicit-api compiler option with the value strict or
warning.

-Xexplicit-api={strict|warning}

Find more details about the explicit API mode in the KEEP.

Mixing
named
and
positional
arguments
In Kotlin 1.3, when you called a function with named arguments, you had to place all the arguments without names (positional arguments)
before the first named argument. For example, you could call f(1, y = 2), but you couldn't call f(x = 1, 2).

It was really annoying when all the arguments were in their correct positions but you wanted to specify a name for one argument in the
middle. It was especially helpful for making absolutely clear which attribute a boolean or null value belongs to.

In Kotlin 1.4, there is no such limitation – you can now specify a name for an argument in the middle of a set of positional arguments.
Moreover, you can mix positional and named arguments any way you like, as long as they remain in the correct order.

fun reformat(
str: String,
uppercaseFirstLetter: Boolean = true,
wordSeparator: Char = ' '
) {
// ...
}

//Function call with a named argument in the middle


reformat("This is a String!", uppercaseFirstLetter = false , '-')

Trailing
comma
With Kotlin 1.4 you can now add a trailing comma in enumerations such as argument and parameter lists, when entries, and components
of destructuring declarations. With a trailing comma, you can add new items and change their order without adding or removing commas.

This is especially helpful if you use multi-line syntax for parameters or values. After adding a trailing comma, you can then easily swap lines
with parameters or values.

fun reformat(
str: String,
uppercaseFirstLetter: Boolean = true,
wordSeparator: Character = ' ', //trailing comma
) {
// ...
}

val colors = listOf(


"red",

193
"green",
"blue", //trailing comma
)

Callable
reference
improvements
Kotlin 1.4 supports more cases for using callable references:

References to functions with default argument values

Function references in Unit-returning functions

References that adapt based on the number of arguments in a function

Suspend conversion on callable references

References to functions with default argument values


Now you can use callable references to functions with default argument values. If the callable reference to the function foo takes no
arguments, the default value 0 is used.

fun foo(i: Int = 0): String = "$i!"

fun apply(func: () -> String): String = func()

fun main() {
println(apply(::foo))
}

Previously, you had to write additional overloads for the function apply to use the default argument values.

// some new overload


fun applyInt(func: (Int) -> String): String = func(0)

Function references in Unit-returning functions


In Kotlin 1.4, you can use callable references to functions returning any type in Unit-returning functions. Before Kotlin 1.4, you could only
use lambda arguments in this case. Now you can use both lambda arguments and callable references.

fun foo(f: () -> Unit) { }


fun returnsInt(): Int = 42

fun main() {
foo { returnsInt() } // this was the only way to do it before 1.4
foo(::returnsInt) // starting from 1.4, this also works
}

References that adapt based on the number of arguments in a function


Now you can adapt callable references to functions when passing a variable number of arguments (vararg) . You can pass any number of
parameters of the same type at the end of the list of passed arguments.

fun foo(x: Int, vararg y: String) {}

fun use0(f: (Int) -> Unit) {}


fun use1(f: (Int, String) -> Unit) {}
fun use2(f: (Int, String, String) -> Unit) {}

194
fun test() {
use0(::foo)
use1(::foo)
use2(::foo)
}

Suspend conversion on callable references


In addition to suspend conversion on lambdas, Kotlin now supports suspend conversion on callable references starting from version 1.4.0.

fun call() {}
fun takeSuspend(f: suspend () -> Unit) {}

fun test() {
takeSuspend { call() } // OK before 1.4
takeSuspend(::call) // In Kotlin 1.4, it also works
}

Using
break
and
continue
inside
when
expressions
included
in
loops
In Kotlin 1.3, you could not use unqualified break and continue inside when expressions included in loops. The reason was that these
keywords were reserved for possible fall-through behavior in when expressions.

That's why if you wanted to use break and continue inside when expressions in loops, you had to label them, which became rather
cumbersome.

fun test(xs: List<Int>) {


LOOP@for (x in xs) {
when (x) {
2 -> continue@LOOP
17 -> break@LOOP
else -> println(x)
}
}
}

In Kotlin 1.4, you can use break and continue without labels inside when expressions included in loops. They behave as expected by
terminating the nearest enclosing loop or proceeding to its next step.

fun test(xs: List<Int>) {


for (x in xs) {
when (x) {
2 -> continue
17 -> break
else -> println(x)
}
}
}

The fall-through behavior inside when is subject to further design.

New
tools
in
the
IDE
With Kotlin 1.4, you can use the new tools in IntelliJ IDEA to simplify Kotlin development:

New flexible Project Wizard

195
Coroutine Debugger

New
flexible
Project
Wizard
With the flexible new Kotlin Project Wizard, you have a place to easily create and configure different types of Kotlin projects, including
multiplatform projects, which can be difficult to configure without a UI.

Kotlin Project Wizard – Multiplatform project

The new Kotlin Project Wizard is both simple and flexible:

1. Select the project template, depending on what you're trying to do. More templates will be added in the future.

2. Select the build system – Gradle (Kotlin or Groovy DSL), Maven, or IntelliJ IDEA.
The Kotlin Project Wizard will only show the build systems supported on the selected project template.

3. Preview the project structure directly on the main screen.

Then you can finish creating your project or, optionally, configure the project on the next screen:

4. Add/remove modules and targets supported for this project template.

5. Configure module and target settings, for example, the target JVM version, target template, and test framework.

196
Kotlin Project Wizard - Configure targets

In the future, we are going to make the Kotlin Project Wizard even more flexible by adding more configuration options and templates.

You can try out the new Kotlin Project Wizard by working through these tutorials:

Create a console application based on Kotlin/JVM

Create a Kotlin/JS application for React

Create a Kotlin/Native application

Coroutine
Debugger
Many people already use coroutines for asynchronous programming. But when it came to debugging, working with coroutines before
Kotlin 1.4, could be a real pain. Since coroutines jumped between threads, it was difficult to understand what a specific coroutine was
doing and check its context. In some cases, tracking steps over breakpoints simply didn't work. As a result, you had to rely on logging or
mental effort to debug code that used coroutines.

In Kotlin 1.4, debugging coroutines is now much more convenient with the new functionality shipped with the Kotlin plugin.

Debugging works for versions 1.3.8 or later of kotlinx-coroutines-core.

The Debug Tool Window now contains a new Coroutines tab. In this tab, you can find information about both currently running and
suspended coroutines. The coroutines are grouped by the dispatcher they are running on.

197
Debugging coroutines

Now you can:

Easily check the state of each coroutine.

See the values of local and captured variables for both running and suspended coroutines.

See a full coroutine creation stack, as well as a call stack inside the coroutine. The stack includes all frames with variable values, even
those that would be lost during standard debugging.

If you need a full report containing the state of each coroutine and its stack, right-click inside the Coroutines tab, and then click Get
Coroutines Dump. Currently, the coroutines dump is rather simple, but we're going to make it more readable and helpful in future versions
of Kotlin.

Coroutines Dump

Learn more about debugging coroutines in this blog post and IntelliJ IDEA documentation.

New
compiler
The new Kotlin compiler is going to be really fast; it will unify all the supported platforms and provide an API for compiler extensions. It's a
long-term project, and we've already completed several steps in Kotlin 1.4.0:

New, more powerful type inference algorithm is enabled by default.

New JVM and JS IR backends. They will become the default once we stabilize them.

New
more
powerful
type
inference
algorithm
Kotlin 1.4 uses a new, more powerful type inference algorithm. This new algorithm was already available to try in Kotlin 1.3 by specifying a

198
compiler option, and now it's used by default. You can find the full list of issues fixed in the new algorithm in YouTrack. Here you can find
some of the most noticeable improvements:

More cases where type is inferred automatically

Smart casts for a lambda's last expression

Smart casts for callable references

Better inference for delegated properties

SAM conversion for Java interfaces with different arguments

Java SAM interfaces in Kotlin

More cases where type is inferred automatically


The new inference algorithm infers types for many cases where the old algorithm required you to specify them explicitly. For instance, in
the following example the type of the lambda parameter it is correctly inferred to String?:

//sampleStart
val rulesMap: Map<String, (String?) -> Boolean> = mapOf(
"weak" to { it != null },
"medium" to { !it.isNullOrBlank() },
"strong" to { it != null && "^[a-zA-Z0-9]+$".toRegex().matches(it) }
)
//sampleEnd

fun main() {
println(rulesMap.getValue("weak")("abc!"))
println(rulesMap.getValue("strong")("abc"))
println(rulesMap.getValue("strong")("abc!"))
}

In Kotlin 1.3, you needed to introduce an explicit lambda parameter or replace to with a Pair constructor with explicit generic arguments to
make it work.

Smart casts for a lambda's last expression


In Kotlin 1.3, the last expression inside a lambda wasn't smart cast unless you specified the expected type. Thus, in the following example,
Kotlin 1.3 infers String? as the type of the result variable:

val result = run {


var str = currentValue()
if (str == null) {
str = "test"
}
str // the Kotlin compiler knows that str is not null here
}
// The type of 'result' is String? in Kotlin 1.3 and String in Kotlin 1.4

In Kotlin 1.4, thanks to the new inference algorithm, the last expression inside a lambda gets smart cast, and this new, more precise type
is used to infer the resulting lambda type. Thus, the type of the result variable becomes String.

In Kotlin 1.3, you often needed to add explicit casts (either !! or type casts like as String) to make such cases work, and now these casts
have become unnecessary.

Smart casts for callable references

199
In Kotlin 1.3, you couldn't access a member reference of a smart cast type. Now in Kotlin 1.4 you can:

import kotlin.reflect.KFunction

sealed class Animal


class Cat : Animal() {
fun meow() {
println("meow")
}
}

class Dog : Animal() {


fun woof() {
println("woof")
}
}

//sampleStart
fun perform(animal: Animal) {
val kFunction: KFunction<*> = when (animal) {
is Cat -> animal::meow
is Dog -> animal::woof
}
kFunction.call()
}
//sampleEnd

fun main() {
perform(Cat())
}

You can use different member references animal::meow and animal::woof after the animal variable has been smart cast to specific types
Cat and Dog. After type checks, you can access member references corresponding to subtypes.

Better inference for delegated properties


The type of a delegated property wasn't taken into account while analyzing the delegate expression which follows the by keyword. For
instance, the following code didn't compile before, but now the compiler correctly infers the types of the old and new parameters as
String?:

import kotlin.properties.Delegates

fun main() {
var prop: String? by Delegates.observable(null) { p, old, new ->
println("$old → $new")
}
prop = "abc"
prop = "xyz"
}

SAM conversion for Java interfaces with different arguments


Kotlin has supported SAM conversions for Java interfaces from the beginning, but there was one case that wasn't supported, which was
sometimes annoying when working with existing Java libraries. If you called a Java method that took two SAM interfaces as parameters,
both arguments needed to be either lambdas or regular objects. You couldn't pass one argument as a lambda and another as an object.

The new algorithm fixes this issue, and you can pass a lambda instead of a SAM interface in any case, which is the way you'd naturally
expect it to work.

// FILE: A.java
public class A {

200
public static void foo(Runnable r1, Runnable r2) {}
}

// FILE: test.kt
fun test(r1: Runnable) {
A.foo(r1) {} // Works in Kotlin 1.4
}

Java SAM interfaces in Kotlin


In Kotlin 1.4, you can use Java SAM interfaces in Kotlin and apply SAM conversions to them.

import java.lang.Runnable

fun foo(r: Runnable) {}

fun test() {
foo { } // OK
}

In Kotlin 1.3, you would have had to declare the function foo above in Java code to perform a SAM conversion.

Unified
backends
and
extensibility
In Kotlin, we have three backends that generate executables: Kotlin/JVM, Kotlin/JS, and Kotlin/Native. Kotlin/JVM and Kotlin/JS don't
share much code since they were developed independently of each other. Kotlin/Native is based on a new infrastructure built around an
intermediate representation (IR) for Kotlin code.

We are now migrating Kotlin/JVM and Kotlin/JS to the same IR. As a result, all three backends share a lot of logic and have a unified
pipeline. This allows us to implement most features, optimizations, and bug fixes only once for all platforms. Both new IR-based back-
ends are in Alpha.

A common backend infrastructure also opens the door for multiplatform compiler extensions. You will be able to plug into the pipeline and
add custom processing and transformations that will automatically work for all platforms.

We encourage you to use our new JVM IR and JS IR backends, which are currently in Alpha, and share your feedback with us.

Kotlin/JVM
Kotlin 1.4.0 includes a number of JVM-specific improvements, such as:

New JVM IR backend

New modes for generating default methods in interfaces

Unified exception type for null checks

Type annotations in the JVM bytecode

New
JVM
IR
backend
Along with Kotlin/JS, we are migrating Kotlin/JVM to the unified IR backend, which allows us to implement most features and bug fixes
once for all platforms. You will also be able to benefit from this by creating multiplatform extensions that will work for all platforms.

Kotlin 1.4.0 does not provide a public API for such extensions yet, but we are working closely with our partners, including Jetpack

201
Compose, who are already building their compiler plugins using our new backend.

We encourage you to try out the new Kotlin/JVM backend, which is currently in Alpha, and to file any issues and feature requests to our
issue tracker. This will help us to unify the compiler pipelines and bring compiler extensions like Jetpack Compose to the Kotlin community
more quickly.

To enable the new JVM IR backend, specify an additional compiler option in your Gradle build script:

kotlinOptions.useIR = true

If you enable Jetpack Compose, you will automatically be opted in to the new JVM backend without needing to specify the
compiler option in kotlinOptions.

When using the command-line compiler, add the compiler option -Xuse-ir.

You can use code compiled by the new JVM IR backend only if you've enabled the new backend. Otherwise, you will get an
error. Considering this, we don't recommend that library authors switch to the new backend in production.

New
modes
for
generating
default
methods
When compiling Kotlin code to targets JVM 1.8 and above, you could compile non-abstract methods of Kotlin interfaces into Java's
default methods. For this purpose, there was a mechanism that includes the @JvmDefault annotation for marking such methods and the -
Xjvm-default compiler option that enables processing of this annotation.

In 1.4.0, we've added a new mode for generating default methods: -Xjvm-default=all compiles all non-abstract methods of Kotlin
interfaces to default Java methods. For compatibility with the code that uses the interfaces compiled without default, we also added all-
compatibility mode.

For more information about default methods in the Java interop, see the interoperability documentation and this blog post.

Unified
exception
type
for
null
checks
Starting from Kotlin 1.4.0, all runtime null checks will throw a java.lang.NullPointerException instead of KotlinNullPointerException,
IllegalStateException, IllegalArgumentException, and TypeCastException. This applies to: the !! operator, parameter null checks in the
method preamble, platform-typed expression null checks, and the as operator with a non-null type. This doesn't apply to lateinit null
checks and explicit library function calls like checkNotNull or requireNotNull.

This change increases the number of possible null check optimizations that can be performed either by the Kotlin compiler or by various
kinds of bytecode processing tools, such as the Android R8 optimizer.

Note that from a developer's perspective, things won't change that much: the Kotlin code will throw exceptions with the same error
messages as before. The type of exception changes, but the information passed stays the same.

Type
annotations
in
the
JVM
bytecode
Kotlin can now generate type annotations in the JVM bytecode (target version 1.8+), so that they become available in Java reflection at
runtime. To emit the type annotation in the bytecode, follow these steps:

1. Make sure that your declared annotation has a proper annotation target (Java's ElementType.TYPE_USE or Kotlin's
AnnotationTarget.TYPE) and retention (AnnotationRetention.RUNTIME).

202
2. Compile the annotation class declaration to JVM bytecode target version 1.8+. You can specify it with -jvm-target=1.8 compiler option.

3. Compile the code that uses the annotation to JVM bytecode target version 1.8+ (-jvm-target=1.8) and add the -Xemit-jvm-type-
annotations compiler option.

Note that the type annotations from the standard library aren't emitted in the bytecode for now because the standard library is compiled
with the target version 1.6.

So far, only the basic cases are supported:

Type annotations on method parameters, method return types and property types;

Invariant projections of type arguments, such as Smth<@Ann Foo>, Array<@Ann Foo>.

In the following example, the @Foo annotation on the String type can be emitted to the bytecode and then used by the library code:

@Target(AnnotationTarget.TYPE)
annotation class Foo

class A {
fun foo(): @Foo String = "OK"
}

Kotlin/JS
On the JS platform, Kotlin 1.4.0 provides the following improvements:

New Gradle DSL

New JS IR backend

New
Gradle
DSL
The kotlin.js Gradle plugin comes with an adjusted Gradle DSL, which provides a number of new configuration options and is more closely
aligned to the DSL used by the kotlin-multiplatform plugin. Some of the most impactful changes include:

Explicit toggles for the creation of executable files via binaries.executable(). Read more about the executing Kotlin/JS and its
environment here.

Configuration of webpack's CSS and style loaders from within the Gradle configuration via cssSupport. Read more about using CSS
and style loaders here.

Improved management for npm dependencies, with mandatory version numbers or semver version ranges, as well as support for
development, peer, and optional npm dependencies using devNpm, optionalNpm and peerNpm. Read more about dependency
management for npm packages directly from Gradle here.

Stronger integrations for Dukat, the generator for Kotlin external declarations. External declarations can now be generated at build time,
or can be manually generated via a Gradle task. Read more about how to use the integration here.

New
JS
IR
backend
The IR backend for Kotlin/JS, which currently has Alpha stability, provides some new functionality specific to the Kotlin/JS target which is
focused around the generated code size through dead code elimination, and improved interoperation with JavaScript and TypeScript,
among others.

To enable the Kotlin/JS IR backend, set the key kotlin.js.compiler=ir in your gradle.properties, or pass the IR compiler type to the js

203
function of your Gradle build script:

kotlin {
js(IR) { // or: LEGACY, BOTH
// . . .
}
binaries.executable()
}

For more detailed information about how to configure the new backend, check out the Kotlin/JS IR compiler documentation.

With the new @JsExport annotation and the ability to generate TypeScript definitions from Kotlin code, the Kotlin/JS IR compiler backend
improves JavaScript & TypeScript interoperability. This also makes it easier to integrate Kotlin/JS code with existing tooling, to create
hybrid applications and leverage code-sharing functionality in multiplatform projects.

Learn more about the available features in the Kotlin/JS IR compiler backend.

Kotlin/Native
In 1.4.0, Kotlin/Native got a significant number of new features and improvements, including:

Support for suspending functions in Swift and Objective-C

Objective-C generics support by default

Exception handling in Objective-C/Swift interop

Generate release .dSYMs on Apple targets by default

Performance improvements

Simplified management of CocoaPods dependencies

Support
for
Kotlin's
suspending
functions
in
Swift
and
Objective-C
In 1.4.0, we add the basic support for suspending functions in Swift and Objective-C. Now, when you compile a Kotlin module into an
Apple framework, suspending functions are available in it as functions with callbacks (completionHandler in the Swift/Objective-C
terminology). When you have such functions in the generated framework's header, you can call them from your Swift or Objective-C code
and even override them.

For example, if you write this Kotlin function:

suspend fun queryData(id: Int): String = ...

…then you can call it from Swift like so:

queryData(id: 17) { result, error in


if let e = error {
print("ERROR: \(e)")
} else {
print(result!)
}
}

Learn more about using suspending functions in Swift and Objective-C.

204
Objective-C
generics
support
by
default
Previous versions of Kotlin provided experimental support for generics in Objective-C interop. Since 1.4.0, Kotlin/Native generates Apple
frameworks with generics from Kotlin code by default. In some cases, this may break existing Objective-C or Swift code calling Kotlin
frameworks. To have the framework header written without generics, add the -Xno-objc-generics compiler option.

kotlin {
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
binaries.all {
freeCompilerArgs += "-Xno-objc-generics"
}
}
}

Please note that all specifics and limitations listed in the documentation on interoperability with Objective-C are still valid.

Exception
handling
in
Objective-C/Swift
interop
In 1.4.0, we slightly change the Swift API generated from Kotlin with respect to the way exceptions are translated. There is a fundamental
difference in error handling between Kotlin and Swift. All Kotlin exceptions are unchecked, while Swift has only checked errors. Thus, to
make Swift code aware of expected exceptions, Kotlin functions should be marked with a @Throws annotation specifying a list of
potential exception classes.

When compiling to Swift or the Objective-C framework, functions that have or are inheriting @Throws annotation are represented as
NSError*-producing methods in Objective-C and as throws methods in Swift.

Previously, any exceptions other than RuntimeException and Error were propagated as NSError. Now this behavior changes: now NSError
is thrown only for exceptions that are instances of classes specified as parameters of @Throws annotation (or their subclasses). Other
Kotlin exceptions that reach Swift/Objective-C are considered unhandled and cause program termination.

Generate
release
.dSYMs
on
Apple
targets
by
default
Starting with 1.4.0, the Kotlin/Native compiler produces debug symbol files (.dSYMs) for release binaries on Darwin platforms by default.
This can be disabled with the -Xadd-light-debug=disable compiler option. On other platforms, this option is disabled by default. To toggle
this option in Gradle, use:

kotlin {
targets.withType<org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget> {
binaries.all {
freeCompilerArgs += "-Xadd-light-debug={enable|disable}"
}
}
}

Learn more about crash report symbolication.

Performance
improvements
Kotlin/Native has received a number of performance improvements that speed up both the development process and execution. Here are
some examples:

To improve the speed of object allocation, we now offer the mimalloc memory allocator as an alternative to the system allocator.
mimalloc works up to two times faster on some benchmarks. Currently, the usage of mimalloc in Kotlin/Native is experimental; you can
switch to it using the -Xallocator=mimalloc compiler option.

We've reworked how C interop libraries are built. With the new tooling, Kotlin/Native produces interop libraries up to 4 times as fast as

205
before, and artifacts are 25% to 30% the size they used to be.

Overall runtime performance has improved because of optimizations in GC. This improvement will be especially apparent in projects
with a large number of long-lived objects. HashMap and HashSet collections now work faster by escaping redundant boxing.

In 1.3.70 we introduced two new features for improving the performance of Kotlin/Native compilation: caching project dependencies
and running the compiler from the Gradle daemon. Since that time, we've managed to fix numerous issues and improve the overall
stability of these features.

Simplified
management
of
CocoaPods
dependencies
Previously, once you integrated your project with the dependency manager CocoaPods, you could build an iOS, macOS, watchOS, or
tvOS part of your project only in Xcode, separate from other parts of your multiplatform project. These other parts could be built in IntelliJ
IDEA.

Moreover, every time you added a dependency on an Objective-C library stored in CocoaPods (Pod library), you had to switch from IntelliJ
IDEA to Xcode, call pod install, and run the Xcode build there.

Now you can manage Pod dependencies right in IntelliJ IDEA while enjoying the benefits it provides for working with code, such as code
highlighting and completion. You can also build the whole Kotlin project with Gradle, without having to switch to Xcode. This means you
only have to go to Xcode when you need to write Swift/Objective-C code or run your application on a simulator or device.

Now you can also work with Pod libraries stored locally.

Depending on your needs, you can add dependencies between:

A Kotlin project and Pod libraries stored remotely in the CocoaPods repository or stored locally on your machine.

A Kotlin Pod (Kotlin project used as a CocoaPods dependency) and an Xcode project with one or more targets.

Complete the initial configuration, and when you add a new dependency to cocoapods, just re-import the project in IntelliJ IDEA. The new
dependency will be added automatically. No additional steps are required.

Learn how to add dependencies.

Kotlin
Multiplatform

Support for multiplatform projects is in Alpha. It may change incompatibly and require manual migration in the future. We
appreciate your feedback on it in YouTrack.

Kotlin Multiplatform reduces time spent writing and maintaining the same code for different platforms while retaining the flexibility and
benefits of native programming. We continue investing our effort in multiplatform features and improvements:

Sharing code in several targets with the hierarchical project structure

Leveraging native libs in the hierarchical structure

Specifying kotlinx dependencies only once

Multiplatform projects require Gradle 6.0 or later.

206
Sharing
code
in
several
targets
with
the
hierarchical
project
structure
With the new hierarchical project structure support, you can share code among several platforms in a multiplatform project.

Previously, any code added to a multiplatform project could be placed either in a platform-specific source set, which is limited to one
target and can't be reused by any other platform, or in a common source set, like commonMain or commonTest, which is shared across
all the platforms in the project. In the common source set, you could only call a platform-specific API by using an expect declaration that
needs platform-specific actual implementations.

This made it easy to share code on all platforms, but it was not so easy to share between only some of the targets, especially similar ones
that could potentially reuse a lot of the common logic and third-party APIs.

For example, in a typical multiplatform project targeting iOS, there are two iOS-related targets: one for iOS ARM64 devices, and the other
for the x64 simulator. They have separate platform-specific source sets, but in practice, there is rarely a need for different code for the
device and simulator, and their dependencies are much alike. So iOS-specific code could be shared between them.

Apparently, in this setup, it would be desirable to have a shared source set for two iOS targets, with Kotlin/Native code that could still
directly call any of the APIs that are common to both the iOS device and the simulator.

Code shared for iOS targets

Now you can do this with the hierarchical project structure support, which infers and adapts the API and language features available in
each source set based on which targets consume them.

For common combinations of targets, you can create a hierarchical structure with target shortcuts.

For example, create two iOS targets and the shared source set shown above with the ios() shortcut:

207
kotlin {
ios() // iOS device and simulator targets; iosMain and iosTest source sets
}

For other combinations of targets, by connecting the source sets with the dependsOn relation.

Hierarchical structure

Kotlin

kotlin{
sourceSets {
val desktopMain by creating {
dependsOn(commonMain)
}
val linuxX64Main by getting {
dependsOn(desktopMain)
}
val mingwX64Main by getting {
dependsOn(desktopMain)
}
val macosX64Main by getting {
dependsOn(desktopMain)
}
}
}

Groovy

kotlin {
sourceSets {
desktopMain {

208
dependsOn(commonMain)
}
linuxX64Main {
dependsOn(desktopMain)
}
mingwX64Main {
dependsOn(desktopMain)
}
macosX64Main {
dependsOn(desktopMain)
}
}
}

Thanks to the hierarchical project structure, libraries can also provide common APIs for a subset of targets. Learn more about sharing
code in libraries.

Leveraging
native
libs
in
the
hierarchical
structure
You can use platform-dependent libraries, such as Foundation, UIKit, and POSIX, in source sets shared among several native targets. This
can help you share more native code without being limited by platform-specific dependencies.

No additional steps are required – everything is done automatically. IntelliJ IDEA will help you detect common declarations that you can
use in the shared code.

Learn more about usage of platform-dependent libraries.

Specifying
dependencies
only
once
From now on, instead of specifying dependencies on different variants of the same library in shared and platform-specific source sets
where it is used, you should specify a dependency only once in the shared source set.

Kotlin

kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
}
}
}
}

Groovy

kotlin {
sourceSets {
commonMain {
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
}
}
}
}

209
Don't use kotlinx library artifact names with suffixes specifying the platform, such as -common, -native, or similar, as they are NOT
supported anymore. Instead, use the library base artifact name, which in the example above is kotlinx-coroutines-core.

However, the change doesn't currently affect:

The stdlib library – starting from Kotlin 1.4.0, the stdlib dependency is added automatically.

The kotlin.test library – you should still use test-common and test-annotations-common. These dependencies will be addressed later.

If you need a dependency only for a specific platform, you can still use platform-specific variants of standard and kotlinx libraries with
such suffixes as -jvm or-js, for example kotlinx-coroutines-core-jvm.

Learn more about configuring dependencies.

Gradle
project
improvements
Besides Gradle project features and improvements that are specific to Kotlin Multiplatform, Kotlin/JVM, Kotlin/Native, and Kotlin/JS, there
are several changes applicable to all Kotlin Gradle projects:

Dependency on the standard library is now added by default

Kotlin projects require a recent version of Gradle

Improved support for Kotlin Gradle DSL in the IDE

Dependency
on
the
standard
library
added
by
default
You no longer need to declare a dependency on the stdlib library in any Kotlin Gradle project, including a multiplatform one. The
dependency is added by default.

The automatically added standard library will be the same version of the Kotlin Gradle plugin, since they have the same versioning.

For platform-specific source sets, the corresponding platform-specific variant of the library is used, while a common standard library is
added to the rest. The Kotlin Gradle plugin will select the appropriate JVM standard library depending on the kotlinOptions.jvmTarget
compiler option of your Gradle build script.

Learn how to change the default behavior.

Minimum
Gradle
version
for
Kotlin
projects
To enjoy the new features in your Kotlin projects, update Gradle to the latest version. Multiplatform projects require Gradle 6.0 or later,
while other Kotlin projects work with Gradle 5.4 or later.

Improved
*.gradle.kts
support
in
the
IDE
In 1.4.0, we continued improving the IDE support for Gradle Kotlin DSL scripts (*.gradle.kts files). Here is what the new version brings:

Explicit loading of script configurations for better performance. Previously, the changes you make to the build script were loaded
automatically in the background. To improve the performance, we've disabled the automatic loading of build script configuration in
1.4.0. Now the IDE loads the changes only when you explicitly apply them.

In Gradle versions earlier than 6.0, you need to manually load the script configuration by clicking Load Configuration in the editor.

210
*.gradle.kts – Load Configuration

In Gradle 6.0 and above, you can explicitly apply changes by clicking Load Gradle Changes or by reimporting the Gradle project.

We've added one more action in IntelliJ IDEA 2020.1 with Gradle 6.0 and above – Load Script Configurations, which loads changes to
the script configurations without updating the whole project. This takes much less time than reimporting the whole project.

*.gradle.kts – Load Script Changes and Load Gradle Changes

You should also Load Script Configurations for newly created scripts or when you open a project with new Kotlin plugin for the first
time.

With Gradle 6.0 and above, you are now able to load all scripts at once as opposed to the previous implementation where they were
loaded individually. Since each request requires the Gradle configuration phase to be executed, this could be resource-intensive for
large Gradle projects.

Currently, such loading is limited to build.gradle.kts and settings.gradle.kts files (please vote for the related issue). To enable
highlighting for init.gradle.kts or applied script plugins, use the old mechanism – adding them to standalone scripts. Configuration for
that scripts will be loaded separately when you need it. You can also enable auto-reload for such scripts.

*.gradle.kts – Add to standalone scripts

Better error reporting. Previously you could only see errors from the Gradle Daemon in separate log files. Now the Gradle Daemon
returns all the information about errors directly and shows it in the Build tool window. This saves you both time and effort.

211
Standard
library
Here is the list of the most significant changes to the Kotlin standard library in 1.4.0:

Common exception processing API

New functions for arrays and collections

Functions for string manipulations

Bit operations

Delegated properties improvements

Converting from KType to Java Type

Proguard configurations for Kotlin reflection

Improving the existing API

module-info descriptors for stdlib artifacts

Deprecations

Exclusion of the deprecated experimental coroutines

Common
exception
processing
API
The following API elements have been moved to the common library:

Throwable.stackTraceToString() extension function, which returns the detailed description of this throwable with its stack trace, and
Throwable.printStackTrace(), which prints this description to the standard error output.

Throwable.addSuppressed() function, which lets you specify the exceptions that were suppressed in order to deliver the exception, and
the Throwable.suppressedExceptions property, which returns a list of all the suppressed exceptions.

@Throws annotation, which lists exception types that will be checked when the function is compiled to a platform method (on JVM or
native platforms).

New
functions
for
arrays
and
collections

Collections
In 1.4.0, the standard library includes a number of useful functions for working with collections:

setOfNotNull(), which makes a set consisting of all the non-null items among the provided arguments.

fun main() {
//sampleStart
val set = setOfNotNull(null, 1, 2, 0, null)
println(set)
//sampleEnd
}

shuffled() for sequences.

fun main() {

212
//sampleStart
val numbers = (0 until 50).asSequence()
val result = numbers.map { it * 2 }.shuffled().take(5)
println(result.toList()) //five random even numbers below 100
//sampleEnd
}

*Indexed() counterparts for onEach() and flatMap(). The operation that they apply to the collection elements has the element index as a
parameter.

fun main() {
//sampleStart
listOf("a", "b", "c", "d").onEachIndexed {
index, item -> println(index.toString() + ":" + item)
}

val list = listOf("hello", "kot", "lin", "world")


val kotlin = list.flatMapIndexed { index, item ->
if (index in 1..2) item.toList() else emptyList()
}
//sampleEnd
println(kotlin)
}

*OrNull() counterparts randomOrNull(), reduceOrNull(), and reduceIndexedOrNull(). They return null on empty collections.

fun main() {
//sampleStart
val empty = emptyList<Int>()
empty.reduceOrNull { a, b -> a + b }
//empty.reduce { a, b -> a + b } // Exception: Empty collection can't be reduced.
//sampleEnd
}

runningFold(), its synonym scan(), and runningReduce() apply the given operation to the collection elements sequentially, similarly
tofold() and reduce(); the difference is that these new functions return the whole sequence of intermediate results.

fun main() {
//sampleStart
val numbers = mutableListOf(0, 1, 2, 3, 4, 5)
val runningReduceSum = numbers.runningReduce { sum, item -> sum + item }
val runningFoldSum = numbers.runningFold(10) { sum, item -> sum + item }
//sampleEnd
println(runningReduceSum.toString())
println(runningFoldSum.toString())
}

sumOf() takes a selector function and returns a sum of its values for all elements of a collection. sumOf() can produce sums of the types
Int, Long, Double, UInt, and ULong. On the JVM, BigInteger and BigDecimal are also available.

data class OrderItem(val name: String, val price: Double, val count: Int)

fun main() {
//sampleStart
val order = listOf<OrderItem>(
OrderItem("Cake", price = 10.0, count = 1),
OrderItem("Coffee", price = 2.5, count = 3),
OrderItem("Tea", price = 1.5, count = 2))

val total = order.sumOf { it.price * it.count } // Double


val count = order.sumOf { it.count } // Int

213
//sampleEnd
println("You've ordered $count items that cost $total in total")
}

The min() and max() functions have been renamed to minOrNull() and maxOrNull() to comply with the naming convention used across
the Kotlin collections API. An *OrNull suffix in the function name means that it returns null if the receiver collection is empty. The same
applies to minBy(), maxBy(), minWith(), maxWith() – in 1.4, they have *OrNull() synonyms.

The new minOf() and maxOf() extension functions return the minimum and the maximum value of the given selector function on the
collection items.

data class OrderItem(val name: String, val price: Double, val count: Int)

fun main() {
//sampleStart
val order = listOf<OrderItem>(
OrderItem("Cake", price = 10.0, count = 1),
OrderItem("Coffee", price = 2.5, count = 3),
OrderItem("Tea", price = 1.5, count = 2))
val highestPrice = order.maxOf { it.price }
//sampleEnd
println("The most expensive item in the order costs $highestPrice")
}

There are also minOfWith() and maxOfWith(), which take a Comparator as an argument, and *OrNull() versions of all four functions that
return null on empty collections.

New overloads for flatMap and flatMapTo let you use transformations with return types that don't match the receiver type, namely:

Transformations to Sequence on Iterable, Array, and Map

Transformations to Iterable on Sequence

fun main() {
//sampleStart
val list = listOf("kot", "lin")
val lettersList = list.flatMap { it.asSequence() }
val lettersSeq = list.asSequence().flatMap { it.toList() }
//sampleEnd
println(lettersList)
println(lettersSeq.toList())
}

removeFirst() and removeLast() shortcuts for removing elements from mutable lists, and *orNull() counterparts of these functions.

Arrays
To provide a consistent experience when working with different container types, we've also added new functions for arrays:

shuffle() puts the array elements in a random order.

onEach() performs the given action on each array element and returns the array itself.

associateWith() and associateWithTo() build maps with the array elements as keys.

reverse() for array subranges reverses the order of the elements in the subrange.

sortDescending() for array subranges sorts the elements in the subrange in descending order.

sort() and sortWith() for array subranges are now available in the common library.

214
fun main() {
//sampleStart
var language = ""
val letters = arrayOf("k", "o", "t", "l", "i", "n")
val fileExt = letters.onEach { language += it }
.filterNot { it in "aeuio" }.take(2)
.joinToString(prefix = ".", separator = "")
println(language) // "kotlin"
println(fileExt) // ".kt"

letters.shuffle()
letters.reverse(0, 3)
letters.sortDescending(2, 5)
println(letters.contentToString()) // [k, o, t, l, i, n]
//sampleEnd
}

Additionally, there are new functions for conversions between CharArray/ByteArray and String:

ByteArray.decodeToString() and String.encodeToByteArray()

CharArray.concatToString() and String.toCharArray()

fun main() {
//sampleStart
val str = "kotlin"
val array = str.toCharArray()
println(array.concatToString())
//sampleEnd
}

ArrayDeque
We've also added the ArrayDeque class – an implementation of a double-ended queue. Double-ended queue lets you can add or remove
elements both at the beginning and the end of the queue in an amortized constant time. You can use a double-ended queue by default
when you need a queue or a stack in your code.

fun main() {
val deque = ArrayDeque(listOf(1, 2, 3))

deque.addFirst(0)
deque.addLast(4)
println(deque) // [0, 1, 2, 3, 4]

println(deque.first()) // 0
println(deque.last()) // 4

deque.removeFirst()
deque.removeLast()
println(deque) // [1, 2, 3]
}

The ArrayDeque implementation uses a resizable array underneath: it stores the contents in a circular buffer, an Array, and resizes this
Array only when it becomes full.

Functions
for
string
manipulations
The standard library in 1.4.0 includes a number of improvements in the API for string manipulation:

StringBuilder has useful new extension functions: set(), setRange(), deleteAt(), deleteRange(), appendRange(), and others.

215
fun main() {
//sampleStart
val sb = StringBuilder("Bye Kotlin 1.3.72")
sb.deleteRange(0, 3)
sb.insertRange(0, "Hello", 0 ,5)
sb.set(15, '4')
sb.setRange(17, 19, "0")
print(sb.toString())
//sampleEnd
}

Some existing functions of StringBuilder are available in the common library. Among them are append(), insert(), substring(), setLength(),
and more.

New functions Appendable.appendLine() and StringBuilder.appendLine() have been added to the common library. They replace the
JVM-only appendln() functions of these classes.

fun main() {
//sampleStart
println(buildString {
appendLine("Hello,")
appendLine("world")
})
//sampleEnd
}

Bit
operations
New functions for bit manipulations:

countOneBits()

countLeadingZeroBits()

countTrailingZeroBits()

takeHighestOneBit()

takeLowestOneBit()

rotateLeft() and rotateRight() (experimental)

fun main() {
//sampleStart
val number = "1010000".toInt(radix = 2)
println(number.countOneBits())
println(number.countTrailingZeroBits())
println(number.takeHighestOneBit().toString(2))
//sampleEnd
}

Delegated
properties
improvements
In 1.4.0, we have added new features to improve your experience with delegated properties in Kotlin:

Now a property can be delegated to another property.

A new interface PropertyDelegateProvider helps create delegate providers in a single declaration.

216
ReadWriteProperty now extends ReadOnlyProperty so you can use both of them for read-only properties.

Aside from the new API, we've made some optimizations that reduce the resulting bytecode size. These optimizations are described in this
blog post.

Learn more about delegated properties.

Converting
from
KType
to
Java
Type
A new extension property KType.javaType (currently experimental) in the stdlib helps you obtain a java.lang.reflect.Type from a Kotlin type
without using the whole kotlin-reflect dependency.

import kotlin.reflect.javaType
import kotlin.reflect.typeOf

@OptIn(ExperimentalStdlibApi::class)
inline fun <reified T> accessReifiedTypeArg() {
val kType = typeOf<T>()
println("Kotlin type: $kType")
println("Java type: ${kType.javaType}")
}

@OptIn(ExperimentalStdlibApi::class)
fun main() {
accessReifiedTypeArg<String>()
// Kotlin type: kotlin.String
// Java type: class java.lang.String

accessReifiedTypeArg<List<String>>()
// Kotlin type: kotlin.collections.List<kotlin.String>
// Java type: java.util.List<java.lang.String>
}

Proguard
configurations
for
Kotlin
reflection
Starting from 1.4.0, we have embedded Proguard/R8 configurations for Kotlin Reflection in kotlin-reflect.jar. With this in place, most
Android projects using R8 or Proguard should work with kotlin-reflect without needing any additional configuration. You no longer need to
copy-paste the Proguard rules for kotlin-reflect internals. But note that you still need to explicitly list all the APIs you're going to reflect on.

Improving
the
existing
API
Several functions now work on null receivers, for example:

toBoolean() on strings

contentEquals(), contentHashcode(), contentToString() on arrays

NaN, NEGATIVE_INFINITY, and POSITIVE_INFINITY in Double and Float are now defined as const, so you can use them as annotation
arguments.

New constants SIZE_BITS and SIZE_BYTES in Double and Float contain the number of bits and bytes used to represent an instance of
the type in binary form.

The maxOf() and minOf() top-level functions can accept a variable number of arguments ( vararg).

module-info
descriptors
for
stdlib
artifacts
Kotlin 1.4.0 adds module-info.java module information to default standard library artifacts. This lets you use them with jlink tool, which

217
generates custom Java runtime images containing only the platform modules that are required for your app. You could already use jlink
with Kotlin standard library artifacts, but you had to use separate artifacts to do so – the ones with the "modular" classifier – and the whole
setup wasn't straightforward.
In Android, make sure you use the Android Gradle plugin version 3.2 or higher, which can correctly process jar files with module-info.

Deprecations

toShort() and toByte() of Double and Float


We've deprecated the functions toShort() and toByte() on Double and Float because they could lead to unexpected results because of the
narrow value range and smaller variable size.

To convert floating-point numbers to Byte or Short, use the two-step conversion: first, convert them to Int, and then convert them again to
the target type.

contains(), indexOf(), and lastIndexOf() on floating-point arrays


We've deprecated the contains(), indexOf(), and lastIndexOf() extension functions of FloatArray and DoubleArray because they use the
IEEE 754 standard equality, which contradicts the total order equality in some corner cases. See this issue for details.

min() and max() collection functions


We've deprecated the min() and max() collection functions in favor of minOrNull() and maxOrNull(), which more properly reflect their
behavior – returning null on empty collections. See this issue for details.

Exclusion
of
the
deprecated
experimental
coroutines
The kotlin.coroutines.experimental API was deprecated in favor of kotlin.coroutines in 1.3.0. In 1.4.0, we're completing the deprecation
cycle for kotlin.coroutines.experimental by removing it from the standard library. For those who still use it on the JVM, we've provided a
compatibility artifact kotlin-coroutines-experimental-compat.jar with all the experimental coroutines APIs. We've published it to Maven,
and we include it in the Kotlin distribution alongside the standard library.

Stable
JSON
serialization
With Kotlin 1.4.0, we are shipping the first stable version of kotlinx.serialization - 1.0.0-RC. Now we are pleased to declare the JSON
serialization API in kotlinx-serialization-core (previously known as kotlinx-serialization-runtime) stable. Libraries for other serialization
formats remain experimental, along with some advanced parts of the core library.

We have significantly reworked the API for JSON serialization to make it more consistent and easier to use. From now on, we'll continue
developing the JSON serialization API in a backward-compatible manner. However, if you have used previous versions of it, you'll need to
rewrite some of your code when migrating to 1.0.0-RC. To help you with this, we also offer the Kotlin Serialization Guide – the complete set
of documentation for kotlinx.serialization. It will guide you through the process of using the most important features and it can help you
address any issues that you might face.

Note: kotlinx-serialization 1.0.0-RC only works with Kotlin compiler 1.4. Earlier compiler versions are not compatible.

Scripting
and
REPL
In 1.4.0, scripting in Kotlin benefits from a number of functional and performance improvements along with other updates. Here are some

218
of the key changes:

New dependencies resolution API

New REPL API

Compiled scripts cache

Artifacts renaming

To help you become more familiar with scripting in Kotlin, we've prepared a project with examples. It contains examples of the standard
scripts (*.main.kts) and examples of uses of the Kotlin Scripting API and custom script definitions. Please give it a try and share your
feedback using our issue tracker.

New
dependencies
resolution
API
In 1.4.0, we've introduced a new API for resolving external dependencies (such as Maven artifacts), along with implementations for it. This
API is published in the new artifacts kotlin-scripting-dependencies and kotlin-scripting-dependencies-maven. The previous dependency
resolution functionality in kotlin-script-util library is now deprecated.

New
REPL
API
The new experimental REPL API is now a part of the Kotlin Scripting API. There are also several implementations of it in the published
artifacts, and some have advanced functionality, such as code completion. We use this API in the Kotlin Jupyter kernel and now you can
try it in your own custom shells and REPLs.

Compiled
scripts
cache
The Kotlin Scripting API now provides the ability to implement a compiled scripts cache, significantly speeding up subsequent executions
of unchanged scripts. Our default advanced script implementation kotlin-main-kts already has its own cache.

Artifacts
renaming
In order to avoid confusion about artifact names, we've renamed kotlin-scripting-jsr223-embeddable and kotlin-scripting-jvm-host-
embeddable to just kotlin-scripting-jsr223 and kotlin-scripting-jvm-host. These artifacts depend on the kotlin-compiler-embeddable
artifact, which shades the bundled third-party libraries to avoid usage conflicts. With this renaming, we're making the usage of kotlin-
compiler-embeddable (which is safer in general) the default for scripting artifacts. If, for some reason, you need artifacts that depend on
the unshaded kotlin-compiler, use the artifact versions with the -unshaded suffix, such as kotlin-scripting-jsr223-unshaded. Note that this
renaming affects only the scripting artifacts that are supposed to be used directly; names of other artifacts remain unchanged.

Migrating
to
Kotlin
1.4.0
The Kotlin plugin's migration tools help you migrate your projects from earlier versions of Kotlin to 1.4.0.

Just change the Kotlin version to 1.4.0 and re-import your Gradle or Maven project. The IDE will then ask you about migration.

If you agree, it will run migration code inspections that will check your code and suggest corrections for anything that doesn't work or that
is not recommended in 1.4.0.

219
Run migration

Code inspections have different severity levels, to help you decide which suggestions to accept and which to ignore.

Migration inspections

Kotlin 1.4.0 is a feature release and therefore can bring incompatible changes to the language. Find the detailed list of such changes in the
Compatibility Guide for Kotlin 1.4.

What's
new
in
Kotlin
1.3
Release date: 29 October 2018

Coroutines
release
After some long and extensive battle testing, coroutines are now released! It means that from Kotlin 1.3 the language support and the API
are fully stable. Check out the new coroutines overview page.

Kotlin 1.3 introduces callable references on suspend-functions and support of coroutines in the reflection API.

Kotlin/Native
Kotlin 1.3 continues to improve and polish the Native target. See the Kotlin/Native overview for details.

Multiplatform
projects
In 1.3, we've completely reworked the model of multiplatform projects in order to improve expressiveness and flexibility, and to make
sharing common code easier. Also, Kotlin/Native is now supported as one of the targets!

220
The key differences to the old model are:

In the old model, common and platform-specific code needed to be placed in separate modules, linked by expectedBy dependencies.
Now, common and platform-specific code is placed in different source roots of the same module, making projects easier to configure.

There is now a large number of preset platform configurations for different supported platforms.

The dependencies configuration has been changed; dependencies are now specified separately for each source root.

Source sets can now be shared between an arbitrary subset of platforms (for example, in a module that targets JS, Android and iOS,
you can have a source set that is shared only between Android and iOS).

Publishing multiplatform libraries is now supported.

For more information, please refer to the multiplatform programming documentation.

Contracts
The Kotlin compiler does extensive static analysis to provide warnings and reduce boilerplate. One of the most notable features is
smartcasts — with the ability to perform a cast automatically based on the performed type checks:

fun foo(s: String?) {


if (s != null) s.length // Compiler automatically casts 's' to 'String'
}

However, as soon as these checks are extracted in a separate function, all the smartcasts immediately disappear:

fun String?.isNotNull(): Boolean = this != null

fun foo(s: String?) {


if (s.isNotNull()) s.length // No smartcast :(
}

To improve the behavior in such cases, Kotlin 1.3 introduces experimental mechanism called contracts.

Contracts allow a function to explicitly describe its behavior in a way which is understood by the compiler. Currently, two wide classes of
cases are supported:

Improving smartcasts analysis by declaring the relation between a function's call outcome and the passed arguments values:

fun require(condition: Boolean) {


// This is a syntax form which tells the compiler:
// "if this function returns successfully, then the passed 'condition' is true"
contract { returns() implies condition }
if (!condition) throw IllegalArgumentException(...)
}

fun foo(s: String?) {


require(s is String)
// s is smartcast to 'String' here, because otherwise
// 'require' would have thrown an exception
}

Improving the variable initialization analysis in the presence of high-order functions:

fun synchronize(lock: Any?, block: () -> Unit) {

221
// It tells the compiler:
// "This function will invoke 'block' here and now, and exactly one time"
contract { callsInPlace(block, EXACTLY_ONCE) }
}

fun foo() {
val x: Int
synchronize(lock) {
x = 42 // Compiler knows that lambda passed to 'synchronize' is called
// exactly once, so no reassignment is reported
}
println(x) // Compiler knows that lambda will be definitely called, performing
// initialization, so 'x' is considered to be initialized here
}

Contracts
in
stdlib
stdlib already makes use of contracts, which leads to improvements in the analyses described above. This part of contracts is stable,
meaning that you can benefit from the improved analysis right now without any additional opt-ins:

//sampleStart
fun bar(x: String?) {
if (!x.isNullOrEmpty()) {
println("length of '$x' is ${x.length}") // Yay, smartcast to not-null!
}
}
//sampleEnd
fun main() {
bar(null)
bar("42")
}

Custom
contracts
It is possible to declare contracts for your own functions, but this feature is experimental, as the current syntax is in a state of early
prototype and will most probably be changed. Also please note that currently the Kotlin compiler does not verify contracts, so it's the
responsibility of the programmer to write correct and sound contracts.

Custom contracts are introduced by a call to contract stdlib function, which provides DSL scope:

fun String?.isNullOrEmpty(): Boolean {


contract {
returns(false) implies (this@isNullOrEmpty != null)
}
return this == null || isEmpty()
}

See the details on the syntax as well as the compatibility notice in the KEEP.

Capturing
when
subject
in
a
variable
In Kotlin 1.3, it is now possible to capture the when subject into a variable:

fun Request.getBody() =
when (val response = executeRequest()) {
is Success -> response.body
is HttpError -> throw HttpException(response.status)
}

222
While it was already possible to extract this variable just before when, val in when has its scope properly restricted to the body of when,
and so preventing namespace pollution. See the full documentation on when here.

@JvmStatic
and
@JvmField
in
companions
of
interfaces
With Kotlin 1.3, it is possible to mark members of a companion object of interfaces with annotations @JvmStatic and @JvmField. In the
classfile, such members will be lifted to the corresponding interface and marked as static.

For example, the following Kotlin code:

interface Foo {
companion object {
@JvmField
val answer: Int = 42

@JvmStatic
fun sayHello() {
println("Hello, world!")
}
}
}

It is equivalent to this Java code:

interface Foo {
public static int answer = 42;
public static void sayHello() {
// ...
}
}

Nested
declarations
in
annotation
classes
In Kotlin 1.3, it is possible for annotations to have nested classes, interfaces, objects, and companions:

annotation class Foo {


enum class Direction { UP, DOWN, LEFT, RIGHT }

annotation class Bar

companion object {
fun foo(): Int = 42
val bar: Int = 42
}
}

Parameterless
main
By convention, the entry point of a Kotlin program is a function with a signature like main(args: Array<String>), where args represent the
command-line arguments passed to the program. However, not every application supports command-line arguments, so this parameter
often ends up not being used.

Kotlin 1.3 introduced a simpler form of main which takes no parameters. Now "Hello, World" in Kotlin is 19 characters shorter!

223
fun main() {
println("Hello, world!")
}

Functions
with
big
arity
In Kotlin, functional types are represented as generic classes taking a different number of parameters: Function0<R>, Function1<P0, R>,
Function2<P0, P1, R>, ... This approach has a problem in that this list is finite, and it currently ends with Function22.

Kotlin 1.3 relaxes this limitation and adds support for functions with bigger arity:

fun trueEnterpriseComesToKotlin(block: (Any, Any, ... /* 42 more */, Any) -> Any) {
block(Any(), Any(), ..., Any())
}

Progressive
mode
Kotlin cares a lot about stability and backward compatibility of code: Kotlin compatibility policy says that breaking changes (e.g., a change
which makes the code that used to compile fine, not compile anymore) can be introduced only in the major releases (1.2, 1.3, etc.).

We believe that a lot of users could use a much faster cycle where critical compiler bug fixes arrive immediately, making the code more
safe and correct. So, Kotlin 1.3 introduces the progressive compiler mode, which can be enabled by passing the argument -progressive to
the compiler.

In the progressive mode, some fixes in language semantics can arrive immediately. All these fixes have two important properties:

They preserve backward compatibility of source code with older compilers, meaning that all the code which is compilable by the
progressive compiler will be compiled fine by non-progressive one.

They only make code safer in some sense — e.g., some unsound smartcast can be forbidden, behavior of the generated code may be
changed to be more predictable/stable, and so on.

Enabling the progressive mode can require you to rewrite some of your code, but it shouldn't be too much — all the fixes enabled under
progressive are carefully handpicked, reviewed, and provided with tooling migration assistance. We expect that the progressive mode will
be a nice choice for any actively maintained codebases which are updated to the latest language versions quickly.

Inline
classes

Inline classes are in Alpha. They may change incompatibly and require manual migration in the future. We appreciate your
feedback on it in YouTrack. See details in the reference.

Kotlin 1.3 introduces a new kind of declaration — inline class. Inline classes can be viewed as a restricted version of the usual classes, in
particular, inline classes must have exactly one property:

inline class Name(val s: String)

The Kotlin compiler will use this restriction to aggressively optimize runtime representation of inline classes and substitute their instances

224
with the value of the underlying property where possible removing constructor calls, GC pressure, and enabling other optimizations:

inline class Name(val s: String)


//sampleStart
fun main() {
// In the next line no constructor call happens, and
// at the runtime 'name' contains just string "Kotlin"
val name = Name("Kotlin")
println(name.s)
}
//sampleEnd

See reference for inline classes for details.

Unsigned
integers

Unsigned integers are in Beta. Their implementation is almost stable, but migration steps may be required in the future. We'll do
our best to minimize any changes you will have to make.

Kotlin 1.3 introduces unsigned integer types:

kotlin.UByte: an unsigned 8-bit integer, ranges from 0 to 255

kotlin.UShort: an unsigned 16-bit integer, ranges from 0 to 65535

kotlin.UInt: an unsigned 32-bit integer, ranges from 0 to 2^32 - 1

kotlin.ULong: an unsigned 64-bit integer, ranges from 0 to 2^64 - 1

Most of the functionality of signed types are supported for unsigned counterparts too:

fun main() {
//sampleStart
// You can define unsigned types using literal suffixes
val uint = 42u
val ulong = 42uL
val ubyte: UByte = 255u

// You can convert signed types to unsigned and vice versa via stdlib extensions:
val int = uint.toInt()
val byte = ubyte.toByte()
val ulong2 = byte.toULong()

// Unsigned types support similar operators:


val x = 20u + 22u
val y = 1u shl 8
val z = "128".toUByte()
val range = 1u..5u
//sampleEnd
println("ubyte: $ubyte, byte: $byte, ulong2: $ulong2")
println("x: $x, y: $y, z: $z, range: $range")
}

See reference for details.

@JvmDefault

225
@JvmDefault is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes. We appreciate
your feedback on it in YouTrack.

Kotlin targets a wide range of the Java versions, including Java 6 and Java 7, where default methods in the interfaces are not allowed. For
your convenience, the Kotlin compiler works around that limitation, but this workaround isn't compatible with the default methods,
introduced in Java 8.

This could be an issue for Java-interoperability, so Kotlin 1.3 introduces the @JvmDefault annotation. Methods annotated with this
annotation will be generated as default methods for JVM:

interface Foo {
// Will be generated as 'default' method
@JvmDefault
fun foo(): Int = 42
}

Warning! Annotating your API with @JvmDefault has serious implications on binary compatibility. Make sure to carefully read the
reference page before using @JvmDefault in production.

Standard
library

Multiplatform
random
Prior to Kotlin 1.3, there was no uniform way to generate random numbers on all platforms — we had to resort to platform-specific
solutions like java.util.Random on JVM. This release fixes this issue by introducing the class kotlin.random.Random, which is available on
all platforms:

import kotlin.random.Random

fun main() {
//sampleStart
val number = Random.nextInt(42) // number is in range [0, limit)
println(number)
//sampleEnd
}

isNullOrEmpty
and
orEmpty
extensions
isNullOrEmpty and orEmpty extensions for some types are already present in stdlib. The first one returns true if the receiver is null or
empty, and the second one falls back to an empty instance if the receiver is null. Kotlin 1.3 provides similar extensions on collections,
maps, and arrays of objects.

Copy
elements
between
two
existing
arrays
The array.copyInto(targetArray, targetOffset, startIndex, endIndex) functions for the existing array types, including the unsigned arrays,
make it easier to implement array-based containers in pure Kotlin.

fun main() {
//sampleStart
val sourceArr = arrayOf("k", "o", "t", "l", "i", "n")

226
val targetArr = sourceArr.copyInto(arrayOfNulls<String>(6), 3, startIndex = 3, endIndex = 6)
println(targetArr.contentToString())

sourceArr.copyInto(targetArr, startIndex = 0, endIndex = 3)
println(targetArr.contentToString())
//sampleEnd
}

associateWith
It is quite a common situation to have a list of keys and want to build a map by associating each of these keys with some value. It was
possible to do it before with the associate { it to getValue(it) } function, but now we're introducing a more efficient and easy to explore
alternative: keys.associateWith { getValue(it) }.

fun main() {
//sampleStart
val keys = 'a'..'f'
val map = keys.associateWith { it.toString().repeat(5).capitalize() }
map.forEach { println(it) }
//sampleEnd
}

ifEmpty
and
ifBlank
functions
Collections, maps, object arrays, char sequences, and sequences now have an ifEmpty function, which allows specifying a fallback value
that will be used instead of the receiver if it is empty:

fun main() {
//sampleStart
fun printAllUppercase(data: List<String>) {
val result = data
.filter { it.all { c -> c.isUpperCase() } }
.ifEmpty { listOf("<no uppercase>") }
result.forEach { println(it) }
}

printAllUppercase(listOf("foo", "Bar"))
printAllUppercase(listOf("FOO", "BAR"))
//sampleEnd
}

Char sequences and strings in addition have an ifBlank extension that does the same thing as ifEmpty but checks for a string being all
whitespace instead of empty.

fun main() {
//sampleStart
val s = " \n"
println(s.ifBlank { "<blank>" })
println(s.ifBlank { null })
//sampleEnd
}

Sealed
classes
in
reflection
We've added a new API to kotlin-reflect that can be used to enumerate all the direct subtypes of a sealed class, namely
KClass.sealedSubclasses.

227
Smaller
changes

Boolean type now has companion.

Any?.hashCode() extension that returns 0 for null.

Char now provides MIN_VALUE and MAX_VALUE constants.

SIZE_BYTES and SIZE_BITS constants in primitive type companions.

Tooling

Code
style
support
in
IDE
Kotlin 1.3 introduces support for the recommended code style in IntelliJ IDEA. Check out this page for the migration guidelines.

kotlinx.serialization
kotlinx.serialization is a library which provides multiplatform support for (de)serializing objects in Kotlin. Previously, it was a separate
project, but since Kotlin 1.3, it ships with the Kotlin compiler distribution on par with the other compiler plugins. The main difference is that
you don't need to manually watch out for the Serialization IDE Plugin being compatible with the Kotlin IDE plugin version you're using: now
the Kotlin IDE plugin already includes serialization!

See here for details.

Even though kotlinx.serialization now ships with the Kotlin Compiler distribution, it is still considered to be an experimental
feature in Kotlin 1.3.

Scripting
update

Scripting is Experimental. It may be dropped or changed at any time. Use it only for evaluation purposes. We appreciate your
feedback on it in YouTrack.

Kotlin 1.3 continues to evolve and improve scripting API, introducing some experimental support for scripts customization, such as adding
external properties, providing static or dynamic dependencies, and so on.

For additional details, please consult the KEEP-75.

Scratches
support
Kotlin 1.3 introduces support for runnable Kotlin scratch files. Scratch file is a kotlin script file with the .kts extension that you can run and
get evaluation results directly in the editor.

Consult the general Scratches documentation for details.

What's
new
in
Kotlin
1.2

228
Release date: 28 November 2017

Table
of
contents
Multiplatform projects

Other language features

Standard library

JVM backend

JavaScript backend

Multiplatform
projects
(experimental)
Multiplatform projects are a new experimental feature in Kotlin 1.2, allowing you to reuse code between target platforms supported by
Kotlin – JVM, JavaScript, and (in the future) Native. In a multiplatform project, you have three kinds of modules:

A common module contains code that is not specific to any platform, as well as declarations without implementation of platform-
dependent APIs.

A platform module contains implementations of platform-dependent declarations in the common module for a specific platform, as well
as other platform-dependent code.

A regular module targets a specific platform and can either be a dependency of platform modules or depend on platform modules.

When you compile a multiplatform project for a specific platform, the code for both the common and platform-specific parts is generated.

A key feature of the multiplatform project support is the possibility to express dependencies of common code on platform-specific parts
through expected and actual declarations. An expected declaration specifies an API (class, interface, annotation, top-level declaration
etc.). An actual declaration is either a platform-dependent implementation of the API or a typealias referring to an existing implementation
of the API in an external library. Here's an example:

In the common code:

// expected platform-specific API:


expect fun hello(world: String): String

fun greet() {
// usage of the expected API:
val greeting = hello("multiplatform world")
println(greeting)
}

expect class URL(spec: String) {


open fun getHost(): String
open fun getPath(): String
}

In the JVM platform code:

actual fun hello(world: String): String =


"Hello, $world, on the JVM platform!"

// using existing platform-specific implementation:


actual typealias URL = java.net.URL

229
See the multiplatform programming documentation for details and steps to build a multiplatform project.

Other
language
features

Array
literals
in
annotations
Starting with Kotlin 1.2, array arguments for annotations can be passed with the new array literal syntax instead of the arrayOf function:

@CacheConfig(cacheNames = ["books", "default"])


public class BookRepositoryImpl {
// ...
}

The array literal syntax is constrained to annotation arguments.

Lateinit
top-level
properties
and
local
variables
The lateinit modifier can now be used on top-level properties and local variables. The latter can be used, for example, when a lambda
passed as a constructor argument to one object refers to another object which has to be defined later:

class Node<T>(val value: T, val next: () -> Node<T>)

fun main(args: Array<String>) {


// A cycle of three nodes:
lateinit var third: Node<Int>

val second = Node(2, next = { third })


val first = Node(1, next = { second })

third = Node(3, next = { first })

val nodes = generateSequence(first) { it.next() }


println("Values in the cycle: ${nodes.take(7).joinToString { it.value.toString() }}, ...")
}

Check
whether
a
lateinit
var
is
initialized
You can now check whether a lateinit var has been initialized using isInitialized on the property reference:

class Foo {
lateinit var lateinitVar: String

fun initializationLogic() {
//sampleStart
println("isInitialized before assignment: " + this::lateinitVar.isInitialized)
lateinitVar = "value"
println("isInitialized after assignment: " + this::lateinitVar.isInitialized)
//sampleEnd
}
}

fun main(args: Array<String>) {


Foo().initializationLogic()
}

230
Inline
functions
with
default
functional
parameters
Inline functions are now allowed to have default values for their inlined functional parameters:

//sampleStart
inline fun <E> Iterable<E>.strings(transform: (E) -> String = { it.toString() }) =
map { transform(it) }

val defaultStrings = listOf(1, 2, 3).strings()


val customStrings = listOf(1, 2, 3).strings { "($it)" }
//sampleEnd

fun main(args: Array<String>) {


println("defaultStrings = $defaultStrings")
println("customStrings = $customStrings")
}

Information
from
explicit
casts
is
used
for
type
inference
The Kotlin compiler can now use information from type casts in type inference. If you're calling a generic method that returns a type
parameter T and casting the return value to a specific type Foo, the compiler now understands that T for this call needs to be bound to the
type Foo.

This is particularly important for Android developers, since the compiler can now correctly analyze generic findViewById calls in Android
API level 26:

val button = findViewById(R.id.button) as Button

Smart
cast
improvements
When a variable is assigned from a safe call expression and checked for null, the smart cast is now applied to the safe call receiver as
well:

fun countFirst(s: Any): Int {


//sampleStart
val firstChar = (s as? CharSequence)?.firstOrNull()
if (firstChar != null)
return s.count { it == firstChar } // s: Any is smart cast to CharSequence

val firstItem = (s as? Iterable<*>)?.firstOrNull()


if (firstItem != null)
return s.count { it == firstItem } // s: Any is smart cast to Iterable<*>
//sampleEnd
return -1
}

fun main(args: Array<String>) {


val string = "abacaba"
val countInString = countFirst(string)
println("called on \"$string\": $countInString")

val list = listOf(1, 2, 3, 1, 2)


val countInList = countFirst(list)
println("called on $list: $countInList")
}

Also, smart casts in a lambda are now allowed for local variables that are only modified before the lambda:

fun main(args: Array<String>) {

231
//sampleStart
val flag = args.size == 0
var x: String? = null
if (flag) x = "Yahoo!"

run {
if (x != null) {
println(x.length) // x is smart cast to String
}
}
//sampleEnd
}

Support
for
::foo
as
a
shorthand
for
this::foo
A bound callable reference to a member of this can now be written without explicit receiver, ::foo instead of this::foo. This also makes
callable references more convenient to use in lambdas where you refer to a member of the outer receiver.

Breaking
change:
sound
smart
casts
after
try
blocks
Earlier, Kotlin used assignments made inside a try block for smart casts after the block, which could break type- and null-safety and lead
to runtime failures. This release fixes this issue, making the smart casts more strict, but breaking some code that relied on such smart
casts.

To switch to the old smart casts behavior, pass the fallback flag -Xlegacy-smart-cast-after-try as the compiler argument. It will become
deprecated in Kotlin 1.3.

Deprecation:
data
classes
overriding
copy
When a data class derived from a type that already had the copy function with the same signature, the copy implementation generated for
the data class used the defaults from the supertype, leading to counter-intuitive behavior, or failed at runtime if there were no default
parameters in the supertype.

Inheritance that leads to a copy conflict has become deprecated with a warning in Kotlin 1.2 and will be an error in Kotlin 1.3.

Deprecation:
nested
types
in
enum
entries
Inside enum entries, defining a nested type that is not an inner class has been deprecated due to issues in the initialization logic. This
causes a warning in Kotlin 1.2 and will become an error in Kotlin 1.3.

Deprecation:
single
named
argument
for
vararg
For consistency with array literals in annotations, passing a single item for a vararg parameter in the named form (foo(items = i)) has been
deprecated. Please use the spread operator with the corresponding array factory functions:

foo(items = *arrayOf(1))

There is an optimization that removes redundant arrays creation in such cases, which prevents performance degradation. The single-
argument form produces warnings in Kotlin 1.2 and is to be dropped in Kotlin 1.3.

Deprecation:
inner
classes
of
generic
classes
extending
Throwable
Inner classes of generic types that inherit from Throwable could violate type-safety in a throw-catch scenario and thus have been
deprecated, with a warning in Kotlin 1.2 and an error in Kotlin 1.3.

232
Deprecation:
mutating
backing
field
of
a
read-only
property
Mutating the backing field of a read-only property by assigning field = ... in the custom getter has been deprecated, with a warning in
Kotlin 1.2 and an error in Kotlin 1.3.

Standard
library

Kotlin
standard
library
artifacts
and
split
packages
The Kotlin standard library is now fully compatible with the Java 9 module system, which forbids split packages (multiple jar files declaring
classes in the same package). In order to support that, new artifacts kotlin-stdlib-jdk7 and kotlin-stdlib-jdk8 are introduced, which replace
the old kotlin-stdlib-jre7 and kotlin-stdlib-jre8.

The declarations in the new artifacts are visible under the same package names from the Kotlin point of view, but have different package
names for Java. Therefore, switching to the new artifacts will not require any changes to your source code.

Another change made to ensure compatibility with the new module system is removing the deprecated declarations in the kotlin.reflect
package from the kotlin-reflect library. If you were using them, you need to switch to using the declarations in the kotlin.reflect.full
package, which is supported since Kotlin 1.1.

windowed,
chunked,
zipWithNext
New extensions for Iterable<T>, Sequence<T>, and CharSequence cover such use cases as buffering or batch processing ( chunked),
sliding window and computing sliding average (windowed) , and processing pairs of subsequent items (zipWithNext):

fun main(args: Array<String>) {


//sampleStart
val items = (1..9).map { it * it }

val chunkedIntoLists = items.chunked(4)


val points3d = items.chunked(3) { (x, y, z) -> Triple(x, y, z) }
val windowed = items.windowed(4)
val slidingAverage = items.windowed(4) { it.average() }
val pairwiseDifferences = items.zipWithNext { a, b -> b - a }
//sampleEnd

println("items: $items\n")

println("chunked into lists: $chunkedIntoLists")


println("3D points: $points3d")
println("windowed by 4: $windowed")
println("sliding average by 4: $slidingAverage")
println("pairwise differences: $pairwiseDifferences")
}

fill,
replaceAll,
shuffle/shuffled
A set of extension functions was added for manipulating lists: fill, replaceAll and shuffle for MutableList, and shuffled for read-only List:

fun main(args: Array<String>) {


//sampleStart
val items = (1..5).toMutableList()

items.shuffle()
println("Shuffled items: $items")

items.replaceAll { it * 2 }
println("Items doubled: $items")

233

items.fill(5)
println("Items filled with 5: $items")
//sampleEnd
}

Math
operations
in
kotlin-stdlib
Satisfying the longstanding request, Kotlin 1.2 adds the kotlin.math API for math operations that is common for JVM and JS and contains
the following:

Constants: PI and E

Trigonometric: cos, sin, tan and inverse of them: acos, asin, atan, atan2

Hyperbolic: cosh, sinh, tanh and their inverse: acosh, asinh, atanh

Exponentation: pow (an extension function), sqrt, hypot, exp, expm1

Logarithms: log, log2, log10, ln, ln1p

Rounding:

ceil, floor, truncate, round (half to even) functions

roundToInt, roundToLong (half to integer) extension functions

Sign and absolute value:

abs and sign functions

absoluteValue and sign extension properties

withSign extension function

max and min of two values

Binary representation:

ulp extension property

nextUp, nextDown, nextTowards extension functions

toBits, toRawBits, Double.fromBits (these are in the kotlin package)

The same set of functions (but without constants) is also available for Float arguments.

Operators
and
conversions
for
BigInteger
and
BigDecimal
Kotlin 1.2 introduces a set of functions for operating with BigInteger and BigDecimal and creating them from other numeric types. These
are:

toBigInteger for Int and Long

toBigDecimal for Int, Long, Float, Double, and BigInteger

Arithmetic and bitwise operator functions:

Binary operators +, -, *, /, % and infix functions and, or, xor, shl, shr

234
Unary operators -, ++, --, and a function inv

Floating
point
to
bits
conversions
New functions were added for converting Double and Float to and from their bit representations:

toBits and toRawBits returning Long for Double and Int for Float

Double.fromBits and Float.fromBits for creating floating point numbers from the bit representation

Regex
is
now
serializable
The kotlin.text.Regex class has become Serializable and can now be used in serializable hierarchies.

Closeable.use
calls
Throwable.addSuppressed
if
available
The Closeable.use function calls Throwable.addSuppressed when an exception is thrown during closing the resource after some other
exception.

To enable this behavior you need to have kotlin-stdlib-jdk7 in your dependencies.

JVM
backend

Constructor
calls
normalization
Ever since version 1.0, Kotlin supported expressions with complex control flow, such as try-catch expressions and inline function calls.
Such code is valid according to the Java Virtual Machine specification. Unfortunately, some bytecode processing tools do not handle such
code quite well when such expressions are present in the arguments of constructor calls.

To mitigate this problem for the users of such bytecode processing tools, we've added a command-line compiler option ( -Xnormalize-
constructor-calls=MODE) that tells the compiler to generate more Java-like bytecode for such constructs. Here MODE is one of:

disable (default) – generate bytecode in the same way as in Kotlin 1.0 and 1.1.

enable – generate Java-like bytecode for constructor calls. This can change the order in which the classes are loaded and initialized.

preserve-class-initialization – generate Java-like bytecode for constructor calls, ensuring that the class initialization order is preserved.
This can affect overall performance of your application; use it only if you have some complex state shared between multiple classes and
updated on class initialization.

The "manual" workaround is to store the values of sub-expressions with control flow in variables, instead of evaluating them directly inside
the call arguments. It's similar to -Xnormalize-constructor-calls=enable.

Java-default
method
calls
Before Kotlin 1.2, interface members overriding Java-default methods while targeting JVM 1.6 produced a warning on super calls: Super
calls to Java default methods are deprecated in JVM target 1.6. Recompile with '-jvm-target 1.8'. In Kotlin 1.2, there's an error instead,
thus requiring any such code to be compiled with JVM target 1.8.

Breaking
change:
consistent
behavior
of
x.equals(null)
for
platform
types
Calling x.equals(null) on a platform type that is mapped to a Java primitive (Int!, Boolean!, Short!, Long!, Float!, Double!, Char!) incorrectly
returned true when x was null. Starting with Kotlin 1.2, calling x.equals(...) on a null value of a platform type throws an NPE (but x == ...

235
does not).

To return to the pre-1.2 behavior, pass the flag -Xno-exception-on-explicit-equals-for-boxed-null to the compiler.

Breaking
change:
fix
for
platform
null
escaping
through
an
inlined
extension
receiver
Inline extension functions that were called on a null value of a platform type did not check the receiver for null and would thus allow null to
escape into the other code. Kotlin 1.2 forces this check at the call sites, throwing an exception if the receiver is null.

To switch to the old behavior, pass the fallback flag -Xno-receiver-assertions to the compiler.

JavaScript
backend

TypedArrays
support
enabled
by
default
The JS typed arrays support that translates Kotlin primitive arrays, such as IntArray, DoubleArray, into JavaScript typed arrays, that was
previously an opt-in feature, has been enabled by default.

Tools

Warnings
as
errors
The compiler now provides an option to treat all warnings as errors. Use -Werror on the command line, or the following Gradle snippet:

compileKotlin {
kotlinOptions.allWarningsAsErrors = true
}

What's
new
in
Kotlin
1.1
Release date: 15 February 2016

Table
of
contents
Coroutines

Other language features

Standard library

JVM backend

JavaScript backend

JavaScript
Starting with Kotlin 1.1, the JavaScript target is no longer considered experimental. All language features are supported, and there are

236
many new tools for integration with the frontend development environment. See below for a more detailed list of changes.

Coroutines
(experimental)
The key new feature in Kotlin 1.1 is coroutines, bringing the support of async/await, yield, and similar programming patterns. The key
feature of Kotlin's design is that the implementation of coroutine execution is part of the libraries, not the language, so you aren't bound to
any specific programming paradigm or concurrency library.

A coroutine is effectively a light-weight thread that can be suspended and resumed later. Coroutines are supported through suspending
functions: a call to such a function can potentially suspend a coroutine, and to start a new coroutine we usually use an anonymous
suspending functions (i.e. suspending lambdas).

Let's look at async/await which is implemented in an external library, kotlinx.coroutines:

// runs the code in the background thread pool


fun asyncOverlay() = async(CommonPool) {
// start two async operations
val original = asyncLoadImage("original")
val overlay = asyncLoadImage("overlay")
// and then apply overlay to both results
applyOverlay(original.await(), overlay.await())
}

// launches new coroutine in UI context


launch(UI) {
// wait for async overlay to complete
val image = asyncOverlay().await()
// and then show it in UI
showImage(image)
}

Here, async { ... } starts a coroutine and, when we use await(), the execution of the coroutine is suspended while the operation being
awaited is executed, and is resumed (possibly on a different thread) when the operation being awaited completes.

The standard library uses coroutines to support lazily generated sequences with yield and yieldAll functions. In such a sequence, the block
of code that returns sequence elements is suspended after each element has been retrieved, and resumed when the next element is
requested. Here's an example:

import kotlin.coroutines.experimental.*

fun main(args: Array<String>) {


val seq = buildSequence {
for (i in 1..5) {
// yield a square of i
yield(i * i)
}
// yield a range
yieldAll(26..28)
}

// print the sequence


println(seq.toList())
}

Run the code above to see the result. Feel free to edit it and run again!

For more information, please refer to the coroutines documentation and tutorial.

Note that coroutines are currently considered an experimental feature, meaning that the Kotlin team is not committing to supporting the

237
backwards compatibility of this feature after the final 1.1 release.

Other
language
features

Type
aliases
A type alias allows you to define an alternative name for an existing type. This is most useful for generic types such as collections, as well
as for function types. Here is an example:

//sampleStart
typealias OscarWinners = Map<String, String>

fun countLaLaLand(oscarWinners: OscarWinners) =


oscarWinners.count { it.value.contains("La La Land") }

// Note that the type names (initial and the type alias) are interchangeable:
fun checkLaLaLandIsTheBestMovie(oscarWinners: Map<String, String>) =
oscarWinners["Best picture"] == "La La Land"
//sampleEnd

fun oscarWinners(): OscarWinners {


return mapOf(
"Best song" to "City of Stars (La La Land)",
"Best actress" to "Emma Stone (La La Land)",
"Best picture" to "Moonlight" /* ... */)
}

fun main(args: Array<String>) {


val oscarWinners = oscarWinners()

val laLaLandAwards = countLaLaLand(oscarWinners)


println("LaLaLandAwards = $laLaLandAwards (in our small example), but actually it's 6.")

val laLaLandIsTheBestMovie = checkLaLaLandIsTheBestMovie(oscarWinners)


println("LaLaLandIsTheBestMovie = $laLaLandIsTheBestMovie")
}

See the type aliases documentation and KEEP for more details.

Bound
callable
references
You can now use the :: operator to get a member reference pointing to a method or property of a specific object instance. Previously this
could only be expressed with a lambda. Here's an example:

//sampleStart
val numberRegex = "\\d+".toRegex()
val numbers = listOf("abc", "123", "456").filter(numberRegex::matches)
//sampleEnd

fun main(args: Array<String>) {


println("Result is $numbers")
}

Read the documentation and KEEP for more details.

Sealed
and
data
classes
Kotlin 1.1 removes some of the restrictions on sealed and data classes that were present in Kotlin 1.0. Now you can define subclasses of a

238
top-level sealed class on the top level in the same file, and not just as nested classes of the sealed class. Data classes can now extend
other classes. This can be used to define a hierarchy of expression classes nicely and cleanly:

//sampleStart
sealed class Expr

data class Const(val number: Double) : Expr()


data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

fun eval(expr: Expr): Double = when (expr) {


is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
}
val e = eval(Sum(Const(1.0), Const(2.0)))
//sampleEnd

fun main(args: Array<String>) {


println("e is $e") // 3.0
}

Read the sealed classes documentation or KEEPs for sealed class and data class for more detail.

Destructuring
in
lambdas
You can now use the destructuring declaration syntax to unpack the arguments passed to a lambda. Here's an example:

fun main(args: Array<String>) {


//sampleStart
val map = mapOf(1 to "one", 2 to "two")
// before
println(map.mapValues { entry ->
val (key, value) = entry
"$key -> $value!"
})
// now
println(map.mapValues { (key, value) -> "$key -> $value!" })
//sampleEnd
}

Read the destructuring declarations documentation and KEEP for more details.

Underscores
for
unused
parameters
For a lambda with multiple parameters, you can use the _ character to replace the names of the parameters you don't use:

fun main(args: Array<String>) {


val map = mapOf(1 to "one", 2 to "two")

//sampleStart
map.forEach { _, value -> println("$value!") }
//sampleEnd
}

This also works in destructuring declarations:

data class Result(val value: Any, val status: String)

fun getResult() = Result(42, "ok").also { println("getResult() returns $it") }

239
fun main(args: Array<String>) {
//sampleStart
val (_, status) = getResult()
//sampleEnd
println("status is '$status'")
}

Read the KEEP for more details.

Underscores
in
numeric
literals
Just as in Java 8, Kotlin now allows to use underscores in numeric literals to separate groups of digits:

//sampleStart
val oneMillion = 1_000_000
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010
//sampleEnd

fun main(args: Array<String>) {


println(oneMillion)
println(hexBytes.toString(16))
println(bytes.toString(2))
}

Read the KEEP for more details.

Shorter
syntax
for
properties
For properties with the getter defined as an expression body, the property type can now be omitted:

//sampleStart
data class Person(val name: String, val age: Int) {
val isAdult get() = age >= 20 // Property type inferred to be 'Boolean'
}
//sampleEnd
fun main(args: Array<String>) {
val akari = Person("Akari", 26)
println("$akari.isAdult = ${akari.isAdult}")
}

Inline
property
accessors
You can now mark property accessors with the inline modifier if the properties don't have a backing field. Such accessors are compiled in
the same way as inline functions.

//sampleStart
public val <T> List<T>.lastIndex: Int
inline get() = this.size - 1
//sampleEnd

fun main(args: Array<String>) {


val list = listOf('a', 'b')
// the getter will be inlined
println("Last index of $list is ${list.lastIndex}")
}

You can also mark the entire property as inline - then the modifier is applied to both accessors.

240
Read the inline functions documentation and KEEP for more details.

Local
delegated
properties
You can now use the delegated property syntax with local variables. One possible use is defining a lazily evaluated local variable:

import java.util.Random

fun needAnswer() = Random().nextBoolean()

fun main(args: Array<String>) {


//sampleStart
val answer by lazy {
println("Calculating the answer...")
42
}
if (needAnswer()) { // returns the random value
println("The answer is $answer.") // answer is calculated at this point
}
else {
println("Sometimes no answer is the answer...")
}
//sampleEnd
}

Read the KEEP for more details.

Interception
of
delegated
property
binding
For delegated properties, it is now possible to intercept delegate to property binding using the provideDelegate operator. For example, if
we want to check the property name before binding, we can write something like this:

class ResourceLoader<T>(id: ResourceID<T>) {


operator fun provideDelegate(thisRef: MyUI, prop: KProperty<*>): ReadOnlyProperty<MyUI, T> {
checkProperty(thisRef, prop.name)
... // property creation
}

private fun checkProperty(thisRef: MyUI, name: String) { ... }


}

fun <T> bindResource(id: ResourceID<T>): ResourceLoader<T> { ... }

class MyUI {
val image by bindResource(ResourceID.image_id)
val text by bindResource(ResourceID.text_id)
}

The provideDelegate method will be called for each property during the creation of a MyUI instance, and it can p