Skip to content

Fix infix docs #10532

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 20 additions & 21 deletions docs/docs/reference/changed-features/operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,19 @@ title: Rules for Operators

The rules for infix operators have changed in some parts:

First, an alphanumeric method can be used as an infix operator only if its definition carries an `@infix` annotation. Second, it is recommended (but not enforced) to
First, an alphanumeric method can be used as an infix operator only if its definition carries an `infix` modifier. Second, it is recommended (but not enforced) to
augment definitions of symbolic operators with `@targetName` annotations. Finally,
a syntax change allows infix operators to be written on the left in a multi-line expression.

## The @infix Annotation
## The `infix` Modifier

An `@infix` annotation on a method definition allows using the method as an infix operation. Example:
An `infix` modifier on a method definition allows using the method as an infix operation. Example:
```scala
import scala.annotation.{infix, targetName}
import scala.annotation.targetName

trait MultiSet[T] {

@infix
def union(other: MultiSet[T]): MultiSet[T]
infix def union(other: MultiSet[T]): MultiSet[T]

def difference(other: MultiSet[T]): MultiSet[T]

Expand All @@ -43,46 +42,46 @@ s1.*(s2) // also OK, but unusual
Infix operations involving alphanumeric operators are deprecated, unless
one of the following conditions holds:

- the operator definition carries an `@infix` annotation, or
- the operator definition carries an `infix` modifier, or
- the operator was compiled with Scala 2, or
- the operator is followed by an opening brace.

An alphanumeric operator is an operator consisting entirely of letters, digits, the `$` and `_` characters, or
any unicode character `c` for which `java.lang.Character.isIdentifierPart(c)` returns `true`.

Infix operations involving symbolic operators are always allowed, so `@infix` is redundant for methods with symbolic names.
Infix operations involving symbolic operators are always allowed, so `infix` is redundant for methods with symbolic names.

The `@infix` annotation can also be given to a type:
The `infix` modifier can also be given to a type:
```
@infix type or[X, Y]
infix type or[X, Y]
val x: String or Int = ...
```

### Motivation

The purpose of the `@infix` annotation is to achieve consistency across a code base in how a method or type is applied. The idea is that the author of a method decides whether that method should be applied as an infix operator or in a regular application. Use sites then implement that decision consistently.
The purpose of the `infix` modifier is to achieve consistency across a code base in how a method or type is applied. The idea is that the author of a method decides whether that method should be applied as an infix operator or in a regular application. Use sites then implement that decision consistently.

### Details

1. `@infix` is defined in package `scala.annotation`.
1. `infix` is a soft modifier. It is treated as a normal identifier except when in modifier position.

2. If a method overrides another, their infix annotations must agree. Either both are annotated with `@infix`, or none of them are.
2. If a method overrides another, their infix annotations must agree. Either both are annotated with `infix`, or none of them are.

3. `@infix` annotations can be given to method definitions. The first non-receiver parameter list of an `@infix` method must define exactly one parameter. Examples:
3. `infix` modifiers can be given to method definitions. The first non-receiver parameter list of an `infix` method must define exactly one parameter. Examples:

```scala
@infix def op(x: S): R // ok
@infix def op[T](x: T)(y: S): R // ok
@infix def op[T](x: T, y: S): R // error: two parameters
infix def op(x: S): R // ok
infix def op[T](x: T)(y: S): R // ok
infix def op[T](x: T, y: S): R // error: two parameters

@infix def (x: A) op (y: B): R // ok
@infix def (x: A) op (y1: B, y2: B): R // error: two parameters
infix def (x: A) op (y: B): R // ok
infix def (x: A) op (y1: B, y2: B): R // error: two parameters
```

4. `@infix` annotations can also be given to type, trait or class definitions that have exactly two type parameters. An infix type like
4. `infix` modifiers can also be given to type, trait or class definitions that have exactly two type parameters. An infix type like

```scala
@infix type op[X, Y]
infix type op[X, Y]
```

can be applied using infix syntax, i.e. `A op B`.
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/reference/features-classification.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ These constructs are restricted to make the language safer.
- [Given Imports](contextual/import-delegate.md): implicits now require a special form of import, to make the import clearly visible.
- [Type Projection](dropped-features/type-projection.md): only classes can be used as prefix `C` of a type projection `C#A`. Type projection on abstract types is no longer supported since it is unsound.
- [Multiversal Equality](contextual/multiversal-equality.md) implements an "opt-in" scheme to rule out nonsensical comparisons with `==` and `!=`.
- [@infix](https://github.com/lampepfl/dotty/pull/5975)
- [infix](https://github.com/lampepfl/dotty/pull/5975)
makes method application syntax uniform across code bases.

Unrestricted implicit conversions continue to be available in Scala 3.0, but will be deprecated and removed later. Unrestricted versions of the other constructs in the list above are available only under `-source 3.0-migration`.
Expand Down
5 changes: 2 additions & 3 deletions docs/docs/reference/metaprogramming/inline.md
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ val multiplication: 3 * 5 = 15

Many of these singleton operation types are meant to be used infix (as in [SLS §
3.2.8](https://www.scala-lang.org/files/archive/spec/2.12/03-types.html#infix-types)),
and are annotated with [`@infix`](scala.annotation.infix) accordingly.
and are annotated accordingly with [`infix`] modifiers.

Since type aliases have the same precedence rules as their term-level
equivalents, the operations compose with the expected precedence rules:
Expand All @@ -518,9 +518,8 @@ match type can dispatch to the correct implementation:

```scala
import scala.compiletime.ops._
import scala.annotation.infix

@infix type +[X <: Int | String, Y <: Int | String] = (X, Y) match {
infix type +[X <: Int | String, Y <: Int | String] = (X, Y) match {
case (Int, Int) => int.+[X, Y]
case (String, String) => string.+[X, Y]
}
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/reference/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ These constructs are restricted to make the language safer.
- [Given Imports](contextual/given-imports.md): implicits now require a special form of import, to make the import clearly visible.
- [Type Projection](dropped-features/type-projection.md): only classes can be used as prefix `C` of a type projection `C#A`. Type projection on abstract types is no longer supported since it is unsound.
- [Multiversal Equality](contextual/multiversal-equality.md) implements an "opt-in" scheme to rule out nonsensical comparisons with `==` and `!=`.
- [@infix annotations](changed-features/operators.md)
- [infix](changed-features/operators.md)
make method application syntax uniform across code bases.

Unrestricted implicit conversions continue to be available in Scala 3.0, but will be deprecated and removed later. Unrestricted versions of the other constructs in the list above are available only under `-source 3.0-migration`.
Expand Down