From 5e76c824f48ff7584472d4525944129f0716d896 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 10 Aug 2018 20:03:03 +0200 Subject: [PATCH 01/11] Change spec, renaming `transparent` to `rewrite`. - also, introduce `rewrite` as a modifier for match expressions and conditionals. - keep `transparent` for methods that are not erased, and don't inline by themselves, yet can be inlined from rewritten code. --- docs/docs/typelevel.md | 210 ++++++++++++++++++++++++++--------------- 1 file changed, 136 insertions(+), 74 deletions(-) diff --git a/docs/docs/typelevel.md b/docs/docs/typelevel.md index 3272458b9506..b9e24f753341 100644 --- a/docs/docs/typelevel.md +++ b/docs/docs/typelevel.md @@ -23,9 +23,9 @@ ideal. In particular: ## The Core Idea -A simple principle underlies the new design: Typelevel programming in Scala 3 means reducing terms and taking their types afterwards. Specifically, if `f` is a _transparent_ function applied to some arguments `es` then the type of the application `f(es)` is the type of the term to which `f(es)` reduces. Since reduction can specialize types, that type can be more specific than `f`'s declared result type. Type-level programming in Scala 3 is thus a form of partial evaluation or [type specialization](http://www.cse.chalmers.se/~rjmh/Papers/typed-pe.html). +A simple principle underlies the new design: Typelevel programming in Scala 3 means reducing terms and taking their types afterwards. Specifically, if `f` is a _rewrite_ method applied to some arguments `es` then the type of the application `f(es)` is the type of the term to which `f(es)` reduces. Since reduction can specialize types, that type can be more specific than `f`'s declared result type. Type-level programming in Scala 3 is thus a form of partial evaluation or [type specialization](http://www.cse.chalmers.se/~rjmh/Papers/typed-pe.html). -## Transparent Functions +## Rewrite Methods Consider the standard definition of typelevel Peano numbers: ```scala @@ -37,24 +37,24 @@ case class S[N <: Nat](n: N) extends Nat A function that maps non-negative integers to Peano numbers can be defined as follows: ```scala -transparent def toNat(n: Int): Nat = n match { +rewrite def toNat(n: Int): Nat = rewrite n match { case 0 => Z case n if n > 0 => S(toNat(n - 1)) } ``` -Without the `transparent` modifier, an application of `toNat(3)` would have type `Nat`, as this -is the method's declared return type. But with `transparent`, the call to `toNat(3)` gets reduced _at compile time_ as follows: +Without the `rewrite` modifier, an application of `toNat(3)` would have type `Nat`, as this +is the method's declared return type. But with `rewrite`, the call to `toNat(3)` gets reduced _at compile time_ as follows: toNat(3) -> - 3 match { + rewrite 3 match { case 0 => Z case n if n > 0 => S(toNat(n - 1)) } -> S(toNat(2)) -> - S(2 match { + S(rewrite 2 match { case 0 => Z case n if n > 0 => S(toNat(n - 1)) }) @@ -63,7 +63,7 @@ is the method's declared return type. But with `transparent`, the call to `toNat -> -> S(S(S(toNat(0)))) -> - S(S(S(0 match { + S(S(S(rewrite 0 match { case 0 => Z case n if n > 0 => S(toNat(n - 1)) }))) @@ -72,30 +72,22 @@ is the method's declared return type. But with `transparent`, the call to `toNat The type of `toNat(3)` is the type of its result, `S[S[S[Z]]]`, which is a subtype of the declared result type `Nat`. -A `transparent` modifier on a method definition indicates that any application of the defined method outside a transparent method definition will be expanded to its right hand side, where formal parameters get bound to actual arguments. The right side will be further simplified using a set of rewrite rules given below. +A `rewrite` modifier on a method definition indicates that any application of the defined method outside a rewrite method definition will be expanded to its right hand side, where formal parameters get bound to actual arguments. The right side will be further simplified using a set of rewrite rules given below. -Top-level `match` expressions in transparent methods are treated specially. An expression is considered top-level if it appears +## Rewrite Matches - - as the right hand side of the `transparent` function, or - - as the final expression of a top-level block, or - - as a branch of a top-level match expression. +A match expression in the body of a rewrite meyhod may be prefixed itself with the `rewrite` modifier. Such a rewrite match _must_ be rewritten at compile-time. That is, if there is enough static information to unambiguously pick one of its branches, the expression +is rewritten to that branch. Otherwise a compile-time error is signalled indicating that the match cannot be reduced. -A top-level match expression in a transparent _must_ be rewritten at compile-time. That is, if there is enough static information to unambiguously pick one of its branches, the expression -is rewritten to that branch. Otherwise a compile-time error is signalled indicating that the match is ambiguous. If one wants to have a transparent function expand to a match expression that cannot be evaluated statically in this fashion, one can always enclose the expression in a -```scala -locally { ... } -``` -block, which de-classifies it as a top-level expression. (`locally` is a function in `Predef` which simply returns its argument.) - -As another example, consider the following two functions over tuples: +As examples, consider the following two functions over tuples: ```scala -transparent def concat(xs: Tuple, ys: Tuple): Tuple = xs match { +rewrite def concat(xs: Tuple, ys: Tuple): Tuple = rewrite xs match { case () => ys case (x, xs1) => (x, concat(xs1, ys)) } -transparent def nth(xs: Tuple, n: Int): Any = xs match { +rewrite def nth(xs: Tuple, n: Int): Any = rewrite xs match { case (x, _) if n == 0 => x case (_, xs1) if n > 0 => nth(xs1, n - 1) } @@ -121,23 +113,23 @@ nth(as, -1) : Nothing nth(concat(as, bs), 3) : List[Int] ``` -In each of these cases, the result is obtained by expanding the transparent function(s), simplifying (reducing) their right hand sides, and taking the type of the result. As an example, the applications `concat(as, bs)` and `nth(as, 1)` would produce expressions like these: +In each of these cases, the result is obtained by expanding the rewrite method(s), simplifying (reducing) their right hand sides, and taking the type of the result. As an example, the applications `concat(as, bs)` and `nth(as, 1)` would produce expressions like these: ```scala concat(as, bs) --> (as._1, { val a$1 = as._2; (a$1._1, bs) } nth(as, 1) --> { val a$1 = as._2; a$1._1 } ``` If tuples get large, so do the expansions. For instance, the size of the expansion of a valid selection `nth(xs, n)` is proportional to `n`. We will show later a scheme to avoid this code blowup using `erased` values. -The following expressions would all give compile-time errors since a toplevel `match` could not be reduced: +The following expressions would all give compile-time errors since a `rewrite` `match` could not be reduced: ```scala concat(tp, bs) nth(tp, 0) nth(as, 2) nth(as -1) ``` -It's possible to add more cases to a toplevel match, thereby moving an error from compile-time to runtime. For instance, here is a version of `nth` that throws a runtime error in case the index is out of bounds: +It's possible to add more cases to a rewrite match, thereby moving an error from compile-time to runtime. For instance, here is a version of `nth` that throws a runtime error in case the index is out of bounds: ```scala -transparent def nthDynamic(xs: Tuple, n: Int): Any = xs match { +rewrite def nthDynamic(xs: Tuple, n: Int): Any = rewrite xs match { case (x, _) if n == 0 => x case (_, xs1) => nthDynamic(xs1, n - 1) case () => throw new IndexOutOfBoundsException @@ -161,12 +153,49 @@ Here is an expansion of `nthDynamic` applied to a tuple `as: (Int, String)` and ``` So the end result of the expansion is the expression `throw new IndexOutOfBoundsException`, which has type `Nothing`. It is important to note that programs are treated as _data_ in this process, so the exception will not be thrown at compile time, but only if the program is run after it compiles without errors. +## Rewrite Conditionals + +Like matches, if-then-else expressions can also be prefixed with the `rewrite` modifier. Such rewrite conditional must have conditions that with a compile-time boolean result. The conditional then recuces to one of its branches depending on whether the condition is knwon to be `true` or to be `false`. + +For instance, here is an alternative version of `toNat` formulated with a conditional instead of a `match`. +```scala +rewrite def toNat(n: Int): Nat = + rewrite if n == 0 then Z + else S(toNat(n - 1)) +} +``` + +## Diagnostics + +The last definition of `toNat` has a problem. When applied to a negative argument such as `-1` it would lead to an infinitely recurring expansion +``` + toNat(-1) --> toNat(-2) --> toNat(-3) --> ... +``` +This will give a compile-time error indicating that the maximal number of allowed expansions is exceeded. The previous `match` based version of `toNat` did not have this problem since we could guard each case with the correct precondition as a guard. So with the first version,`toNat(-1)` would have produced an irreducible match error instead of an infinite expansion error. This is better but ideally we'd like to see a more customized error message instad, such as +``` + Illegal argument for `toNat`: -1 is negative +``` +To implement this, there is a predefined method +```scala +rewrite def error(msg: String): Unit +``` +in the `typelevel` package. An application of this method will always give a compile-time error with the given string argument as error message. Using this method, `toNat` can be +formulated as follows: +```scala +import scala.typelevel.error +rewrite def toNat(n: Int): Nat = + rewrite + if n == 0 then Z + else if n > 0 then S(toNat(n - 1)) + else error("Illegal argument for `toNat`: $n is negative") +} +``` + ## Rewrite Rules The following rewrite rules are performed when simplifying inlined bodies: - - **Pattern matching:** Pattern matches in toplevel match expressions are evaluated and the case with the first - pattern that is statically known to match is chosen. A pattern match `E match { Case_1 ... Case_n }` is translated as follows: + - **Pattern matching:** Pattern matches in `rewrite match` expressions are evaluated and the case with the first pattern that is statically known to match is chosen. A pattern match `rewrite E match { Case_1 ... Case_n }` is translated as follows: - We first create a binding `val $scrutinee_n = E` for the scrutinee of the match. - Matching a pattern `P` takes as additional input the current scrutinee reference `S` (this is `$scrutinee_n` for toplevel patterns). It either returns with a sequence of additional bindings or fails. The rules depend on the form of the pattern `P`. @@ -186,8 +215,9 @@ The following rewrite rules are performed when simplifying inlined bodies: - If `P` is a pattern with a guard `Q if E`, the match succeeds if matching `Q` succeeds and the guard `E` is statically known to be `true`. - The first case `case P => E` with a matching pattern `P` is chosen. The match is then rewritten - to `{ Bs; E }` where `Bs` are the bindings generated by the match of `P`. + The first case `case P => E` with a matching pattern `P` is chosen. The match is then rewritten to `{ Bs; E }` where `Bs` are the bindings generated by the match of `P`. + + Note that matches are only evaluated if they are marked `rewrite`. - **Reduction of projections:** An expression `E_0(E_1, ..., E_i, ...E_n).f_i`, where @@ -229,24 +259,47 @@ The following rewrite rules are performed when simplifying inlined bodies: Dropping a binding might make other bindings redundant. Garbage collection proceeds until no further bindings can be dropped. -## Restrictions for Transparent and Typelevel Functions +All rules are sound wrt to the language semantics. However, it should be noted that rewriting a `rewrite match` at compile time does not guarantee to pick the same case as every execution at runtime of the same match without the `rewrite`. Here is an example: +```scala +trait A +trait B + +rewrite def f(x: Any) = rewrite x match { + case _: A => "A" + case _: B => "B" +} +def g(x: Any) = x match { + case _: A => "A" + case _: B => "B" +} + +val b1: B = new B {} +val b2: B = new A with B {} + +f(b1) // rewrites to "B" +g(b1) // evaluates to "B" +f(b2) // rewrites to "B" +g(b2) // evaluates to "A" +``` +Since both applications of `f` are passed arguments with static type `B`, the second case `"B"` is chosen in each case. By contrast, the application `g(b2)` yields `"A"`, since +even though the static type of `b2` is `B`, its runtime value is of type `A & B`, which +matches the first case. -Transparent methods are effectively final; they may not be overwritten. +## Restrictions for Rewrite Methods -If a transparent -method has a toplevel match expression or a toplevel splice `~` on its right-hand side, -it is classified as a typelevel method that can _only_ be executed at compile time. For typelevel methods two more restrictions apply: +Rewrite methods are effectively final; they may not be overwritten. Rewrite methods +must satisfy two more restrictions, which ensure that no code needs to be generated for them. 1. They must be always fully applied. 2. They may override other methods only if one of the overridden methods is concrete. -The right hand side of a typelevel method is never invoked by dynamic dispatch. As an example consider a situation like the following: +The right hand side of a rewrite method is never invoked by dynamic dispatch. As an example consider a situation like the following: ```scala class Iterable[T] { def foreach(f: T => Unit): Unit = ... } class List[T] extends Iterable[T] { - override transparent def foreach(f: T => Unit): Unit = ... + override rewrite def foreach(f: T => Unit): Unit = ... } val xs: Iterable[T] = ... val ys: List[T] = ... @@ -255,14 +308,13 @@ xs.foreach(f) // calls Iterable's foreach ys.foreach(f) // expands to the body of List's foreach zs.foreach(f) // calls Iterable's foreach ``` -It follows that an overriding typelevel method should implement exactly the same semantics as the -method it overrides (but possibly more efficiently). +It follows that an overriding rewrite method should implement exactly the same semantics as the method it overrides (but possibly more efficiently). ## Matching on Types -We have seen so far transparent functions that take terms (tuples and integers) as parameters. What if we want to base case distinctions on types instead? For instance, one would like to be able to write a function `defaultValue`, that, given a type `T` +We have seen so far rewrite methods that take terms (tuples and integers) as parameters. What if we want to base case distinctions on types instead? For instance, one would like to be able to write a function `defaultValue`, that, given a type `T` returns optionally the default value of `T`, if it exists. In fact, we can already express -this using ordinary match expressions and a simple helper function, `scala.typelevel.erasedValue`, which is defined as follows: +this using rewrite match expressions and a simple helper function, `scala.typelevel.erasedValue`, which is defined as follows: ```scala erased def erasedValue[T]: T = ??? ``` @@ -270,7 +322,7 @@ The `erasedValue` function _pretends_ to return a value of its type argument `T` Using `erasedValue`, we can then define `defaultValue` as follows: ```scala -transparent def defaultValue[T] = erasedValue[T] match { +rewrite def defaultValue[T] = rewrite erasedValue[T] match { case _: Byte => Some(0: Byte) case _: Char => Some(0: Char) case _: Short => Some(0: Short) @@ -293,7 +345,7 @@ defaultValue[AnyVal] = None ``` As another example, consider the type-level inverse of `toNat`: given a _type_ representing a Peano number, return the integer _value_ corresponding to it. Here's how this can be defined: ```scala -transparent def toInt[N <: Nat]: Int = erasedValue[N] match { +rewrite def toInt[N <: Nat]: Int = rewrite erasedValue[N] match { case _: Z => 0 case _: S[n] => toInt[n] + 1 } @@ -308,7 +360,7 @@ class Typed[T](val value: T) { type Type = T } ``` Here is a version of `concat` that computes at the same time a result and its type: ```scala -transparent def concatTyped(xs: Tuple, ys: Tuple): Typed[_ <: Tuple] = xs match { +rewrite def concatTyped(xs: Tuple, ys: Tuple): Typed[_ <: Tuple] = rewrite xs match { case () => Typed(ys) case (x, xs1) => Typed((x, concatTyped(xs1, ys).value)) } @@ -316,7 +368,7 @@ transparent def concatTyped(xs: Tuple, ys: Tuple): Typed[_ <: Tuple] = xs match ## Avoiding Code Explosion -Recursive transparent functions implement a form of loop unrolling through inlining. This can lead to very large generated expressions. The code explosion can be avoided by calling typed versions of the transparent functions to define erased values, of which just the typed part is used afterwards. Here is how this can be done for `concat`: +Recursive rewrite methods implement a form of loop unrolling through inlining. This can lead to very large generated expressions. The code explosion can be avoided by calling typed versions of the rewrite methods to define erased values, of which just the typed part is used afterwards. Here is how this can be done for `concat`: ```scala def concatImpl(xs: Tuple, ys: Tuple): Tuple = xs match { @@ -324,26 +376,26 @@ def concatImpl(xs: Tuple, ys: Tuple): Tuple = xs match { case (x, xs1) => (x, concatImpl(xs1, ys)) } -transparent def concat(xs: Tuple, ys: Tuple): Tuple = { - erased val r = concatTyped(xs, ys) - concatImpl(xs, ys).asInstanceOf[r.Type] +rewrite def concat(xs: Tuple, ys: Tuple): Tuple = { + erased val resTpe = concatTyped(xs, ys) + concatImpl(xs, ys).asInstanceOf[resTpe.Type] } ``` -The transparent `concat` method makes use of two helper functions, `concatTyped` (described in the last section) and `concatImpl`. `concatTyped` is called as the right hand side of an `erased` value `r`. Since `r` is `erased`, no code is generated for its definition. -`concatImpl` is a regular, non-transparent function that implements `concat` on generic tuples. It is not inlineable, and its result type is always `Tuple`. The actual code for `concat` calls `concatImpl` and casts its result to type `r.Type`, the computed result type of the concatenation. This gives the best of both worlds: Compact code and expressive types. +The `concat` rewrite method makes use of two helper functions, `concatTyped` (described in the last section) and `concatImpl`. `concatTyped` is called as the right hand side of an `erased` value `resTpe`. Since `resTpe` is `erased`, no code is generated for its definition. +`concatImpl` is a regular, non-rewrite method that implements `concat` on generic tuples. It is not inlineable, and its result type is always `Tuple`. The actual code for `concat` calls `concatImpl` and casts its result to type `resTpe.Type`, the computed result type of the concatenation. This gives the best of both worlds: Compact code and expressive types. -One might criticize that this scheme involves code duplication. In the example above, the recursive `concat` algorithm had to be implemented twice, once as a regular function, the other time as a transparent function. However, in practice it is is quite likely that the regular function would use optimized data representatons and algorithms that do not lend themselves easily to a typelevel interpretation. In these cases a dual implementation is required anyway. +One might criticize that this scheme involves code duplication. In the example above, the recursive `concat` algorithm had to be implemented twice, once as a regular method, the other time as a rewrite method. However, in practice it is is quite likely that the regular function would use optimized data representatons and algorithms that do not lend themselves easily to a typelevel interpretation. In these cases a dual implementation is required anyway. ## Code Specialization -Transparent functions are a convenient means to achieve code specialization. As an example, consider implementing a math library that implements (among others) a `dotProduct` method. Here is a possible implementation of `MathLib` with some user code. +Rewrite methods are a convenient means to achieve code specialization. As an example, consider implementing a math library that implements (among others) a `dotProduct` method. Here is a possible implementation of `MathLib` with some user code. ```scala abstract class MathLib[N : Numeric] { def dotProduct(xs: Array[N], ys: Array[N]): N } object MathLib { - transparent def apply[N](implicit n: Numeric[N]) = new MathLib[N] { + rewrite def apply[N](implicit n: Numeric[N]) = new MathLib[N] { import n._ def dotProduct(xs: Array[N], ys: Array[N]): N = { require(xs.length == ys.length) @@ -373,7 +425,7 @@ Even though the `dotProduct` code looks simple, there is a lot of hidden complex - It uses unbounded generic arrays, which means code on the JVM needs reflection to access their elements - All operations on array elements forward to generic operations in class `Numeric`. -It would be quite hard for even a good optimizer to undo the generic abstractions and replace them with something simpler if `N` is specialized to a primitive type like `Double`. But since `apply` is marked `transparent`, the specialization happens automatically as a result of inlining the body of `apply` with the new types. Indeed, the specialized version of `dotProduct` looks like this: +It would be quite hard for even a good optimizer to undo the generic abstractions and replace them with something simpler if `N` is specialized to a primitive type like `Double`. But since `apply` is a rewrite method, the specialization happens automatically as a result of inlining the body of `apply` with the new types. Indeed, the specialized version of `dotProduct` looks like this: ``` def dotProduct(xs: Array[Double], ys: Array[Double]): Double = { require(xs.length == ys.length) @@ -386,12 +438,11 @@ def dotProduct(xs: Array[Double], ys: Array[Double]): Double = { s } ``` -In other words, specialization with transparent functions allows "abstraction without regret". The price to pay for this -is the increase of code size through inlining. That price is often worth paying, but inlining decisions need to be considered carefully. +In other words, specialization with rewrite methods allows "abstraction without regret". The price to pay for this is the increase of code size through inlining. That price is often worth paying, but inlining decisions need to be considered carefully. ## Implicit Matches -It is foreseen that many areas of typelevel programming can be done with transparent functions instead of implicits. But sometimes implicits are unavoidable. The problem so far was that the Prolog-like programming style of implicit search becomes viral: Once some construct depends on implicit search it has to be written as a logic program itself. Consider for instance the problem +It is foreseen that many areas of typelevel programming can be done with rewrite methods instead of implicits. But sometimes implicits are unavoidable. The problem so far was that the Prolog-like programming style of implicit search becomes viral: Once some construct depends on implicit search it has to be written as a logic program itself. Consider for instance the problem of creating a `TreeSet[T]` or a `HashSet[T]` depending on whether `T` has an `Ordering` or not. We can create a set of implicit definitions like this: ```scala trait SetFor[T, S <: Set[T]] @@ -415,7 +466,7 @@ There are some proposals to improve the situation in specific areas, for instanc By contrast, the new `implicit match` construct makes implicit search available in a functional context. To solve the problem of creating the right set, one would use it as follows: ```scala -transparent def setFor[T]: Set[T] = implicit match { +rewrite def setFor[T]: Set[T] = implicit match { case ord: Ordering[T] => new TreeSet[T] case _ => new HashSet[T] } @@ -426,8 +477,17 @@ Patterns are tried in sequence. The first case with a pattern `x: T` such that a of type `T` can be summoned is chosen. The variable `x` is then bound to the implicit value for the remainder of the case. It can in turn be used as an implicit in the right hand side of the case. It is an error if one of the tested patterns gives rise to an ambiguous implicit search. -Implicit matches can only occur as toplevel match expressions of transparent methods. This ensures that -all implicit searches are done at compile-time. +An implicit matches is considered to be a special kind of a rewrite match. This means it can only occur in the body of a rewrite method, and it must be reduced at compile time. + +## Transparent Methods + +Recall that rewrite methods are always erased. Sometimes, this is inconvenient. Consider for example a type with a user-defined `unapply` method. If the method is marked as `rewrite` +pattern reduction can "see inside" the method by expanding it. But the extractor can then not be used at run-time. To allow both use cases at the same time, one can use the `transparent` modifier. E.g. +```scala +transparent def unapply(x: C) = ... +``` +Transparent methods are regular methods that can be called at runtime. But when an application of a transparent method occurs in the inlined body of a rewrite method, +the method is itself inlined, just like if it had been marked `rewrite`. ## Transparent Values @@ -440,28 +500,29 @@ The right hand side of a `transparent` value definition must be a pure expressi Transparent values are effectively final; they may not be overridden. In Scala-2, constant values had to be expressed using `final`, which gave an unfortunate double meaning to the modifier. The `final` syntax is still supported in Scala 3 for a limited time to support cross-building. -The `transparent` modifier can also be used for value parameters of `transparent` methods. Example +The `transparent` modifier can also be used for value parameters of `rewrite` methods. Example ```scala -transparent def power(x: Double, transparent n: Int) = ... +rewrite def power(x: Double, transparent n: Int) = ... ``` If a `transparent` modifier is given, corresponding arguments must be pure expressions of constant type. However, the restrictions on right-hand sides or arguments mentioned in this section do not apply in code that is -itself in a `transparent` method. In other words, constantness checking is performed only when a `transparent` method +itself in a `rewrite` method. In other words, constantness checking is performed only when a `transparent` method is expanded, not when it is defined. -## Transparent and Inline +## Rewrite and Inline -Dotty up to version 0.9 also supports an `inline` modifier. `inline` is similar to `transparent` in that inlining happens during type-checking. However, `inline` does not change the types of the inlined expressions. The expressions are instead inlined in the form of trees that are already typed. +Dotty up to version 0.9 also supports an `inline` modifier. `inline` is similar to `rewrite` in that inlining happens during type-checking. However, `inline` does not change the types of the inlined expressions. The expressions are instead inlined in the form of trees that are already typed. -Since there is very large overlap between `transparent` and `inline`, we propose to drop `inline` as a separate modifier. The current `@inline` annotation, which represents a hint to the optimizer that inlining might be advisable, will remain unaffected. +Since there is large overlap between `rewrite` and `inline`, we have dropped `inline` as a separate modifier. The current `@inline` annotation, which represents a hint to the optimizer that inlining might be advisable, remains unaffected. ## Relationship to "TypeOf" -This document describes one particular way to conceptualize and implement transparent methods. An implementation is under way in #4616. An alternative approach is explored in #4671. The main difference is that the present proposal uses the machinery of partial evaluation (PE) whereas #4671 uses the machinery of (term-) dependent types (DT). +This document describes a scheme to implement typelevel computations using rewrite methods. An alternative approach is explored in #4671 where instead of rewrite methods one has +transparent methods that can specialize types without rewriting terms. The main difference is that the present proposal uses the machinery of partial evaluation (PE) whereas #4671 uses the machinery of (term-) dependent types (DT). -The PE approach reduces the original right-hand side of a transparent function via term rewriting. The right hand side is conceptually the term as it is written down, closed over the environment where the transparent function was defined. This is implemented by rewriting and then re-type-checking the original untyped tree, but with typed leaves that refer to the tree's free variables. The re-type-checking with more specific argument types can lead to a type derivation that is quite different -than the original typing of the transparent method's right hand side. Types might be inferred to be more specific, overloading resolution could pick different alternatives, and implicit searches might yield different results or might be elided altogether. +The PE approach reduces the original right-hand side of a rewrite method via term rewriting. The right hand side is conceptually the term as it is written down, closed over the environment where the rewrite method was defined. This is implemented by rewriting and then re-type-checking the original untyped tree, but with typed leaves that refer to the tree's free variables. The re-type-checking with more specific argument types can lead to a type derivation that is quite different +than the original typing of the rewrite method's right hand side. Types might be inferred to be more specific, overloading resolution could pick different alternatives, and implicit searches might yield different results or might be elided altogether. This flexibility is what makes code specialization work smoothly. By constrast, the DT approach typechecks the right hand side of a transparent function in a special way. Instead of @@ -485,15 +546,16 @@ By contrast, here are some advantages of PE over DT: + It uses the standard type checker and typing rules with no need to go to full dependent types (only path dependent types instead of full term-dependencies). + + It simplify more cases. + It can do code specialization. + It can do implicit matches. + It can also serve as the inlining mechanism for implementing macros with staging (see next section). ## Relationship To Meta Programming -Transparent functions are a safer alternative to the whitebox macros in Scala 2. Both share the principle that some function applications get expanded such that the types of these applications are the types of their expansions. But the way the expansions are performed is completely different: For transparent functions, expansions are simply beta reduction (_aka_ inlining) and a set of rewrite rules that are sound wrt the language semantics. All rewritings are performed by the compiler itself. It is really as if some parts of the program reduction are performed early, which is the essence of partial evaluation. +Rewrite methods are a safer alternative to the whitebox macros in Scala 2. Both share the principle that some function applications get expanded such that the types of these applications are the types of their expansions. But the way the expansions are performed is completely different: For rewrite methods, expansions are simply beta reduction (_aka_ inlining) and a set of rewrite rules that are patterned after the language semantics. All rewritings are performed by the compiler itself. It is really as if some parts of the program reduction are performed early, which is the essence of partial evaluation. -By contrast, Scala 2 macros mean that user-defined code is invoked to process program fragments as data. The result of this computation is then embedded instead of the macro call. Macros are thus a lot more powerful than transparent functions, but also a lot less safe. +By contrast, Scala 2 macros mean that user-defined code is invoked to process program fragments as data. The result of this computation is then embedded instead of the macro call. Macros are thus a lot more powerful than rewrite methods, but also a lot less safe. Functionality analogous to blackbox macros in Scala-2 is available in Scala-3 through its [principled meta programming](https://dotty.epfl.ch/docs/reference/principled-meta-programming.html) system: Code can be turned into data using quotes `(')`. Code-returning computations can be inserted into quotes using splices `(~)`. A splice outside quotes means that the spliced computation is _run_, which is the analogue of invoking a macro. Quoted code can be inspected using reflection on Tasty trees. @@ -506,11 +568,11 @@ def mImpl(x: Tree) = ... ``` Here's analogous functionality in Scala-3: ```scala -transparent def m(x: T) = ~mImpl('x) +rewrite def m(x: T) = ~mImpl('x) ... def mImpl(x: Expr[T]) = ... ``` -The new scheme is more explicit and orthogonal: The usual way to define a macro is as a transparent function that invokes with `~` a macro library method, passing it quoted arguments as data. The role of the transparent function is simply to avoid to have to write the splices and quotes in user code. +The new scheme is more explicit and orthogonal: The usual way to define a macro is as a rewrite method that invokes with `~` a macro library method, passing it quoted arguments as data. The role of the rewrite method is simply to avoid to have to write the splices and quotes in user code. One important difference between the two schemes is that the reflective call implied by `~` is performed _after_ the program is typechecked. Besides a better separation of concerns, this also provides a more predictable environment for macro code to run in. From ccc78454b978d120aab585d526e7ab2b124683a2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 12 Aug 2018 20:13:52 +0200 Subject: [PATCH 02/11] Rename transparent methods -> rewrite methods Also implements rewrite matches and rewrite ifs. Keeps transparent as a separate modifier with meaning: "inline if called from a rewrite context". --- bench/tests/power-macro/PowerMacro.scala | 2 +- .../dotty/tools/dotc/CompilationUnit.scala | 2 +- compiler/src/dotty/tools/dotc/Run.scala | 2 +- .../src/dotty/tools/dotc/ast/TreeInfo.scala | 2 +- compiler/src/dotty/tools/dotc/ast/Trees.scala | 16 +++ compiler/src/dotty/tools/dotc/ast/untpd.scala | 6 +- .../tools/dotc/config/ScalaSettings.scala | 4 +- .../dotty/tools/dotc/core/Annotations.scala | 2 +- .../src/dotty/tools/dotc/core/Contexts.scala | 4 + .../src/dotty/tools/dotc/core/Flags.scala | 18 ++- compiler/src/dotty/tools/dotc/core/Mode.scala | 4 +- .../src/dotty/tools/dotc/core/NameKinds.scala | 8 +- .../src/dotty/tools/dotc/core/NameOps.scala | 8 +- .../src/dotty/tools/dotc/core/Names.scala | 10 +- .../tools/dotc/core/SymDenotations.scala | 23 +++- .../src/dotty/tools/dotc/core/TypeOps.scala | 8 +- .../tools/dotc/core/tasty/TastyFormat.scala | 8 +- .../tools/dotc/core/tasty/TreePickler.scala | 11 +- .../tools/dotc/core/tasty/TreeUnpickler.scala | 10 +- .../dotty/tools/dotc/parsing/Parsers.scala | 76 +++++++---- .../dotty/tools/dotc/parsing/Scanners.scala | 2 +- .../src/dotty/tools/dotc/parsing/Tokens.scala | 20 +-- .../dotty/tools/dotc/quoted/ToolboxImpl.scala | 2 +- .../reporting/diagnostic/ErrorMessageID.java | 4 +- .../dotc/reporting/diagnostic/messages.scala | 16 +-- .../dotc/{rewrite => rewrites}/Rewrites.scala | 6 +- .../src/dotty/tools/dotc/sbt/ExtractAPI.scala | 2 +- .../tools/dotc/tastyreflect/FlagSet.scala | 2 + .../tools/dotc/transform/AccessProxies.scala | 2 +- .../dotc/transform/ArrayConstructors.scala | 8 +- .../dotty/tools/dotc/transform/Erasure.scala | 8 +- .../dotc/transform/InterceptedMethods.scala | 12 +- .../tools/dotc/transform/LambdaLift.scala | 2 +- .../dotty/tools/dotc/transform/LazyVals.scala | 2 +- .../tools/dotc/transform/PostTyper.scala | 6 +- .../dotc/transform/PruneErasedDefs.scala | 10 +- .../tools/dotc/transform/ReifyQuotes.scala | 30 ++--- .../tools/dotc/transform/RenameLifted.scala | 6 +- .../dotty/tools/dotc/transform/Splicer.scala | 6 +- .../tools/dotc/transform/TreeChecker.scala | 4 +- .../src/dotty/tools/dotc/typer/Checking.scala | 16 ++- .../dotty/tools/dotc/typer/Implicits.scala | 4 +- .../src/dotty/tools/dotc/typer/Inliner.scala | 107 +++++++-------- .../src/dotty/tools/dotc/typer/Namer.scala | 24 +--- ...nsparent.scala => PrepareInlineable.scala} | 34 ++--- .../dotty/tools/dotc/typer/ProtoTypes.scala | 4 +- .../src/dotty/tools/dotc/typer/ReTyper.scala | 1 - .../dotty/tools/dotc/typer/RefChecks.scala | 24 ++-- .../src/dotty/tools/dotc/typer/Typer.scala | 44 +++--- .../tools/dotc/typer/VarianceChecker.scala | 2 +- .../backend/jvm/InlineBytecodeTests.scala | 2 +- .../dotty/tools/dotc/CompilationTests.scala | 2 +- .../dotc/parsing/ModifiersParsingTest.scala | 2 + .../dotc/reporting/ErrorMessagesTests.scala | 8 +- docs/docs/internals/syntax.md | 10 +- docs/docs/reference/inline.md | 36 ++--- .../reference/principled-meta-programming.md | 28 ++-- docs/sidebar.yml | 2 +- .../src/scala/annotation/internal/Body.scala | 2 +- library/src/scala/quoted/Expr.scala | 4 +- library/src/scala/quoted/QuoteError.scala | 2 +- library/src/scala/tasty/TopLevelSplice.scala | 2 +- library/src/scala/tasty/reflect/FlagSet.scala | 3 +- .../src/scala/tasty/util/ShowSourceCode.scala | 1 + .../inline/changes/B1.scala | 2 +- .../inline/changes/B2.scala | 2 +- .../inline/changes/B3.scala | 2 +- .../quote-run-in-macro-1/quoted_1.scala | 2 +- .../quote-run-in-macro-2/quoted_1.scala | 2 +- tests/neg/i1568.scala | 2 +- tests/neg/i1605.scala | 2 +- tests/neg/i2006.scala | 4 +- tests/neg/i2421.scala | 14 +- tests/neg/i2564.scala | 2 +- tests/neg/i2564b.scala | 2 +- tests/neg/i2901.scala | 2 +- tests/neg/i4433.scala | 2 +- tests/neg/i4493-b.scala | 2 +- tests/neg/i4493.scala | 2 +- tests/neg/implicitMatch-ambiguous.scala | 2 +- tests/neg/implicitMatch-syntax.scala | 10 +- tests/neg/inline-i1773.scala | 2 +- tests/neg/inline-position/A_1.scala | 2 +- tests/neg/inlineAccess/C_1.scala | 2 +- tests/neg/inlinevals.scala | 10 +- tests/neg/power.scala | 2 +- tests/neg/quote-MacroOverride.scala | 4 +- tests/neg/quote-complex-top-splice.scala | 8 +- tests/neg/quote-error-2/Macro_1.scala | 2 +- tests/neg/quote-error/Macro_1.scala | 2 +- tests/neg/quote-exception/Macro_1.scala | 2 +- tests/neg/quote-interpolator-core-old.scala | 6 +- tests/neg/quote-macro-2-splices.scala | 2 +- tests/neg/quote-macro-complex-arg-0.scala | 2 +- tests/neg/quote-macro-splice.scala | 8 +- tests/neg/quote-pcp-in-arg.scala | 2 +- tests/neg/quote-splice-interpret-1.scala | 2 +- tests/neg/splice-in-top-level-splice-1.scala | 2 +- tests/neg/splice-in-top-level-splice-2.scala | 2 +- tests/neg/tasty-macro-assert/quoted_1.scala | 2 +- tests/neg/transparent-override/A_1.scala | 2 +- tests/neg/transparent-override/B_2.scala | 2 +- tests/neg/typelevel-erased-leak.scala | 2 +- tests/neg/typelevel-noeta.scala | 4 +- tests/neg/typelevel-nomatch.scala | 2 +- tests/neg/typelevel.scala | 16 +-- tests/pickling/i2166.scala | 2 +- tests/pickling/i3608.scala | 2 +- tests/pickling/i4006.scala | 2 +- tests/pickling/i4006b.scala | 2 +- tests/pickling/i4006c.scala | 2 +- tests/pickling/transparent.scala | 2 +- tests/pos-with-compiler/quote-0.scala | 4 +- .../quote-assert/quoted_2.scala | 2 +- .../pos-with-compiler/tasty/definitions.scala | 2 +- tests/pos/SI-7060.scala | 2 +- tests/pos/depfuntype.scala | 2 +- tests/pos/i1570.decompiled | 4 +- tests/pos/i1570.scala | 4 +- tests/pos/i1891.scala | 2 +- tests/pos/i1990.scala | 2 +- tests/pos/i1990a.scala | 2 +- tests/pos/i2056.scala | 2 +- tests/pos/i2980.scala | 2 +- tests/pos/i3050.scala | 12 +- tests/pos/i3082.scala | 2 +- tests/pos/i3129.scala | 4 +- tests/pos/i3130a.scala | 2 +- tests/pos/i3130b.scala | 2 +- tests/pos/i3130c.scala | 2 +- tests/pos/i3130d.scala | 2 +- tests/pos/i3488.scala | 2 +- tests/pos/i3608.scala | 2 +- tests/pos/i3633.scala | 2 +- tests/pos/i3636.scala | 4 +- tests/pos/i3873.scala | 2 +- tests/pos/i3898/quoted_1.scala | 2 +- tests/pos/i3898b/quoted_1.scala | 2 +- tests/pos/i3898c/quoted_1.scala | 2 +- tests/pos/i3912-1/i3912_1.scala | 2 +- tests/pos/i3912-2/i3912_1.scala | 2 +- tests/pos/i3912-3/i3912_1.scala | 2 +- tests/pos/i4023/Macro_1.scala | 2 +- tests/pos/i4023b/Macro_1.scala | 2 +- tests/pos/i4023c/Macro_1.scala | 2 +- tests/pos/i4322.scala | 6 +- tests/pos/i4493-c.scala | 2 +- tests/pos/i4514.scala | 2 +- tests/pos/i4586.scala | 2 +- tests/pos/i4590.scala | 4 +- tests/pos/i4773.scala | 4 +- tests/pos/i4846.scala | 2 +- tests/pos/inline-access-levels/A_1.scala | 2 +- tests/pos/inline-apply.scala | 2 +- tests/pos/inline-i2570.scala | 2 +- tests/pos/inline-named-typeargs.scala | 2 +- tests/pos/inline-t2425.scala | 2 +- tests/pos/inlineAccesses.scala | 4 +- tests/pos/inliner2.scala | 2 +- tests/pos/macro-with-array/Macro_1.scala | 46 +++---- tests/pos/macro-with-type/Macro_1.scala | 2 +- tests/pos/pos_valueclasses/t5853.scala | 4 +- tests/pos/power-macro/Macro_1.scala | 2 +- tests/pos/quote-lift-inline-params-b.scala | 2 +- .../quote-lift-inline-params/Macro_1.scala | 2 +- tests/pos/quote-nested-object/Macro_1.scala | 4 +- tests/pos/quote-non-static-macro.scala | 8 +- tests/pos/rbtree.scala | 4 +- tests/pos/reference/inlines.scala | 2 +- tests/pos/sealed-final.scala | 2 +- tests/pos/simpleInline.decompiled | 2 +- tests/pos/simpleInline.scala | 2 +- tests/pos/t6157.scala | 2 +- tests/pos/t6562.scala | 4 +- tests/pos/transparent-nested.scala | 10 +- tests/pos/transparent-overload.scala | 4 +- tests/pos/typelevel-vector1.scala | 4 +- tests/run-with-compiler/i3876-d.scala | 2 +- .../quote-impure-by-name/quoted_1.scala | 2 +- .../quote-inline-function/quoted_1.scala | 4 +- .../quoted_1.scala | 2 +- tests/run/Tuple.scala | 26 ++-- tests/run/TupleAbstract.scala | 56 ++++---- tests/run/TupleImpl.scala | 125 ------------------ tests/run/dead-code-elimination.scala | 2 +- tests/run/generic-tuples.scala | 2 +- tests/run/genericValueClass.scala | 4 +- tests/run/i1569.scala | 2 +- tests/run/i1990b.scala | 2 +- tests/run/i2360.scala | 2 +- tests/run/i2895a.scala | 2 +- tests/run/i4431/quoted_1.scala | 2 +- tests/run/i4455/Macro_1.scala | 4 +- tests/run/i4492/quoted_1.scala | 2 +- tests/run/i4496b.scala | 6 +- tests/run/i4735/App_2.scala | 2 +- tests/run/i4735/Macro_1.scala | 2 +- tests/run/i4754.scala | 2 +- tests/run/i4803/App_2.scala | 2 +- tests/run/i4803/Macro_1.scala | 2 +- tests/run/i4803b/App_2.scala | 2 +- tests/run/i4803c/App_2.scala | 4 +- tests/run/i4803d/App_2.scala | 4 +- tests/run/i4803e/App_2.scala | 2 +- tests/run/i4803e/Macro_1.scala | 2 +- tests/run/i4803f/App_2.scala | 2 +- tests/run/i4803f/Macro_1.scala | 2 +- tests/run/implicitMatch.scala | 4 +- tests/run/lst/Lst.scala | 18 +-- tests/run/quote-and-splice/Macros_1.scala | 12 +- tests/run/quote-force/quoted_1.scala | 2 +- .../quote-indexed-map-by-name/quoted_1.scala | 2 +- tests/run/quote-sep-comp-2/Test_2.scala | 2 +- tests/run/quote-sep-comp/Macro_1.scala | 2 +- tests/run/quote-simple-macro/quoted_1.scala | 2 +- .../run/quote-unrolled-foreach/quoted_1.scala | 2 +- tests/run/reduce-projections.scala | 2 +- tests/run/tasty-custom-show/quoted_1.scala | 2 +- tests/run/tasty-definitions-1/quoted_1.scala | 2 +- tests/run/tasty-eval/quoted_1.scala | 4 +- tests/run/tasty-extractors-1/quoted_1.scala | 2 +- tests/run/tasty-extractors-2/quoted_1.scala | 2 +- tests/run/tasty-extractors-3/quoted_1.scala | 2 +- .../quoted_1.scala | 2 +- .../tasty-extractors-owners/quoted_1.scala | 2 +- .../run/tasty-extractors-types/quoted_1.scala | 2 +- tests/run/tasty-getfile/Macro_1.scala | 2 +- tests/run/tasty-indexed-map/quoted_1.scala | 2 +- tests/run/tasty-linenumber-2/quoted_1.scala | 2 +- tests/run/tasty-linenumber/quoted_1.scala | 2 +- tests/run/tasty-location/quoted_1.scala | 2 +- tests/run/tasty-macro-assert/quoted_1.scala | 2 +- tests/run/tasty-positioned/quoted_1.scala | 2 +- tests/run/tasty-subtyping/quoted_1.scala | 4 +- tests/run/transparent-foreach.scala | 10 +- tests/run/transparent-implicits.scala | 2 +- tests/run/transparent-object.scala | 2 +- tests/run/transparent/inlines_1.scala | 14 +- tests/run/transparentAccess/C_1.scala | 2 +- tests/run/transparentArrowAssoc.scala | 2 +- tests/run/transparentAssign.scala | 4 +- tests/run/transparentByName.scala | 6 +- tests/run/transparentForeach.scala | 2 +- tests/run/transparentPower/power_1.scala | 2 +- tests/run/transparentPrivates.scala | 14 +- tests/run/transparentProtected.scala | 2 +- tests/run/typelevel-defaultValue.scala | 2 +- tests/run/typelevel-numeric.scala | 2 +- tests/run/typelevel-overrides.scala | 4 +- tests/run/typelevel-patmat.scala | 12 +- tests/run/typelevel.scala | 36 ++--- tests/run/typelevel1.scala | 18 +-- tests/run/typelevel3.scala | 12 +- 253 files changed, 787 insertions(+), 850 deletions(-) rename compiler/src/dotty/tools/dotc/{rewrite => rewrites}/Rewrites.scala (94%) rename compiler/src/dotty/tools/dotc/typer/{PrepareTransparent.scala => PrepareInlineable.scala} (94%) delete mode 100644 tests/run/TupleImpl.scala diff --git a/bench/tests/power-macro/PowerMacro.scala b/bench/tests/power-macro/PowerMacro.scala index 3a18f97e980e..a228467e4885 100644 --- a/bench/tests/power-macro/PowerMacro.scala +++ b/bench/tests/power-macro/PowerMacro.scala @@ -2,7 +2,7 @@ import scala.quoted.Expr object PowerMacro { - transparent def power(transparent n: Long, x: Double) = ~powerCode(n, '(x)) + rewrite def power(transparent n: Long, x: Double) = ~powerCode(n, '(x)) def powerCode(n: Long, x: Expr[Double]): Expr[Double] = if (n == 0) '(1.0) diff --git a/compiler/src/dotty/tools/dotc/CompilationUnit.scala b/compiler/src/dotty/tools/dotc/CompilationUnit.scala index 59c8f47eaae8..210894277f92 100644 --- a/compiler/src/dotty/tools/dotc/CompilationUnit.scala +++ b/compiler/src/dotty/tools/dotc/CompilationUnit.scala @@ -4,7 +4,7 @@ package dotc import util.SourceFile import ast.{tpd, untpd} import tpd.{ Tree, TreeTraverser } -import typer.PrepareTransparent.InlineAccessors +import typer.PrepareInlineable.InlineAccessors import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.SymDenotations.ClassDenotation import dotty.tools.dotc.core.Symbols._ diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala index 6316ad9399ac..d30b2808fcde 100644 --- a/compiler/src/dotty/tools/dotc/Run.scala +++ b/compiler/src/dotty/tools/dotc/Run.scala @@ -16,7 +16,7 @@ import scala.io.Codec import util.{Set => _, _} import reporting.Reporter import transform.TreeChecker -import rewrite.Rewrites +import rewrites.Rewrites import java.io.{BufferedWriter, OutputStreamWriter} import profile.Profiler diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 2e1b674b895e..91d1db303082 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -437,7 +437,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => def refPurity(tree: Tree)(implicit ctx: Context): PurityLevel = { val sym = tree.symbol if (!tree.hasType) Impure - else if (!tree.tpe.widen.isParameterless || sym.is(Erased)) SimplyPure + else if (!tree.tpe.widen.isParameterless || sym.isEffectivelyErased) SimplyPure else if (!sym.isStable) Impure else if (sym.is(Module)) if (sym.moduleClass.isNoInitsClass) Pure else Idempotent diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index cf3b1359cfe6..0e56af56f3b9 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -497,6 +497,10 @@ object Trees { extends TermTree[T] { type ThisTree[-T >: Untyped] = If[T] } + class RewriteIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T]) + extends If(cond, thenp, elsep) { + override def toString = s"RewriteIf($cond, $thenp, $elsep)" + } /** A closure with an environment and a reference to a method. * @param env The captured parameters of the closure @@ -517,6 +521,10 @@ object Trees { extends TermTree[T] { type ThisTree[-T >: Untyped] = Match[T] } + class RewriteMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]]) + extends Match(selector, cases) { + override def toString = s"RewriteMatch($selector, $cases)" + } /** case pat if guard => body; only appears as child of a Match */ case class CaseDef[-T >: Untyped] private[ast] (pat: Tree[T], guard: Tree[T], body: Tree[T]) @@ -883,8 +891,10 @@ object Trees { type Assign = Trees.Assign[T] type Block = Trees.Block[T] type If = Trees.If[T] + type RewriteIf = Trees.RewriteIf[T] type Closure = Trees.Closure[T] type Match = Trees.Match[T] + type RewriteMatch = Trees.RewriteMatch[T] type CaseDef = Trees.CaseDef[T] type Return = Trees.Return[T] type Try = Trees.Try[T] @@ -1013,6 +1023,9 @@ object Trees { case _ => finalize(tree, untpd.Block(stats, expr)) } def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = tree match { + case tree: RewriteIf => + if ((cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep)) tree + else finalize(tree, untpd.RewriteIf(cond, thenp, elsep)) case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree case _ => finalize(tree, untpd.If(cond, thenp, elsep)) } @@ -1021,6 +1034,9 @@ object Trees { case _ => finalize(tree, untpd.Closure(env, meth, tpt)) } def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = tree match { + case tree: RewriteMatch => + if ((selector eq tree.selector) && (cases eq tree.cases)) tree + else finalize(tree, untpd.RewriteMatch(selector, cases)) case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) => tree case _ => finalize(tree, untpd.Match(selector, cases)) } diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala index 878d307dcd66..7325f5f99936 100644 --- a/compiler/src/dotty/tools/dotc/ast/untpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala @@ -132,6 +132,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { case class Lazy() extends Mod(Flags.Lazy) + case class Rewrite() extends Mod(Flags.Rewrite) + case class Transparent() extends Mod(Flags.Transparent) case class Enum() extends Mod(Flags.Enum) @@ -273,8 +275,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def Assign(lhs: Tree, rhs: Tree): Assign = new Assign(lhs, rhs) def Block(stats: List[Tree], expr: Tree): Block = new Block(stats, expr) def If(cond: Tree, thenp: Tree, elsep: Tree): If = new If(cond, thenp, elsep) + def RewriteIf(cond: Tree, thenp: Tree, elsep: Tree): If = new RewriteIf(cond, thenp, elsep) def Closure(env: List[Tree], meth: Tree, tpt: Tree): Closure = new Closure(env, meth, tpt) def Match(selector: Tree, cases: List[CaseDef]): Match = new Match(selector, cases) + def RewriteMatch(selector: Tree, cases: List[CaseDef]): Match = new RewriteMatch(selector, cases) def CaseDef(pat: Tree, guard: Tree, body: Tree): CaseDef = new CaseDef(pat, guard, body) def Return(expr: Tree, from: Tree): Return = new Return(expr, from) def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree): Try = new Try(expr, cases, finalizer) @@ -310,7 +314,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { * where `Ts` are the class type arguments of `T` or its class type alias. * Note: we also keep any type arguments as parts of `T`. This is necessary to allow * navigation into these arguments from the IDE, and to do the right thing in - * PrepareTransparent. + * PrepareInlineable. */ def New(tpt: Tree, argss: List[List[Tree]])(implicit ctx: Context): Tree = { val (tycon, targs) = tpt match { diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 3261979a9c0c..ed113a73cb23 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -5,7 +5,7 @@ import java.io.File import dotty.tools.io.{ Directory, PlainDirectory } import PathResolver.Defaults -import rewrite.Rewrites +import rewrites.Rewrites class ScalaSettings extends Settings.SettingGroup { @@ -43,7 +43,7 @@ class ScalaSettings extends Settings.SettingGroup { val pageWidth = IntSetting("-pagewidth", "Set page width", 80) val strict = BooleanSetting("-strict", "Use strict type rules, which means some formerly legal code does not typecheck anymore.") val language = MultiStringSetting("-language", "feature", "Enable one or more language features.") - val rewrite = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with -language:Scala2 rewrites sources to migrate to new syntax") + val `rewrite` = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with -language:Scala2 rewrites sources to migrate to new syntax") val silentWarnings = BooleanSetting("-nowarn", "Silence all warnings.") val fromTasty = BooleanSetting("-from-tasty", "Compile classes from tasty in classpath. The arguments are used as class names.") diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala index 48c18455e512..6138b63ea8ac 100644 --- a/compiler/src/dotty/tools/dotc/core/Annotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala @@ -57,7 +57,7 @@ object Annotations { } /** An annotation indicating the body of a right-hand side, - * typically of a transparent method. Treated specially in + * typically of a rewrite or transparent method. Treated specially in * pickling/unpickling and TypeTreeMaps */ abstract class BodyAnnotation extends Annotation { diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala index d165e521dc17..a80d25e16b04 100644 --- a/compiler/src/dotty/tools/dotc/core/Contexts.scala +++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala @@ -307,6 +307,10 @@ object Contexts { def isNonEmptyScopeContext: Boolean = (this.scope ne outer.scope) && !this.scope.isEmpty + /** Is this a context for typechecking an inlined body? */ + def isInlineContext: Boolean = + typer.isInstanceOf[Inliner#InlineTyper] + /** The next outer context whose tree is a template or package definition * Note: Currently unused def enclTemplate: Context = { diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 8d894bdfa034..41ab40f36acc 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -283,6 +283,9 @@ object Flags { */ final val Synthetic = commonFlag(18, "") + /** Labelled with `rewrite` modifier */ + final val Rewrite = commonFlag(19, "rewrite") + /** A covariant type variable / an outer accessor */ final val CovariantOrOuter = commonFlag(20, "") final val Covariant = typeFlag(20, "") @@ -433,7 +436,7 @@ object Flags { /** Flags representing source modifiers */ final val SourceModifierFlags = - commonFlags(Private, Protected, Abstract, Final, Transparent, + commonFlags(Private, Protected, Abstract, Final, Rewrite | Transparent, Sealed, Case, Implicit, Override, AbsOverride, Lazy, JavaStatic, Erased) /** Flags representing modifiers that can appear in trees */ @@ -454,7 +457,7 @@ object Flags { Scala2ExistentialCommon | Mutable.toCommonFlags | Touched | JavaStatic | CovariantOrOuter | ContravariantOrLabel | CaseAccessor.toCommonFlags | NonMember | ImplicitCommon | Permanent | Synthetic | - SuperAccessorOrScala2x | Transparent + SuperAccessorOrScala2x | Rewrite | Transparent /** Flags that are not (re)set when completing the denotation, or, if symbol is * a top-level class or object, when completing the denotation once the class @@ -548,8 +551,8 @@ object Flags { /** Assumed to be pure */ final val StableOrErased = Stable | Erased - /** Labeled `private`, `final`, or `transparent` */ - final val EffectivelyFinal = Private | Final | Transparent + /** Labeled `private`, `final`, `rewrite` or `transparent` */ + final val EffectivelyFinal = Private | Final | Rewrite | Transparent /** A private method */ final val PrivateMethod = allOf(Private, Method) @@ -560,8 +563,11 @@ object Flags { /** A transparent method */ final val TransparentMethod = allOf(Transparent, Method) - /** A transparent implicit method */ - final val TransparentImplicitMethod = allOf(Transparent, Implicit, Method) + /** A rewrite method */ + final val RewriteMethod = allOf(Rewrite, Method) + + /** An implicit rewrite method */ + final val ImplicitRewriteMethod = allOf(Rewrite, Implicit, Method) /** A transparent parameter */ final val TransparentParam = allOf(Transparent, Param) diff --git a/compiler/src/dotty/tools/dotc/core/Mode.scala b/compiler/src/dotty/tools/dotc/core/Mode.scala index d05191dc024b..9dc4e92df3f7 100644 --- a/compiler/src/dotty/tools/dotc/core/Mode.scala +++ b/compiler/src/dotty/tools/dotc/core/Mode.scala @@ -95,8 +95,8 @@ object Mode { /** We are in the IDE */ val Interactive = newMode(20, "Interactive") - /** We are typing the body of a transparent method */ - val TransparentBody = newMode(21, "TransparentBody") + /** We are typing the body of a transparent or rewrite method */ + val InlineableBody = newMode(21, "InlineableBody") /** Read comments from definitions when unpickling from TASTY */ val ReadComments = newMode(22, "ReadComments") diff --git a/compiler/src/dotty/tools/dotc/core/NameKinds.scala b/compiler/src/dotty/tools/dotc/core/NameKinds.scala index 2c69f6339f1c..8e7e7db98047 100644 --- a/compiler/src/dotty/tools/dotc/core/NameKinds.scala +++ b/compiler/src/dotty/tools/dotc/core/NameKinds.scala @@ -45,7 +45,7 @@ object NameKinds { } /** Does this kind define logically a new name (respectively qualified name)? - * Tested by the `rewrite` and `collect` combinators of class `Name`. + * Tested by the `replace` and `collect` combinators of class `Name`. */ def definesNewName = false def definesQualifiedName = false @@ -135,7 +135,7 @@ object NameKinds { * Needed because the suffix of an expanded name may itself be expanded. * For example, look at javap of scala.App.initCode */ - def apply(qual: TermName, name: TermName): TermName = name rewrite { + def apply(qual: TermName, name: TermName): TermName = name replace { case name: SimpleName => apply(qual, name) case AnyQualifiedName(_, _) => apply(qual, name.toSimpleName) } @@ -294,8 +294,8 @@ object NameKinds { val SuperArgName = new UniqueNameKind("$superArg$") val DocArtifactName = new UniqueNameKind("$doc") val UniqueInlineName = new UniqueNameKind("$i") - val TransparentScrutineeName = new UniqueNameKind("$scrutinee") - val TransparentBinderName = new UniqueNameKind("$elem") + val RewriteScrutineeName = new UniqueNameKind("$scrutinee") + val RewriteBinderName = new UniqueNameKind("$elem") /** A kind of unique extension methods; Unlike other unique names, these can be * unmangled. diff --git a/compiler/src/dotty/tools/dotc/core/NameOps.scala b/compiler/src/dotty/tools/dotc/core/NameOps.scala index a3f021001158..3abd919f89d9 100644 --- a/compiler/src/dotty/tools/dotc/core/NameOps.scala +++ b/compiler/src/dotty/tools/dotc/core/NameOps.scala @@ -123,12 +123,12 @@ object NameOps { /** Revert the expanded name. */ def unexpandedName: N = likeSpacedN { - name.rewrite { case ExpandedName(_, unexp) => unexp } + name.replace { case ExpandedName(_, unexp) => unexp } } /** Remove the variance from the name. */ def invariantName: N = likeSpacedN { - name.rewrite { case VariantName(invariant, _) => invariant } + name.replace { case VariantName(invariant, _) => invariant } } def implClassName: N = likeSpacedN(name ++ tpnme.IMPL_CLASS_SUFFIX) @@ -254,11 +254,11 @@ object NameOps { } def unmangle(kind: NameKind): N = likeSpacedN { - name rewrite { + name replace { case unmangled: SimpleName => kind.unmangle(unmangled) case ExpandedName(prefix, last) => - kind.unmangle(last) rewrite { + kind.unmangle(last) replace { case kernel: SimpleName => ExpandedName(prefix, kernel) } diff --git a/compiler/src/dotty/tools/dotc/core/Names.scala b/compiler/src/dotty/tools/dotc/core/Names.scala index 3de657629fcb..e2e5a9e60ab4 100644 --- a/compiler/src/dotty/tools/dotc/core/Names.scala +++ b/compiler/src/dotty/tools/dotc/core/Names.scala @@ -83,7 +83,7 @@ object Names { * Stops at derived names whose kind has `definesNewName = true`. * If `f` does not apply to any part, return name unchanged. */ - def rewrite(f: PartialFunction[Name, Name]): ThisName + def replace(f: PartialFunction[Name, Name]): ThisName /** If partial function `f` is defined for some part of this name, apply it * in a Some, otherwise None. @@ -348,7 +348,7 @@ object Names { override def toSimpleName = this override final def mangle = encode - override def rewrite(f: PartialFunction[Name, Name]): ThisName = + override def replace(f: PartialFunction[Name, Name]): ThisName = if (f.isDefinedAt(this)) likeSpaced(f(this)) else this override def collect[T](f: PartialFunction[Name, T]): Option[T] = f.lift(this) override def mapLast(f: SimpleName => SimpleName) = f(this) @@ -447,7 +447,7 @@ object Names { override def mangled = toTermName.mangled.toTypeName override def mangledString = toTermName.mangledString - override def rewrite(f: PartialFunction[Name, Name]): ThisName = toTermName.rewrite(f).toTypeName + override def replace(f: PartialFunction[Name, Name]): ThisName = toTermName.replace(f).toTypeName override def collect[T](f: PartialFunction[Name, T]): Option[T] = toTermName.collect(f) override def mapLast(f: SimpleName => SimpleName) = toTermName.mapLast(f).toTypeName override def mapParts(f: SimpleName => SimpleName) = toTermName.mapParts(f).toTypeName @@ -480,11 +480,11 @@ object Names { override def toSimpleName = termName(toString) override final def mangle = encode.toSimpleName - override def rewrite(f: PartialFunction[Name, Name]): ThisName = + override def replace(f: PartialFunction[Name, Name]): ThisName = if (f.isDefinedAt(this)) likeSpaced(f(this)) else info match { case qual: QualifiedInfo => this - case _ => underlying.rewrite(f).derived(info) + case _ => underlying.replace(f).derived(info) } override def collect[T](f: PartialFunction[Name, T]): Option[T] = diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 4b5da2c09284..8dad726672af 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -409,7 +409,7 @@ object SymDenotations { prefix = prefix.exclude(ModuleClassName) def qualify(n: SimpleName) = kind(prefix.toTermName, if (filler.isEmpty) n else termName(filler + n)) - val fn = name rewrite { + val fn = name replace { case name: SimpleName => qualify(name) case name @ AnyQualifiedName(_, _) => qualify(name.mangled.toSimpleName) } @@ -781,11 +781,24 @@ object SymDenotations { def isTransparentMethod(implicit ctx: Context): Boolean = is(TransparentMethod, butNot = AccessorOrSynthetic) - /** A transparent method that is not nested inside another transparent method. - * Nested transparents are not inlineable yet, only their inlined copies are. + def isRewriteMethod(implicit ctx: Context): Boolean = + is(RewriteMethod, butNot = AccessorOrSynthetic) + + /** A transparent or rewrite method */ + def isInlineable(implicit ctx: Context): Boolean = + is(TransparentMethod) || is(RewriteMethod) + + /** An erased value or a rewrite method, excluding @forceInline annotated methods. + * The latter have to be kept around to get to parity with Scala. + * This is necessary at least until we have full bootstrap. Right now + * dotty-bootstrapped involves running the Dotty compiler compiled with Scala 2 with + * a Dotty runtime library compiled with Dotty. If we erase @forceInline annotated + * methods, this means that the support methods in dotty.runtime.LazyVals vanish. + * But they are needed for running the lazy val implementations in the Scala-2 compiled compiler. */ - def isTransparentInlineable(implicit ctx: Context): Boolean = - isTransparentMethod && !owner.ownersIterator.exists(_.is(TransparentMethod)) + def isEffectivelyErased(implicit ctx: Context): Boolean = + is(Erased) || + isRewriteMethod && unforcedAnnotation(defn.ForceInlineAnnot).isEmpty /** ()T and => T types should be treated as equivalent for this symbol. * Note: For the moment, we treat Scala-2 compiled symbols as loose matching, diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index af13b3f22ed5..91703bb22dbf 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -273,8 +273,8 @@ trait TypeOps { this: Context => // TODO: Make standalone object. violations.toList } - /** Are we in a transparent method body? */ - def inTransparentMethod = owner.ownersIterator.exists(_.isTransparentMethod) + /** Are we in a rewrite method body? */ + def inRewriteMethod = owner.ownersIterator.exists(_.isRewriteMethod) /** Is `feature` enabled in class `owner`? * This is the case if one of the following two alternatives holds: @@ -320,10 +320,10 @@ trait TypeOps { this: Context => // TODO: Make standalone object. def dynamicsEnabled = featureEnabled(defn.LanguageModuleClass, nme.dynamics) - def testScala2Mode(msg: => Message, pos: Position, rewrite: => Unit = ()) = { + def testScala2Mode(msg: => Message, pos: Position, replace: => Unit = ()) = { if (scala2Mode) { migrationWarning(msg, pos) - rewrite + replace } scala2Mode } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index b9b9d2821b71..724f32463069 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -182,8 +182,8 @@ Standard-Section: "ASTs" TopLevelStat* LAZY OVERRIDE TRANSPARENT - TYPELEVEL // transparent method containing toplevel matches (TODO: merge with MACRO) - MACRO // transparent method containing toplevel splices + REWRITE + MACRO // rewrite method containing toplevel splices STATIC // mapped to static Java member OBJECT // an object or its class TRAIT // a trait @@ -298,7 +298,7 @@ object TastyFormat { final val LAZY = 14 final val OVERRIDE = 15 final val TRANSPARENT = 16 - + final val REWRITE = 17 final val STATIC = 18 final val OBJECT = 19 final val TRAIT = 20 @@ -476,6 +476,7 @@ object TastyFormat { | LAZY | OVERRIDE | TRANSPARENT + | REWRITE | MACRO | STATIC | OBJECT @@ -532,6 +533,7 @@ object TastyFormat { case LAZY => "LAZY" case OVERRIDE => "OVERRIDE" case TRANSPARENT => "TRANSPARENT" + case REWRITE => "REWRITE" case MACRO => "MACRO" case STATIC => "STATIC" case OBJECT => "OBJECT" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index f4f202650877..51b410020217 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -603,6 +603,7 @@ class TreePickler(pickler: TastyPickler) { if (flags is Case) writeByte(CASE) if (flags is Override) writeByte(OVERRIDE) if (flags is Transparent) writeByte(TRANSPARENT) + if (flags is Rewrite) writeByte(REWRITE) if (flags is Macro) writeByte(MACRO) if (flags is JavaStatic) writeByte(STATIC) if (flags is Module) writeByte(OBJECT) @@ -766,10 +767,16 @@ class TreePickler(pickler: TastyPickler) { withLength { pickleUntyped(expr); stats.foreach(pickleUntyped) } case If(cond, thenp, elsep) => writeByte(IF) - withLength { pickleUntyped(cond); pickleUntyped(thenp); pickleUntyped(elsep) } + withLength { + if (tree.isInstanceOf[untpd.RewriteIf]) writeByte(REWRITE) + pickleUntyped(cond); pickleUntyped(thenp); pickleUntyped(elsep) + } case Match(selector, cases) => writeByte(MATCH) - withLength { pickleUntyped(selector); cases.foreach(pickleUntyped) } + withLength { + if (tree.isInstanceOf[untpd.RewriteMatch]) writeByte(REWRITE) + pickleUntyped(selector); cases.foreach(pickleUntyped) + } case CaseDef(pat, guard, rhs) => writeByte(CASEDEF) withLength { pickleUntyped(pat); pickleUntyped(rhs); pickleUnlessEmpty(guard) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 31eccffe7348..40cfba553bcd 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -587,6 +587,7 @@ class TreeUnpickler(reader: TastyReader, case LAZY => addFlag(Lazy) case OVERRIDE => addFlag(Override) case TRANSPARENT => addFlag(Transparent) + case REWRITE => addFlag(Rewrite) case MACRO => addFlag(Macro) case STATIC => addFlag(JavaStatic) case OBJECT => addFlag(Module) @@ -1304,9 +1305,14 @@ class TreeUnpickler(reader: TastyReader, val stats = until(end)(readUntyped()) untpd.Block(stats, expr) case IF => - untpd.If(readUntyped(), readUntyped(), readUntyped()) + val mkIf = if (nextByte == REWRITE) { readByte(); untpd.RewriteIf(_, _, _) } + else untpd.If(_, _, _) + mkIf(readUntyped(), readUntyped(), readUntyped()) case MATCH => - untpd.Match(readUntyped(), readCases(end)) + val mkMatch = + if (nextByte == REWRITE) { readByte(); untpd.RewriteMatch(_, _) } + else untpd.Match(_, _) + mkMatch(readUntyped(), readCases(end)) case CASEDEF => val pat = readUntyped() val rhs = readUntyped() diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index fc443e3c5367..596dce4fca49 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -24,7 +24,7 @@ import ScriptParsers._ import Comments._ import scala.annotation.{tailrec, switch} import util.DotClass -import rewrite.Rewrites.patch +import rewrites.Rewrites.patch object Parsers { @@ -170,18 +170,21 @@ object Parsers { def isLiteral = literalTokens contains in.token def isNumericLit = numericLitTokens contains in.token def isModifier = modifierTokens contains in.token - def isExprIntro = canStartExpressionTokens contains in.token def isBindingIntro = canStartBindingTokens contains in.token def isTemplateIntro = templateIntroTokens contains in.token def isDclIntro = dclIntroTokens contains in.token def isStatSeqEnd = in.token == RBRACE || in.token == EOF def mustStartStat = mustStartStatTokens contains in.token - def isDefIntro(allowedMods: BitSet) = - in.token == AT || (allowedMods contains in.token) || (defIntroTokens contains in.token) + def isExprIntro = + (canStartExpressionTokens `contains` in.token) && + (in.token != REWRITE || lookaheadIn(canStartExpressionTokens)) - def isCaseIntro = - in.token == AT || (modifierTokensOrCase contains in.token) + def isDefIntro(allowedMods: BitSet) = + in.token == AT || + (defIntroTokens `contains` in.token) || + (allowedMods `contains` in.token) && + (in.token != REWRITE || lookaheadIn(BitSet(AT) | defIntroTokens | allowedMods)) def isStatSep: Boolean = in.token == NEWLINE || in.token == NEWLINES || in.token == SEMI @@ -456,7 +459,7 @@ object Parsers { def commaSeparated[T](part: () => T): List[T] = tokenSeparated(COMMA, part) /** Is the token following the current one in `tokens`? */ - def lookaheadIn(tokens: Token*): Boolean = { + def lookaheadIn(tokens: BitSet): Boolean = { val lookahead = in.lookaheadScanner lookahead.nextToken() tokens.contains(lookahead.token) @@ -839,7 +842,7 @@ object Parsers { /** Is current ident a `*`, and is it followed by a `)` or `,`? */ def isPostfixStar: Boolean = - in.name == nme.raw.STAR && lookaheadIn(RPAREN, COMMA) + in.name == nme.raw.STAR && lookaheadIn(BitSet(RPAREN, COMMA)) def infixTypeRest(t: Tree): Tree = infixOps(t, canStartTypeTokens, refinedType, isType = true, isOperator = !isPostfixStar) @@ -897,7 +900,7 @@ object Parsers { val start = in.skipToken() typeBounds().withPos(Position(start, in.lastOffset, start)) } - else if (isIdent(nme.raw.TILDE) && lookaheadIn(IDENTIFIER, BACKQUOTED_IDENT)) + else if (isIdent(nme.raw.TILDE) && lookaheadIn(BitSet(IDENTIFIER, BACKQUOTED_IDENT))) atPos(in.offset) { PrefixOp(typeIdent(), path(thisOK = true)) } else path(thisOK = false, handleSingletonType) match { case r @ SingletonTypeTree(_) => r @@ -1099,8 +1102,8 @@ object Parsers { * | Expr * BlockResult ::= [FunArgMods] FunParams =>' Block * | Expr1 - * Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] else Expr] - * | `if' Expr `then' Expr [[semi] else Expr] + * Expr1 ::= [‘rewrite’] `if' `(' Expr `)' {nl} Expr [[semi] else Expr] + * | [‘rewrite’] `if' Expr `then' Expr [[semi] else Expr] * | `while' `(' Expr `)' {nl} Expr * | `while' Expr `do' Expr * | `do' Expr [semi] `while' Expr @@ -1112,7 +1115,7 @@ object Parsers { * | [SimpleExpr `.'] id `=' Expr * | SimpleExpr1 ArgumentExprs `=' Expr * | PostfixExpr [Ascription] - * | PostfixExpr `match' `{' CaseClauses `}' + * | [‘rewrite’] PostfixExpr `match' `{' CaseClauses `}' * | `implicit' `match' `{' ImplicitCaseClauses `}' * Bindings ::= `(' [Binding {`,' Binding}] `)' * Binding ::= (id | `_') [`:' Type] @@ -1154,14 +1157,7 @@ object Parsers { def expr1(location: Location.Value = Location.ElseWhere): Tree = in.token match { case IF => - atPos(in.skipToken()) { - val cond = condExpr(THEN) - newLinesOpt() - val thenp = expr() - val elsep = if (in.token == ELSE) { in.nextToken(); expr() } - else EmptyTree - If(cond, thenp, elsep) - } + ifExpr(in.offset, If) case WHILE => atPos(in.skipToken()) { val cond = condExpr(DO) @@ -1215,6 +1211,19 @@ object Parsers { atPos(in.skipToken()) { Return(if (isExprIntro) expr() else EmptyTree, EmptyTree) } case FOR => forExpr() + case REWRITE => + val start = in.skipToken() + in.token match { + case IF => + ifExpr(start, RewriteIf) + case _ => + val t = postfixExpr() + if (in.token == MATCH) matchExpr(t, start, RewriteMatch) + else { + syntaxErrorOrIncomplete("`match` or `if` expected but ${in.token} found") + t + } + } case _ => expr1Rest(postfixExpr(), location) } @@ -1230,7 +1239,7 @@ object Parsers { case COLON => ascription(t, location) case MATCH => - matchExpr(t) + matchExpr(t, startOffset(t), Match) case _ => t } @@ -1261,12 +1270,25 @@ object Parsers { } } + /** `if' `(' Expr `)' {nl} Expr [[semi] else Expr] + * `if' Expr `then' Expr [[semi] else Expr] + */ + def ifExpr(start: Offset, mkIf: (Tree, Tree, Tree) => If): If = + atPos(start, in.skipToken()) { + val cond = condExpr(THEN) + newLinesOpt() + val thenp = expr() + val elsep = if (in.token == ELSE) { in.nextToken(); expr() } + else EmptyTree + mkIf(cond, thenp, elsep) + } + /** `match' { CaseClauses } * `match' { ImplicitCaseClauses } */ - def matchExpr(t: Tree) = - atPos(startOffset(t), in.skipToken()) { - inBraces(Match(t, caseClauses())) + def matchExpr(t: Tree, start: Offset, mkMatch: (Tree, List[CaseDef]) => Match) = + atPos(start, in.skipToken()) { + inBraces(mkMatch(t, caseClauses())) } /** `match' { ImplicitCaseClauses } @@ -1280,7 +1302,8 @@ object Parsers { case Mod.Implicit() :: mods => markFirstIllegal(mods) case mods => markFirstIllegal(mods) } - val result @ Match(t, cases) = matchExpr(ImplicitScrutinee().withPos(implicitKwPos(start))) + val result @ Match(t, cases) = + matchExpr(ImplicitScrutinee().withPos(implicitKwPos(start)), start, RewriteMatch) for (CaseDef(pat, _, _) <- cases) { def isImplicitPattern(pat: Tree) = pat match { case Typed(pat1, _) => isVarPattern(pat1) @@ -1733,6 +1756,7 @@ object Parsers { case FINAL => Mod.Final() case IMPLICIT => Mod.Implicit() case ERASED => Mod.Erased() + case REWRITE => Mod.Rewrite() case TRANSPARENT => Mod.Transparent() case LAZY => Mod.Lazy() case OVERRIDE => Mod.Override() @@ -2519,6 +2543,8 @@ object Parsers { stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens)) else if (!isStatSep) { exitOnError = mustStartStat + println(in.token) + println(in.next.token) syntaxErrorOrIncomplete("illegal start of definition") } acceptStatSepUnlessAtEnd() diff --git a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala index 694386cef3b3..b33f0627be7f 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Scanners.scala @@ -13,7 +13,7 @@ import scala.annotation.{ switch, tailrec } import scala.collection.mutable import scala.collection.immutable.SortedMap import mutable.ListBuffer -import rewrite.Rewrites.patch +import rewrites.Rewrites.patch object Scanners { diff --git a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala index 2c2ff229544e..1482e8a7cdd0 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Tokens.scala @@ -91,9 +91,10 @@ abstract class TokensCommon { //final val LAZY = 59; enter(LAZY, "lazy") //final val THEN = 60; enter(THEN, "then") //final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate - //final val TRANSPARENT = 62; enter(TRANSPARENT, "transparent") - //final val ENUM = 63; enter(ENUM, "enum") - //final val ERASED = 64; enter(ERASED, "erased") + //final val REWRITE = 62; enter(REWRITE, "rewrite") + //final val TRANSPARENT = 63; enter(TRANSPARENT, "transparent") + //final val ENUM = 64; enter(ENUM, "enum") + //final val ERASED = 65; enter(ERASED, "erased") /** special symbols */ final val COMMA = 70; enter(COMMA, "','") @@ -176,9 +177,10 @@ object Tokens extends TokensCommon { final val LAZY = 59; enter(LAZY, "lazy") final val THEN = 60; enter(THEN, "then") final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate - final val TRANSPARENT = 62; enter(TRANSPARENT, "transparent") - final val ENUM = 63; enter(ENUM, "enum") - final val ERASED = 64; enter(ERASED, "erased") + final val REWRITE = 62; enter(REWRITE, "rewrite") + final val TRANSPARENT = 63; enter(TRANSPARENT, "transparent") + final val ENUM = 64; enter(ENUM, "enum") + final val ERASED = 65; enter(ERASED, "erased") /** special symbols */ final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line") @@ -213,7 +215,7 @@ object Tokens extends TokensCommon { USCORE, NULL, THIS, SUPER, TRUE, FALSE, RETURN, XMLSTART) final val canStartExpressionTokens = atomicExprTokens | BitSet( - LBRACE, LPAREN, QBRACE, QPAREN, IF, DO, WHILE, FOR, NEW, TRY, THROW) + LBRACE, LPAREN, QBRACE, QPAREN, IF, DO, WHILE, FOR, NEW, TRY, THROW, REWRITE) final val canStartTypeTokens = literalTokens | identifierTokens | BitSet( THIS, SUPER, USCORE, LPAREN, AT) @@ -227,7 +229,7 @@ object Tokens extends TokensCommon { final val defIntroTokens = templateIntroTokens | dclIntroTokens final val localModifierTokens = BitSet( - ABSTRACT, FINAL, SEALED, IMPLICIT, TRANSPARENT, LAZY, ERASED) + ABSTRACT, FINAL, SEALED, IMPLICIT, REWRITE, TRANSPARENT, LAZY, ERASED) final val accessModifierTokens = BitSet( PRIVATE, PROTECTED) @@ -238,7 +240,7 @@ object Tokens extends TokensCommon { final val modifierTokensOrCase = modifierTokens | BitSet(CASE) /** Is token only legal as start of statement (eof also included)? */ - final val mustStartStatTokens = defIntroTokens | modifierTokens | BitSet( + final val mustStartStatTokens = defIntroTokens | (modifierTokens - REWRITE) | BitSet( IMPORT, PACKAGE) final val canStartStatTokens = canStartExpressionTokens | mustStartStatTokens | BitSet( diff --git a/compiler/src/dotty/tools/dotc/quoted/ToolboxImpl.scala b/compiler/src/dotty/tools/dotc/quoted/ToolboxImpl.scala index 04d8c255f0e8..1067caf89a9a 100644 --- a/compiler/src/dotty/tools/dotc/quoted/ToolboxImpl.scala +++ b/compiler/src/dotty/tools/dotc/quoted/ToolboxImpl.scala @@ -17,7 +17,7 @@ object ToolboxImpl { case expr: LiftedExpr[T] => expr.value case expr: TastyTreeExpr[Tree] @unchecked => - throw new Exception("Cannot call `Expr.run` on an `Expr` that comes from a transparent macro argument.") + throw new Exception("Cannot call `Expr.run` on an `Expr` that comes from a macro argument.") case _ => synchronized(driver.run(expr, settings)) } diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index c7cacfed991d..66439ae19599 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -90,7 +90,7 @@ public enum ErrorMessageID { OnlyCaseClassOrCaseObjectAllowedID, ExpectedClassOrObjectDefID, AnonymousFunctionMissingParamTypeID, - SuperCallsNotAllowedTransparentID, + SuperCallsNotAllowedInlineableID, ModifiersNotAllowedID, WildcardOnTypeArgumentNotAllowedOnNewID, FunctionTypeNeedsNonEmptyParameterListID, @@ -98,7 +98,7 @@ public enum ErrorMessageID { DuplicatePrivateProtectedQualifierID, ExpectedStartOfTopLevelDefinitionID, MissingReturnTypeWithReturnStatementID, - NoReturnFromTransparentID, + NoReturnFromInlineableID, ReturnOutsideMethodDefinitionID, UncheckedTypePatternID, ExtendFinalClassID, diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 1c988606b9f9..faf4dbd7002d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -1696,10 +1696,10 @@ object messages { val explanation = "" } - case class SuperCallsNotAllowedTransparent(symbol: Symbol)(implicit ctx: Context) - extends Message(SuperCallsNotAllowedTransparentID) { + case class SuperCallsNotAllowedInlineable(symbol: Symbol)(implicit ctx: Context) + extends Message(SuperCallsNotAllowedInlineableID) { val kind = "Syntax" - val msg = s"super call not allowed in transparent $symbol" + val msg = s"super call not allowed in inlineable $symbol" val explanation = "Method inlining prohibits calling superclass methods, as it may lead to confusion about which super is being called." } @@ -1747,12 +1747,12 @@ object messages { hl"you have to provide either ${"class"}, ${"trait"}, ${"object"}, or ${"enum"} definitions after qualifiers" } - case class NoReturnFromTransparent(owner: Symbol)(implicit ctx: Context) - extends Message(NoReturnFromTransparentID) { + case class NoReturnFromInlineable(owner: Symbol)(implicit ctx: Context) + extends Message(NoReturnFromInlineableID) { val kind = "Syntax" - val msg = hl"no explicit ${"return"} allowed from transparent $owner" + val msg = hl"no explicit ${"return"} allowed from inlineable $owner" val explanation = - hl"""Methods marked with ${"transparent"} modifier may not use ${"return"} statements. + hl"""Methods marked with ${"rewrite"} or ${"transparent"} modifier may not use ${"return"} statements. |Instead, you should rely on the last expression's value being |returned from a method. |""" @@ -2061,7 +2061,7 @@ object messages { case class ParamsNoTransparent(owner: Symbol)(implicit ctx: Context) extends Message(ParamsNoTransparentID) { val kind = "Syntax" - val msg = hl"""${"transparent"} modifier cannot be used for a parameter of a non-transparent method""" + val msg = hl"""${"transparent"} modifier can only be used for parameters of rewrite methods""" val explanation = "" } diff --git a/compiler/src/dotty/tools/dotc/rewrite/Rewrites.scala b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala similarity index 94% rename from compiler/src/dotty/tools/dotc/rewrite/Rewrites.scala rename to compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala index 909a145d134d..755509a3c058 100644 --- a/compiler/src/dotty/tools/dotc/rewrite/Rewrites.scala +++ b/compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala @@ -1,5 +1,5 @@ package dotty.tools.dotc -package rewrite +package rewrites import util.{SourceFile, Positions} import Positions.Position @@ -63,7 +63,7 @@ object Rewrites { * given by `pos` in `source` by `replacement` */ def patch(source: SourceFile, pos: Position, replacement: String)(implicit ctx: Context): Unit = - for (rewrites <- ctx.settings.rewrite.value) + for (rewrites <- ctx.settings.`rewrite`.value) rewrites.patched .getOrElseUpdate(source, new Patches(source)) .addPatch(pos, replacement) @@ -75,7 +75,7 @@ object Rewrites { /** If -rewrite is set, apply all patches and overwrite patched source files. */ def writeBack()(implicit ctx: Context) = - for (rewrites <- ctx.settings.rewrite.value; source <- rewrites.patched.keys) { + for (rewrites <- ctx.settings.`rewrite`.value; source <- rewrites.patched.keys) { ctx.echo(s"[patched file ${source.file.path}]") rewrites.patched(source).writeBack() } diff --git a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala index 4418a5f4f518..ce3ce629a70a 100644 --- a/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala +++ b/compiler/src/dotty/tools/dotc/sbt/ExtractAPI.scala @@ -590,7 +590,7 @@ private class ExtractAPICollector(implicit val ctx: Context) extends ThunkHolder val annots = new mutable.ListBuffer[api.Annotation] if (Inliner.hasBodyToInline(s)) { - // FIXME: If the body of a transparent method changes, all the reverse + // FIXME: If the body of an inlineable method changes, all the reverse // dependencies of this method need to be recompiled. sbt has no way // of tracking method bodies, so as a hack we include the pretty-printed // typed tree of the method as part of the signature we send to sbt. diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/FlagSet.scala b/compiler/src/dotty/tools/dotc/tastyreflect/FlagSet.scala index 41a3b69f6ca2..629f8f24dd0d 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/FlagSet.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/FlagSet.scala @@ -15,6 +15,7 @@ class FlagSet(flags: Flags.FlagSet) extends scala.tasty.reflect.FlagSet { def isLazy: Boolean = flags.is(Lazy) def isOverride: Boolean = flags.is(Override) def isTransparent: Boolean = flags.is(Transparent) + def isRewrite: Boolean = flags.is(Rewrite) def isMacro: Boolean = flags.is(Macro) def isStatic: Boolean = flags.is(JavaStatic) def isObject: Boolean = flags.is(Module) @@ -46,6 +47,7 @@ class FlagSet(flags: Flags.FlagSet) extends scala.tasty.reflect.FlagSet { if (isLazy) flags += "lazy" if (isOverride) flags += "override" if (isTransparent) flags += "transparent" + if (isRewrite) flags += "rewrite" if (isMacro) flags += "macro" if (isStatic) flags += "javaStatic" if (isObject) flags += "object" diff --git a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala index bffd84779544..1e4bd8730559 100644 --- a/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala +++ b/compiler/src/dotty/tools/dotc/transform/AccessProxies.scala @@ -145,7 +145,7 @@ abstract class AccessProxies { def accessorIfNeeded(tree: Tree)(implicit ctx: Context): Tree = tree match { case tree: RefTree if needsAccessor(tree.symbol) => if (tree.symbol.isConstructor) { - ctx.error("Implementation restriction: cannot use private constructors in transparent methods", tree.pos) + ctx.error("Implementation restriction: cannot use private constructors in inlineable methods", tree.pos) tree // TODO: create a proper accessor for the private constructor } else useAccessor(tree) diff --git a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala index 888696846ae7..00e2473d8ae1 100644 --- a/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala +++ b/compiler/src/dotty/tools/dotc/transform/ArrayConstructors.scala @@ -35,22 +35,22 @@ class ArrayConstructors extends MiniPhase { override def phaseName: String = "arrayConstructors" override def transformApply(tree: tpd.Apply)(implicit ctx: Context): tpd.Tree = { - def rewrite(elemType: Type, dims: List[Tree]) = + def expand(elemType: Type, dims: List[Tree]) = tpd.newArray(elemType, tree.tpe, tree.pos, JavaSeqLiteral(dims, TypeTree(defn.IntClass.typeRef))) if (tree.fun.symbol eq defn.ArrayConstructor) { val TypeApply(tycon, targ :: Nil) = tree.fun - rewrite(targ.tpe, tree.args) + expand(targ.tpe, tree.args) } else if ((tree.fun.symbol.maybeOwner eq defn.ArrayModule) && (tree.fun.symbol.name eq nme.ofDim) && !tree.tpe.isInstanceOf[MethodicType]) { val Apply(Apply(TypeApply(_, List(tp)), _), _) = tree val cs = tp.tpe.widen.classSymbol tree.fun match { case Apply(TypeApply(t: Ident, targ), dims) if !TypeErasure.isGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) => - rewrite(targ.head.tpe, dims) + expand(targ.head.tpe, dims) case Apply(TypeApply(t: Select, targ), dims) if !TypeErasure.isGeneric(targ.head.tpe) && !ValueClasses.isDerivedValueClass(cs) => - Block(t.qualifier :: Nil, rewrite(targ.head.tpe, dims)) + Block(t.qualifier :: Nil, expand(targ.head.tpe, dims)) case _ => tree } diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index d9f316a366b8..69bded663ee5 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -319,7 +319,7 @@ object Erasure { import Boxing._ private def checkNotErased(tree: Tree)(implicit ctx: Context): tree.type = { - if (tree.symbol.is(Flags.Erased) && !ctx.mode.is(Mode.Type)) + if (tree.symbol.isEffectivelyErased && !ctx.mode.is(Mode.Type)) ctx.error(em"${tree.symbol} is declared as erased, but is in fact used", tree.pos) tree } @@ -554,17 +554,17 @@ object Erasure { } override def typedValDef(vdef: untpd.ValDef, sym: Symbol)(implicit ctx: Context): Tree = - if (sym.is(Flags.Erased)) erasedDef(sym) + if (sym.isEffectivelyErased) erasedDef(sym) else super.typedValDef(untpd.cpy.ValDef(vdef)( tpt = untpd.TypedSplice(TypeTree(sym.info).withPos(vdef.tpt.pos))), sym) /** Besides normal typing, this function also compacts anonymous functions - * with more than `MaxImplementedFunctionArity` parameters to ise a single + * with more than `MaxImplementedFunctionArity` parameters to use a single * parameter of type `[]Object`. */ override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context): Tree = - if (sym.is(Flags.Erased)) erasedDef(sym) + if (sym.isEffectivelyErased) erasedDef(sym) else { val restpe = if (sym.isConstructor) defn.UnitType diff --git a/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala b/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala index e9843c0a5f34..fa39295c1652 100644 --- a/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala +++ b/compiler/src/dotty/tools/dotc/transform/InterceptedMethods.scala @@ -41,9 +41,9 @@ class InterceptedMethods extends MiniPhase { case id: Ident => tpd.desugarIdentPrefix(id) case sel: Select => sel.qualifier } - val rewrite = poundPoundValue(qual) - ctx.log(s"$phaseName rewrote $tree to $rewrite") - rewrite + val rewritten = poundPoundValue(qual) + ctx.log(s"$phaseName rewrote $tree to $rewritten") + rewritten } else tree } @@ -80,7 +80,7 @@ class InterceptedMethods extends MiniPhase { } val Any_!= = defn.Any_!= - val rewrite: Tree = tree.fun.symbol match { + val rewritten: Tree = tree.fun.symbol match { case Any_!= => qual.select(defn.Any_==).appliedToArgs(tree.args).select(defn.Boolean_!) /* @@ -104,7 +104,7 @@ class InterceptedMethods extends MiniPhase { case _ => tree } - ctx.log(s"$phaseName rewrote $tree to $rewrite") - rewrite + ctx.log(s"$phaseName rewrote $tree to $rewritten") + rewritten } } diff --git a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala index 8d3ce14983b7..ebabdf124e7e 100644 --- a/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala +++ b/compiler/src/dotty/tools/dotc/transform/LambdaLift.scala @@ -291,7 +291,7 @@ object LambdaLift { private def newName(sym: Symbol)(implicit ctx: Context): Name = if (sym.isAnonymousFunction && sym.owner.is(Method, butNot = Label)) - sym.name.rewrite { + sym.name.replace { case name: SimpleName => ExpandPrefixName(sym.owner.name.asTermName, name) }.freshened else sym.name.freshened diff --git a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala index d3db6c1b1aa2..3be21d41e716 100644 --- a/compiler/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/compiler/src/dotty/tools/dotc/transform/LazyVals.scala @@ -11,7 +11,7 @@ import Decorators._ import NameOps._ import NameKinds._ import StdNames.nme -import rewrite.Rewrites.patch +import rewrites.Rewrites.patch import util.Positions.Position import dotty.tools.dotc.transform.MegaPhase._ import dotty.tools.dotc.ast.Trees._ diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index a5b78a2c0ebf..d12420f1313b 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -156,7 +156,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase } } - /** 1. If we are in a transparent method but not in a nested quote, mark the transparent method + /** 1. If we are in a rewrite method but not in a nested quote, mark the rewrite method * as a macro. * * 2. If selection is a quote or splice node, record that fact in the current compilation unit. @@ -165,7 +165,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase def markAsMacro(c: Context): Unit = if (c.owner eq c.outer.owner) markAsMacro(c.outer) - else if (c.owner.isTransparentMethod) { + else if (c.owner.isRewriteMethod) { c.owner.setFlag(Macro) } else if (!c.outer.owner.is(Package)) markAsMacro(c.outer) @@ -335,6 +335,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase * Performed to shrink the tree that is known to be erased later. */ private def normalizeErasedRhs(rhs: Tree, sym: Symbol)(implicit ctx: Context) = - if (sym.is(Erased, butNot = Deferred)) dropInlines.transform(rhs) else rhs + if (sym.isEffectivelyErased) dropInlines.transform(rhs) else rhs } } diff --git a/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala b/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala index 38a05099da02..2da2fcd08122 100644 --- a/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala +++ b/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala @@ -29,10 +29,8 @@ class PruneErasedDefs extends MiniPhase with SymTransformer { thisTransform => override def runsAfterGroupsOf = Set(RefChecks.name, ExplicitOuter.name) override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = - if (sym.is(Erased, butNot = Private) && sym.owner.isClass) - sym.copySymDenotation( - //name = UnlinkedErasedName.fresh(sym.name.asTermName), - initFlags = sym.flags | Private) + if (sym.isEffectivelyErased && !sym.is(Private) && sym.owner.isClass) + sym.copySymDenotation(initFlags = sym.flags | Private) else sym override def transformApply(tree: Apply)(implicit ctx: Context) = @@ -41,12 +39,12 @@ class PruneErasedDefs extends MiniPhase with SymTransformer { thisTransform => else tree override def transformValDef(tree: ValDef)(implicit ctx: Context) = - if (tree.symbol.is(Erased) && !tree.rhs.isEmpty) + if (tree.symbol.isEffectivelyErased && !tree.rhs.isEmpty) cpy.ValDef(tree)(rhs = ref(defn.Predef_undefined)) else tree override def transformDefDef(tree: DefDef)(implicit ctx: Context) = - if (tree.symbol.is(Erased) && !tree.rhs.isEmpty) + if (tree.symbol.isEffectivelyErased && !tree.rhs.isEmpty) cpy.DefDef(tree)(rhs = ref(defn.Predef_undefined)) else tree } diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index d5766bc2e23d..eac7e5c0b92a 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -56,7 +56,7 @@ import dotty.tools.dotc.util.SourcePosition * and then performs the same transformation on `'{ ... x1$1.unary_~ ... x2$1.unary_~ ...}`. * * - * For transparent macro definitions we assume that we have a single ~ directly as the RHS. + * For macro definitions we assume that we have a single ~ directly as the RHS. * The Splicer is used to check that the RHS will be interpretable (with the `Splicer`) once inlined. */ class ReifyQuotes extends MacroTransformWithImplicits { @@ -76,7 +76,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = { tree match { - case tree: RefTree if !ctx.inTransparentMethod => + case tree: RefTree if !ctx.inRewriteMethod => assert(!tree.symbol.isQuote) // assert(!tree.symbol.isSplice) // TODO widen ~ type references at stage 0? assert(tree.symbol != defn.QuotedExpr_~) @@ -117,7 +117,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { * @param outer the next outer reifier, null is this is the topmost transformer * @param level the current level, where quotes add one and splices subtract one level. * The initial level is 0, a level `l` where `l > 0` implies code has been quoted `l` times - * and `l == -1` is code inside a top level splice (in an transparent method). + * and `l == -1` is code inside a top level splice (in a rewrite method). * @param levels a stacked map from symbols to the levels in which they were defined * @param embedded a list of embedded quotes (if `inSplice = true`) or splices (if `inQuote = true` */ @@ -250,7 +250,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { def tryHeal(tp: Type, pos: Position)(implicit ctx: Context): Option[String] = tp match { case tp: TypeRef => if (level == -1) { - assert(ctx.owner.ownersIterator.exists(_.is(Transparent))) + assert(ctx.inRewriteMethod) None } else { val reqType = defn.QuotedTypeType.appliedTo(tp) @@ -281,7 +281,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { else i"${sym.name}.this" if (!isThis && sym.maybeOwner.isType && !sym.is(Param)) check(sym.owner, sym.owner.thisType, pos) - else if (level == 1 && sym.isType && sym.is(Param) && sym.owner.is(Transparent) && !outer.isRoot) + else if (level == 1 && sym.isType && sym.is(Param) && sym.owner.isRewriteMethod && !outer.isRoot) importedTags(sym.typeRef) = capturers(sym)(ref(sym)) else if (sym.exists && !sym.isStaticOwner && !levelOK(sym)) for (errMsg <- tryHeal(tp, pos)) @@ -372,9 +372,9 @@ class ReifyQuotes extends MacroTransformWithImplicits { capturers(body.symbol)(body) case _=> val (body1, splices) = nested(isQuote = true).split(body) - if (level == 0 && !ctx.inTransparentMethod) pickledQuote(body1, splices, body.tpe, isType).withPos(quote.pos) + if (level == 0 && !ctx.inRewriteMethod) pickledQuote(body1, splices, body.tpe, isType).withPos(quote.pos) else { - // In top-level splice in an transparent def. Keep the tree as it is, it will be transformed at inline site. + // In top-level splice in a rewrite def. Keep the tree as it is, it will be transformed at inline site. body } } @@ -413,7 +413,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { /** If inside a quote, split the body of the splice into a core and a list of embedded quotes * and make a hole from these parts. Otherwise issue an error, unless we - * are in the body of a transparent method. + * are in the body of a rewrite method. */ private def splice(splice: Select)(implicit ctx: Context): Tree = { if (level > 1) { @@ -430,15 +430,15 @@ class ReifyQuotes extends MacroTransformWithImplicits { val evaluatedSplice = Splicer.splice(splice.qualifier, pos, macroClassLoader)(spliceCtx).withPos(splice.pos) if (ctx.reporter.hasErrors) splice else transform(evaluatedSplice) } - else if (!ctx.owner.is(Transparent)) { // level 0 outside a transparent definition - ctx.error(i"splice outside quotes or transparent method", splice.pos) + else if (!ctx.owner.isRewriteMethod) { // level 0 outside a rewrite method + ctx.error(i"splice outside quotes or rewrite method", splice.pos) splice } - else if (Splicer.canBeSpliced(splice.qualifier)) { // level 0 inside a transparent definition + else if (Splicer.canBeSpliced(splice.qualifier)) { // level 0 inside a rewrite definition nested(isQuote = false).split(splice.qualifier) // Just check PCP splice } - else { // level 0 inside a transparent definition + else { // level 0 inside a rewrite definition ctx.error("Malformed macro call. The contents of the ~ must call a static method and arguments must be quoted or transparent.".stripMargin, splice.pos) splice } @@ -504,7 +504,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { val captured = mutable.LinkedHashMap.empty[Symbol, Tree] val captured2 = capturer(captured) - outer.enteredSyms.foreach(sym => if (!sym.is(Transparent)) capturers.put(sym, captured2)) + outer.enteredSyms.foreach(sym => if (!sym.isRewriteMethod) capturers.put(sym, captured2)) val tree2 = transform(tree) capturers --= outer.enteredSyms @@ -571,10 +571,10 @@ class ReifyQuotes extends MacroTransformWithImplicits { cpy.DefDef(tree)(rhs = defaultValue(tree.rhs.tpe)) case _ => ctx.error( - """Malformed transparent macro. + """Malformed macro. | |Expected the ~ to be at the top of the RHS: - | transparent def foo(x: X, ..., y: Y): Int = ~impl(x, ... '(y)) + | rewrite def foo(x: X, ..., y: Y): Int = ~impl(x, ... '(y)) | |The contents of the splice must call a static method. Arguments must be quoted or inlined. """.stripMargin, tree.rhs.pos) diff --git a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala index f6ae2ff3954e..ea7180b51917 100644 --- a/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala +++ b/compiler/src/dotty/tools/dotc/transform/RenameLifted.scala @@ -37,11 +37,11 @@ class RenameLifted extends MiniPhase with SymTransformer { val fullName = (sym.owner.fullName.toString + name.underlying).toTermName val freshName = UniqueName.fresh(fullName) val info = freshName.asInstanceOf[DerivedName].info - DerivedName(name.underlying.rewrite(rewriteUnique), info) + DerivedName(name.underlying.replace(rewriteUnique), info) case DerivedName(underlying, info: QualifiedInfo) => - underlying.rewrite(rewriteUnique).derived(info) + underlying.replace(rewriteUnique).derived(info) } - sym.name.rewrite(rewriteUnique) + sym.name.replace(rewriteUnique) } } diff --git a/compiler/src/dotty/tools/dotc/transform/Splicer.scala b/compiler/src/dotty/tools/dotc/transform/Splicer.scala index 92de6ed118c1..f4e11cbb984f 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicer.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicer.scala @@ -147,7 +147,7 @@ object Splicer { } } - private def extraMsg = ". The most common reason for that is that you cannot use transparent macro implementations in the same compilation run that defines them" + private def extraMsg = ". The most common reason for that is that you apply macros in the compilation run that defines them" private def stopIfRuntimeException[T](thunk: => T): T = { try thunk @@ -239,9 +239,9 @@ object Splicer { def interpretStaticMethodCall(fn: tpd.Tree, args: => List[Boolean])(implicit env: Env): Boolean = args.forall(identity) def unexpectedTree(tree: tpd.Tree)(implicit env: Env): Boolean = { - // Assuming that top-level splices can only be in transparent methods + // Assuming that top-level splices can only be in rewrite methods // and splices are expanded at inline site, references to transparent values - // will be know literal constant trees. + // will be known literal constant trees. tree.symbol.is(Transparent) } } diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 19ed183f357e..f58e79edb462 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -264,7 +264,7 @@ class TreeChecker extends Phase with SymTransformer { * completely in phase `Erasure` if they are defined in a currently compiled unit. */ override def excludeFromDoubleDeclCheck(sym: Symbol)(implicit ctx: Context) = - sym.is(PrivateErased) && !sym.initial.is(Private) + sym.isEffectivelyErased && sym.is(Private) && !sym.initial.is(Private) override def typed(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): tpd.Tree = { val tpdTree = super.typed(tree, pt) @@ -512,6 +512,4 @@ object TreeChecker { tp } }.apply(tp0) - - private val PrivateErased = allOf(Private, Erased) } diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 9f6793760017..2e62a0ea3da0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -371,7 +371,7 @@ object Checking { if (sym.is(Transparent) && ( sym.is(ParamAccessor) && sym.owner.isClass - || sym.is(TermParam) && !sym.owner.isTransparentMethod + || sym.is(TermParam) && !sym.owner.isRewriteMethod )) fail(ParamsNoTransparent(sym.owner)) @@ -400,6 +400,7 @@ object Checking { checkWithDeferred(Private) checkWithDeferred(Final) checkWithDeferred(Transparent) + checkWithDeferred(Rewrite) } if (sym.isValueClass && sym.is(Trait) && !sym.isRefinementClass) fail(CannotExtendAnyVal(sym)) @@ -407,9 +408,10 @@ object Checking { checkCombination(Private, Protected) checkCombination(Abstract, Override) checkCombination(Lazy, Transparent) - checkCombination(Module, Transparent) + checkCombination(Rewrite, Transparent) checkNoConflict(Lazy, ParamAccessor, s"parameter may not be `lazy`") if (sym.is(Transparent)) checkApplicable(Transparent, sym.isTerm && !sym.is(Mutable | Module)) + if (sym.is(Rewrite)) checkApplicable(Rewrite, sym.is(Method, butNot = Accessor)) if (sym.is(Lazy)) checkApplicable(Lazy, !sym.is(Method | Mutable)) if (sym.isType && !sym.is(Deferred)) for (cls <- sym.allOverriddenSymbols.filter(_.isClass)) { @@ -676,7 +678,7 @@ trait Checking { tree.tpe.widenTermRefExpr match { case tp: ConstantType if exprPurity(tree) >= purityLevel => // ok case _ => - val allow = ctx.erasedTypes || ctx.inTransparentMethod + val allow = ctx.erasedTypes || ctx.inRewriteMethod if (!allow) ctx.error(em"$what must be a constant expression", tree.pos) } } @@ -694,7 +696,7 @@ trait Checking { def checkDecl(decl: Symbol): Unit = { for (other <- seen(decl.name)) { typr.println(i"conflict? $decl $other") - if (decl.matches(other) /*&& !decl.is(Erased) && !other.is(Erased)*/) { + if (decl.matches(other)) { def doubleDefError(decl: Symbol, other: Symbol): Unit = if (!decl.info.isErroneous && !other.info.isErroneous) ctx.error(DoubleDeclaration(decl, other), decl.pos) @@ -845,6 +847,11 @@ trait Checking { checker.traverse(tree) } + /** Check that we are in a rewrite context (inside a rewrite method or in inlined code) */ + def checkInRewriteContext(what: String, pos: Position)(implicit ctx: Context) = + if (!ctx.inRewriteMethod && !ctx.isInlineContext) + ctx.error(em"$what can only be used in a rewrite method", pos) + /** Check that all case classes that extend `scala.Enum` are `enum` cases */ def checkEnum(cdef: untpd.TypeDef, cls: Symbol)(implicit ctx: Context): Unit = { import untpd.modsDeco @@ -956,5 +963,6 @@ trait NoChecking extends ReChecking { override def checkCaseInheritance(parentSym: Symbol, caseCls: ClassSymbol, pos: Position)(implicit ctx: Context) = () override def checkNoForwardDependencies(vparams: List[ValDef])(implicit ctx: Context): Unit = () override def checkMembersOK(tp: Type, pos: Position)(implicit ctx: Context): Type = tp + override def checkInRewriteContext(what: String, pos: Position)(implicit ctx: Context) = () override def checkFeature(base: ClassSymbol, name: TermName, description: => String, featureUseSite: Symbol, pos: Position)(implicit ctx: Context): Unit = () } diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index feb6bc391a55..1e09e7e9702f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -1144,8 +1144,8 @@ trait Implicits { self: Typer => else implicitScope(wildProto).eligible searchImplicits(eligible, contextual) match { case result: SearchSuccess => - if (contextual && ctx.mode.is(Mode.TransparentBody)) - PrepareTransparent.markContextualImplicit(result.tree) + if (contextual && ctx.mode.is(Mode.InlineableBody)) + PrepareInlineable.markContextualImplicit(result.tree) result case failure: SearchFailure => failure.reason match { diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index ec4e7f725a28..ed09a387f7dd 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -15,7 +15,7 @@ import StdNames._ import Contexts.Context import Names.{Name, TermName, EmptyTermName} import NameOps._ -import NameKinds.{ClassifiedNameKind, InlineAccessorName, UniqueInlineName, TransparentScrutineeName, TransparentBinderName} +import NameKinds.{ClassifiedNameKind, InlineAccessorName, UniqueInlineName, RewriteScrutineeName, RewriteBinderName} import ProtoTypes.selectionProto import SymDenotations.SymDenotation import Annotations._ @@ -43,11 +43,11 @@ object Inliner { def inlineBindings(implicit ctx: Context): MutableSymbolMap[Tree] = ctx.property(InlineBindings).get - /** `sym` has a transparent method with a known body to inline (note: definitions coming - * from Scala2x class files might be `@forceInline`, but still lack that body. + /** `sym` is a rewrite or transparent method with a known body to inline (note: definitions coming + * from Scala2x class files might be `@forceInline`, but still lack that body). */ def hasBodyToInline(sym: SymDenotation)(implicit ctx: Context): Boolean = - sym.isTransparentInlineable && sym.hasAnnotation(defn.BodyAnnot) + sym.isInlineable && sym.hasAnnotation(defn.BodyAnnot) /** The body to inline for method `sym`. * @pre hasBodyToInline(sym) @@ -55,17 +55,11 @@ object Inliner { def bodyToInline(sym: SymDenotation)(implicit ctx: Context): Tree = sym.unforcedAnnotation(defn.BodyAnnot).get.tree - /** Should call with method `meth` be inlined in this context? */ - def isInlineable(meth: Symbol)(implicit ctx: Context): Boolean = { - - def suppressInline = - ctx.inTransparentMethod || - ctx.settings.YnoInline.value || - ctx.isAfterTyper || - ctx.reporter.hasErrors - - hasBodyToInline(meth) && !suppressInline - } + /** Should call to method `meth` be inlined in this context? */ + def isInlineable(meth: Symbol)(implicit ctx: Context): Boolean = + (meth.is(Rewrite) || meth.is(Transparent) && ctx.isInlineContext) && + hasBodyToInline(meth) && + !ctx.inRewriteMethod /** Should call be inlined in this context? */ def isInlineable(tree: Tree)(implicit ctx: Context): Boolean = tree match { @@ -73,11 +67,7 @@ object Inliner { case _ => isInlineable(tree.symbol) } - /** Is `meth` a transparent method that should be inlined in this context? */ - def isTransparentInlineable(meth: Symbol)(implicit ctx: Context): Boolean = - meth.isTransparentInlineable && isInlineable(meth) - - /** Try to inline a call to a transparent method. Fail with error if the maximal + /** Try to inline a call to a rewrite or transparent method. Fail with error if the maximal * inline depth is exceeded. * * @param tree The call to inline @@ -141,7 +131,7 @@ object Inliner { errorTree( tree, i"""|Maximal number of successive inlines (${ctx.settings.XmaxInlines.value}) exceeded, - |Maybe this is caused by a recursive transparent method? + |Maybe this is caused by a recursive rewrite method? |You can use -Xmax:inlines to change the limit.""", (tree :: enclosingInlineds).last.pos ) @@ -185,8 +175,8 @@ object Inliner { /** Produces an inlined version of `call` via its `inlined` method. * - * @param call the original call to an `inline` method - * @param rhsToInline the body of the transparent method that replaces the call. + * @param call the original call to an inlineable method + * @param rhsToInline the body of the inlineable method that replaces the call. */ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { import tpd._ @@ -199,7 +189,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { // Make sure all type arguments to the call are fully determined for (targ <- callTypeArgs) fullyDefinedType(targ.tpe, "inlined type argument", targ.pos) - /** A map from parameter names of the transparent method to references of the actual arguments. + /** A map from parameter names of the inlineable method to references of the actual arguments. * For a type argument this is the full argument type. * For a value argument, it is a reference to either the argument value * (if the argument is a pure expression of singleton type), or to `val` or `def` acting @@ -207,7 +197,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { */ private val paramBinding = new mutable.HashMap[Name, Type] - /** A map from references to (type and value) parameters of the transparent method + /** A map from references to (type and value) parameters of the inlineable method * to their corresponding argument or proxy references, as given by `paramBinding`. */ private val paramProxy = new mutable.HashMap[Type, Type] @@ -506,9 +496,9 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { } } - /** If we are inlining a transparent method and `tree` is equivalent to `new C(args).x` - * where class `C` does not have initialization code and `x` is a parameter corresponding - * to one of the arguments `args`, the corresponding argument, prefixed by the evaluation + /** If `tree` is equivalent to `new C(args).x` where class `C` does not have + * initialization code and `x` is a parameter corresponding to one of the + * arguments `args`, the corresponding argument, prefixed by the evaluation * of impure arguments, otherwise `tree` itself. */ def reduceProjection(tree: Tree)(implicit ctx: Context): Tree = { @@ -639,7 +629,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { */ type MatchRedux = Option[(List[MemberDef], untpd.Tree)] - /** Reduce a toplevel match of a transparent function + /** Reduce a rewrite match * @param scrutinee the scrutinee expression, assumed to be pure * @param scrutType its fully defined type * @param cases All cases of the match @@ -647,7 +637,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { * @return optionally, if match can be reduced to a matching case: A pair of * bindings for all pattern-bound variables and the untyped RHS of the case. */ - def reduceTopLevelMatch(scrutinee: Tree, scrutType: Type, cases: List[untpd.CaseDef], typer: Typer)(implicit ctx: Context): MatchRedux = { + def reduceRewriteMatch(scrutinee: Tree, scrutType: Type, cases: List[untpd.CaseDef], typer: Typer)(implicit ctx: Context): MatchRedux = { val gadtSyms = typer.gadtSyms(scrutType) @@ -738,7 +728,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { for ((pat, accessor) <- (pats, caseAccessors).zipped) subOK = subOK && { val rhs = constToLiteral(reduceProjection(ref(scrut).select(accessor).ensureApplied)) - val elem = newBinding(TransparentBinderName.fresh(), Synthetic, rhs) + val elem = newBinding(RewriteBinderName.fresh(), Synthetic, rhs) reducePattern(bindingsBuf, elem.termRef, pat) } subOK @@ -751,7 +741,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { } /** The initial scrutinee binding: `val $scrutineeN = ` */ - val scrutineeSym = newSym(TransparentScrutineeName.fresh(), Synthetic, scrutType).asTerm + val scrutineeSym = newSym(RewriteScrutineeName.fresh(), Synthetic, scrutType).asTerm val scrutineeBinding = normalizeBinding(ValDef(scrutineeSym, scrutinee)) def reduceCase(cdef: untpd.CaseDef): MatchRedux = { @@ -782,8 +772,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { } } - /** A typer for inlined bodies of transparent methods. Beyond standard typing - * an inline typer performs the following functions: + /** A typer for inlined bodies. Beyond standard typing, an inline typer performs + * the following functions: * * 1. Implement constant folding over inlined code * 2. Selectively expand ifs with constant conditions @@ -821,33 +811,34 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { if (isIdempotentExpr(cond1)) selected else Block(cond1 :: Nil, selected) case cond1 => + if (tree.isInstanceOf[untpd.RewriteIf]) + errorTree(tree, em"""cannot reduce rewrite if + | its condition ${tree.cond} + | is not a constant value.""") val if1 = untpd.cpy.If(tree)(cond = untpd.TypedSplice(cond1)) super.typedIf(if1, pt) } - override def typedMatchFinish(tree: untpd.Match, sel: Tree, selType: Type, pt: Type)(implicit ctx: Context) = - tree.getAttachment(PrepareTransparent.TopLevelMatch) match { - case Some(_) if !ctx.owner.isTransparentMethod => // don't reduce match of nested transparent yet - reduceTopLevelMatch(sel, sel.tpe, tree.cases, this) match { - case Some((caseBindings, rhs)) => - var rhsCtx = ctx.fresh.setNewScope - for (binding <- caseBindings) { - matchBindingsBuf += binding - rhsCtx.enter(binding.symbol) - } - typedExpr(rhs, pt)(rhsCtx) - case None => - def guardStr(guard: untpd.Tree) = if (guard.isEmpty) "" else i" if $guard" - def patStr(cdef: untpd.CaseDef) = i"case ${cdef.pat}${guardStr(cdef.guard)}" - errorTree(tree, em"""cannot reduce top-level match of transparent function with - | scrutinee: $sel : ${sel.tpe} - | patterns : ${tree.cases.map(patStr).mkString("\n ")} - | - | Hint: if you do not expect the match to be reduced, put it in a locally { ... } block.""") - } - case _ => - super.typedMatchFinish(tree, sel, selType, pt) - } + override def typedMatchFinish(tree: untpd.Match, sel: Tree, selType: Type, pt: Type)(implicit ctx: Context) = tree match { + case _: untpd.RewriteMatch if !ctx.owner.isRewriteMethod => // don't reduce match of nested rewrite method yet + reduceRewriteMatch(sel, sel.tpe, tree.cases, this) match { + case Some((caseBindings, rhs)) => + var rhsCtx = ctx.fresh.setNewScope + for (binding <- caseBindings) { + matchBindingsBuf += binding + rhsCtx.enter(binding.symbol) + } + typedExpr(rhs, pt)(rhsCtx) + case None => + def guardStr(guard: untpd.Tree) = if (guard.isEmpty) "" else i" if $guard" + def patStr(cdef: untpd.CaseDef) = i"case ${cdef.pat}${guardStr(cdef.guard)}" + errorTree(tree, em"""cannot reduce rewrite match with + | scrutinee: $sel : ${sel.tpe} + | patterns : ${tree.cases.map(patStr).mkString("\n ")}.""") + } + case _ => + super.typedMatchFinish(tree, sel, selType, pt) + } override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context) = constToLiteral(betaReduce(super.typedApply(tree, pt))) @@ -897,7 +888,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) { case Some(x) => x > 1 || x == 1 && !boundSym.is(Method) case none => true } - } && !boundSym.is(TransparentImplicitMethod) + } && !boundSym.is(ImplicitRewriteMethod) val (termBindings, typeBindings) = bindings.partition(_.symbol.isTerm) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index ed32410d2f74..001a100f2a96 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -754,14 +754,14 @@ class Namer { typer: Typer => val ann = Annotation.deferred(cls, implicit ctx => typedAnnotation(annotTree)) sym.addAnnotation(ann) if (cls == defn.ForceInlineAnnot && sym.is(Method, butNot = Accessor)) - sym.setFlag(Transparent) + sym.setFlag(Rewrite) } case _ => } private def addInlineInfo(sym: Symbol) = original match { - case original: untpd.DefDef if sym.isTransparentInlineable => - PrepareTransparent.registerInlineInfo( + case original: untpd.DefDef if sym.isInlineable => + PrepareInlineable.registerInlineInfo( sym, original.rhs, implicit ctx => typedAheadExpr(original).asInstanceOf[tpd.DefDef].rhs @@ -1075,13 +1075,13 @@ class Namer { typer: Typer => // println(s"final inherited for $sym: ${inherited.toString}") !!! // println(s"owner = ${sym.owner}, decls = ${sym.owner.info.decls.show}") - def isInline = sym.is(FinalOrTransparent, butNot = Method | Mutable) + def isTransparentVal = sym.is(FinalOrTransparent, butNot = Method | Mutable) // Widen rhs type and eliminate `|' but keep ConstantTypes if // definition is inline (i.e. final in Scala2) and keep module singleton types // instead of widening to the underlying module class types. def widenRhs(tp: Type): Type = tp.widenTermRefExpr match { - case ctp: ConstantType if isInline => ctp + case ctp: ConstantType if isTransparentVal => ctp case ref: TypeRef if ref.symbol.is(ModuleClass) => tp case _ => tp.widen.widenUnion } @@ -1091,10 +1091,7 @@ class Namer { typer: Typer => def dealiasIfUnit(tp: Type) = if (tp.isRef(defn.UnitClass)) defn.UnitType else tp var rhsCtx = ctx.addMode(Mode.InferringReturnType) - if (sym.isTransparentMethod) { - rhsCtx = rhsCtx.addMode(Mode.TransparentBody) - PrepareTransparent.markTopLevelMatches(sym, mdef.rhs) - } + if (sym.isInlineable) rhsCtx = rhsCtx.addMode(Mode.InlineableBody) def rhsType = typedAheadExpr(mdef.rhs, inherited orElse rhsProto)(rhsCtx).tpe // Approximate a type `tp` with a type that does not contain skolem types. @@ -1195,15 +1192,6 @@ class Namer { typer: Typer => instantiateDependent(restpe, typeParams, termParamss) ctx.methodType(tparams map symbolOfTree, termParamss, restpe, isJava = ddef.mods is JavaDefined) } - if (sym.is(Transparent) && - sym.unforcedAnnotation(defn.ForceInlineAnnot).isEmpty) - // Need to keep @forceInline annotated methods around to get to parity with Scala. - // This is necessary at least until we have full bootstrap. Right now - // dotty-bootstrapped involves running the Dotty compiler compiled with Scala 2 with - // a Dotty runtime library compiled with Dotty. If we erase @forceInline annotated - // methods, this means that the support methods in dotty.runtime.LazyVals vanish. - // But they are needed for running the lazy val implementations in the Scala-2 compiled compiler. - sym.setFlag(Erased) if (isConstructor) { // set result type tree to unit, but take the current class as result type of the symbol typedAheadType(ddef.tpt, defn.UnitType) diff --git a/compiler/src/dotty/tools/dotc/typer/PrepareTransparent.scala b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala similarity index 94% rename from compiler/src/dotty/tools/dotc/typer/PrepareTransparent.scala rename to compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala index 44156f56e74f..d98096c63f3b 100644 --- a/compiler/src/dotty/tools/dotc/typer/PrepareTransparent.scala +++ b/compiler/src/dotty/tools/dotc/typer/PrepareInlineable.scala @@ -30,7 +30,7 @@ import util.Positions.Position import util.Property import ast.TreeInfo -object PrepareTransparent { +object PrepareInlineable { import tpd._ /** Marks an implicit reference found in the context (as opposed to the implicit scope) @@ -39,22 +39,10 @@ object PrepareTransparent { */ private val ContextualImplicit = new Property.StickyKey[Unit] - /** An attachment labeling a toplevel match node of a transparent function */ - val TopLevelMatch = new Property.StickyKey[Unit] - def markContextualImplicit(tree: Tree)(implicit ctx: Context): Unit = if (!defn.ScalaPredefModule.moduleClass.derivesFrom(tree.symbol.maybeOwner)) methPart(tree).putAttachment(ContextualImplicit, ()) - def markTopLevelMatches(meth: Symbol, tree: untpd.Tree)(implicit ctx: Context): Unit = tree match { - case tree: untpd.Match => - tree.putAttachment(TopLevelMatch, ()) - for (cdef <- tree.cases) markTopLevelMatches(meth, cdef.body) - case tree: untpd.Block => - markTopLevelMatches(meth, tree.expr) - case _ => - } - class InlineAccessors extends AccessProxies { /** If an inline accessor name wraps a unique inline name, this is taken as indication @@ -76,14 +64,14 @@ object PrepareTransparent { * by excluding all symbols properly contained in the inlined method. * * Constant vals don't need accessors since they are inlined in FirstTransform. - * Transparent methods don't need accessors since they are inlined in Typer. + * Rewrite methods don't need accessors since they are inlined in Typer. */ def needsAccessor(sym: Symbol)(implicit ctx: Context) = sym.isTerm && (sym.is(AccessFlags) || sym.privateWithin.exists) && !sym.isContainedIn(inlineSym) && !(sym.isStable && sym.info.widenTermRefExpr.isInstanceOf[ConstantType]) && - !sym.is(TransparentMethod) + !sym.isRewriteMethod def preTransform(tree: Tree)(implicit ctx: Context): Tree @@ -107,7 +95,7 @@ object PrepareTransparent { def preTransform(tree: Tree)(implicit ctx: Context): Tree = tree match { case tree: RefTree if needsAccessor(tree.symbol) => if (tree.symbol.isConstructor) { - ctx.error("Implementation restriction: cannot use private constructors in transparent methods", tree.pos) + ctx.error("Implementation restriction: cannot use private constructors in transparent or rewrite methods", tree.pos) tree // TODO: create a proper accessor for the private constructor } else useAccessor(tree) @@ -127,11 +115,11 @@ object PrepareTransparent { * private[inlines] def next[U](y: U): (T, U) = (x, y) * } * class TestPassing { - * transparent def foo[A](x: A): (A, Int) = { + * rewrite def foo[A](x: A): (A, Int) = { * val c = new C[A](x) * c.next(1) * } - * transparent def bar[A](x: A): (A, String) = { + * rewrite def bar[A](x: A): (A, String) = { * val c = new C[A](x) * c.next("") * } @@ -218,7 +206,7 @@ object PrepareTransparent { def makeInlineable(tree: Tree)(implicit ctx: Context) = { val inlineSym = ctx.owner if (inlineSym.owner.isTerm) - // Transparent methods in local scopes can only be called in the scope they are defined, + // Inlineable methods in local scopes can only be called in the scope they are defined, // so no accessors are needed for them. tree else @@ -233,9 +221,9 @@ object PrepareTransparent { def isLocal(sym: Symbol, inlineMethod: Symbol)(implicit ctx: Context) = isLocalOrParam(sym, inlineMethod) && !(sym.is(Param) && sym.owner == inlineMethod) - /** Register inline info for given transparent method `sym`. + /** Register inline info for given inlineable method `sym`. * - * @param sym The symbol denotatioon of the transparent method for which info is registered + * @param sym The symbol denotation of the inlineable method for which info is registered * @param treeExpr A function that computes the tree to be inlined, given a context * This tree may still refer to non-public members. * @param ctx The context to use for evaluating `treeExpr`. It needs @@ -419,12 +407,12 @@ object PrepareTransparent { val localImplicit = iref.symbol.asTerm.copy( owner = inlineMethod, name = UniqueInlineName.fresh(iref.symbol.name.asTermName), - flags = Implicit | Method | Stable | iref.symbol.flags & (Transparent | Erased), + flags = Implicit | Method | Stable | iref.symbol.flags & (Rewrite | Erased), info = iref.tpe.widen.ensureMethodic, coord = inlineMethod.pos).asTerm val idef = polyDefDef(localImplicit, tps => vrefss => iref.appliedToTypes(tps).appliedToArgss(vrefss)) - if (localImplicit.is(Transparent)) { + if (localImplicit.is(Rewrite)) { // produce a Body annotation for inlining def untype(tree: Tree): untpd.Tree = tree match { case Apply(fn, args) => untpd.cpy.Apply(tree)(untype(fn), args) diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index 020d3a8dcfd8..1421bad81b34 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -74,14 +74,14 @@ object ProtoTypes { res } - /** Constrain result with special case if `meth` is a transparent method in an inlineable context. + /** Constrain result with special case if `meth` is an inlineable method in an inlineable context. * In that case, we should always succeed and not constrain type parameters in the expected type, * because the actual return type can be a subtype of the currently known return type. * However, we should constrain parameters of the declared return type. This distinction is * achieved by replacing expected type parameters with wildcards. */ def constrainResult(meth: Symbol, mt: Type, pt: Type)(implicit ctx: Context): Boolean = - if (Inliner.isTransparentInlineable(meth)) { + if (Inliner.isInlineable(meth)) { constrainResult(mt, wildApprox(pt)) true } diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala index 6846016d0bbc..a8346503888b 100644 --- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala +++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala @@ -121,7 +121,6 @@ class ReTyper extends Typer with ReChecking { override def inferView(from: Tree, to: Type)(implicit ctx: Context): Implicits.SearchResult = Implicits.NoMatchingImplicitsFailure override def checkCanEqual(ltp: Type, rtp: Type, pos: Position)(implicit ctx: Context): Unit = () - override def inlineExpansion(mdef: DefDef)(implicit ctx: Context): Tree = mdef override protected def addAccessorDefs(cls: Symbol, body: List[Tree])(implicit ctx: Context): List[Tree] = body override protected def checkEqualityEvidence(tree: tpd.Tree, pt: Type)(implicit ctx: Context): Unit = () } diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 41b955c907bb..ab5dbbf1c0bd 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -43,7 +43,7 @@ object RefChecks { if defaultGetterClass.isClass ) { val defaultGetterNames = defaultGetterClass.asClass.memberNames(defaultMethodFilter) - val defaultMethodNames = defaultGetterNames map { _ rewrite { + val defaultMethodNames = defaultGetterNames map { _ replace { case DefaultGetterName(methName, _) => methName }} @@ -143,9 +143,10 @@ object RefChecks { * 1.8.1 M's type is a subtype of O's type, or * 1.8.2 M is of type []S, O is of type ()T and S <: T, or * 1.8.3 M is of type ()S, O is of type []T and S <: T, or - * 1.9 M must not be a typelevel def or a Dotty macro def - * 1.10. If M is a 2.x macro def, O cannot be deferred unless there's a concrete method overriding O. - * 1.11. If M is not a macro def, O cannot be a macro def. + * 1.9 If M is an erased def, O must be as well + * 1.10 If `M` is a rewrite or Scala2x macro method, O cannot be deferred unless + * there's also a concrete method that M overrides. + * 1.11. If O is a Scala-2 macro, M must be a Scala-2 macro. * 2. Check that only abstract classes have deferred members * 3. Check that concrete classes do not have deferred definitions * that are not implemented in a subclass. @@ -376,14 +377,13 @@ object RefChecks { overrideError("may not override a non-lazy value") } else if (other.is(Lazy) && !other.isRealMethod && !member.is(Lazy)) { overrideError("must be declared lazy to override a lazy value") - } else if (member.is(Erased) && member.allOverriddenSymbols.forall(_.is(Deferred))) { // (1.9) - overrideError("is an erased method, may not override only deferred methods") - } else if (member.is(Macro, butNot = Scala2x)) { // (1.9) - overrideError("is a macro, may not override anything") - } else if (other.is(Deferred) && member.is(Scala2Macro) && member.extendedOverriddenSymbols.forall(_.is(Deferred))) { // (1.10) - overrideError("cannot be used here - term macros cannot override abstract methods") - } else if (other.is(Macro) && !member.is(Macro)) { // (1.11) - overrideError("cannot be used here - only term macros can override term macros") + } else if (member.is(Erased) && !other.is(Erased)) { // (1.9) + overrideError("is erased, cannot override non-erased member") + } else if ((member.is(Rewrite) || member.is(Scala2Macro)) && other.is(Deferred) && + member.extendedOverriddenSymbols.forall(_.is(Deferred))) { // (1.10) + overrideError("is a rewrite method, must override at least one concrete method") + } else if (other.is(Scala2Macro) && !member.is(Scala2Macro)) { // (1.11) + overrideError("cannot be used here - only Scala-2 macros can override Scala-2 macros") } else if (!compatibleTypes(memberTp(self), otherTp(self)) && !compatibleTypes(memberTp(upwardsSelf), otherTp(upwardsSelf))) { overrideError("has incompatible type" + err.whyNoMatchStr(memberTp(self), otherTp(self))) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index ee076403eb35..2e7d03c6031c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -34,7 +34,7 @@ import annotation.tailrec import Implicits._ import util.Stats.{record, track} import config.Printers.{gadts, typr} -import rewrite.Rewrites.patch +import rewrites.Rewrites.patch import NavigateAST._ import transform.SymUtils._ import reporting.trace @@ -476,9 +476,9 @@ class Typer extends Namer case pt: SelectionProto if pt.name == nme.CONSTRUCTOR => true case _ => false } - val enclosingTransparent = ctx.owner.ownersIterator.findSymbol(_.isTransparentMethod) - if (enclosingTransparent.exists && !PrepareTransparent.isLocal(qual1.symbol, enclosingTransparent)) - ctx.error(SuperCallsNotAllowedTransparent(enclosingTransparent), tree.pos) + val enclosingInlineable = ctx.owner.ownersIterator.findSymbol(_.isInlineable) + if (enclosingInlineable.exists && !PrepareInlineable.isLocal(qual1.symbol, enclosingInlineable)) + ctx.error(SuperCallsNotAllowedInlineable(enclosingInlineable), tree.pos) pt match { case pt: SelectionProto if pt.name.isTypeName => qual1 // don't do super references for types; they are meaningless anyway @@ -709,6 +709,7 @@ class Typer extends Namer } def typedIf(tree: untpd.If, pt: Type)(implicit ctx: Context): Tree = track("typedIf") { + if (tree.isInstanceOf[untpd.RewriteIf]) checkInRewriteContext("rewrite if", tree.pos) val cond1 = typed(tree.cond, defn.BooleanType) val thenp2 :: elsep2 :: Nil = harmonic(harmonize) { val thenp1 = typed(tree.thenp, pt.notApplied) @@ -974,18 +975,18 @@ class Typer extends Namer val unchecked = pt.isRef(defn.PartialFunctionClass) typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked) withPos tree.pos, pt) case id @ untpd.ImplicitScrutinee() => - if (tree.getAttachment(PrepareTransparent.TopLevelMatch).isEmpty) - ctx.error(em"implicit match cannot be used here; it must occur as a toplevel match of a transparent method", tree.pos) + checkInRewriteContext("implicit match", tree.pos) val sel1 = id.withType(defn.ImplicitScrutineeTypeRef) typedMatchFinish(tree, sel1, sel1.tpe, pt) case _ => + if (tree.isInstanceOf[untpd.RewriteMatch]) checkInRewriteContext("rewrite match", tree.pos) val sel1 = typedExpr(tree.selector) val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.pos).widen typedMatchFinish(tree, sel1, selType, pt) } } - // Overridden in InlineTyper for transparent matches + // Overridden in InlineTyper for rewrite matches def typedMatchFinish(tree: untpd.Match, sel: Tree, selType: Type, pt: Type)(implicit ctx: Context): Tree = { val cases1 = harmonic(harmonize)(typedCases(tree.cases, selType, pt.notApplied)) .asInstanceOf[List[CaseDef]] @@ -1088,8 +1089,8 @@ class Typer extends Namer (EmptyTree, WildcardType) } else if (owner != cx.outer.owner && owner.isRealMethod) { - if (owner.isTransparentMethod) - (EmptyTree, errorType(NoReturnFromTransparent(owner), tree.pos)) + if (owner.isInlineable) + (EmptyTree, errorType(NoReturnFromInlineable(owner), tree.pos)) else if (!owner.isCompleted) (EmptyTree, errorType(MissingReturnTypeWithReturnStatement(owner), tree.pos)) else { @@ -1406,7 +1407,7 @@ class Typer extends Namer private def patchIfLazy(vdef: ValDef)(implicit ctx: Context): Unit = { val sym = vdef.symbol if (sym.is(Lazy, butNot = Deferred | Module | Synthetic) && !sym.isVolatile && - ctx.scala2Mode && ctx.settings.rewrite.value.isDefined && + ctx.scala2Mode && ctx.settings.`rewrite`.value.isDefined && !ctx.isAfterTyper) patch(Position(toUntyped(vdef).pos.start), "@volatile ") } @@ -1455,13 +1456,10 @@ class Typer extends Namer (tparams1, sym.owner.typeParams).zipped.foreach ((tdef, tparam) => rhsCtx.gadt.setBounds(tdef.symbol, TypeAlias(tparam.typeRef))) } - if (sym.isTransparentMethod) { - rhsCtx = rhsCtx.addMode(Mode.TransparentBody) - PrepareTransparent.markTopLevelMatches(sym, ddef.rhs) - } + if (sym.isInlineable) rhsCtx = rhsCtx.addMode(Mode.InlineableBody) val rhs1 = typedExpr(ddef.rhs, tpt1.tpe)(rhsCtx) - if (sym.isTransparentInlineable) PrepareTransparent.registerInlineInfo(sym, ddef.rhs, _ => rhs1) + if (sym.isInlineable) PrepareInlineable.registerInlineInfo(sym, ddef.rhs, _ => rhs1) if (sym.isConstructor && !sym.isPrimaryConstructor) for (param <- tparams1 ::: vparamss1.flatten) @@ -1930,7 +1928,7 @@ class Typer extends Namer case none => typed(mdef) match { case mdef1: DefDef if Inliner.hasBodyToInline(mdef1.symbol) => - assert(mdef1.symbol.isTransparentInlineable, mdef.symbol) + assert(mdef1.symbol.isInlineable, mdef.symbol) Inliner.bodyToInline(mdef1.symbol) // just make sure accessors are computed, buf += mdef1 // but keep original definition, since inline-expanded code // is pickled in this case. @@ -1965,13 +1963,6 @@ class Typer extends Namer checkEnumCompanions(traverse(stats)(localCtx), enumContexts) } - /** Given a transparent method `mdef`, the method rewritten so that its body - * uses accessors to access non-public members. - * Overwritten in Retyper to return `mdef` unchanged. - */ - protected def inlineExpansion(mdef: DefDef)(implicit ctx: Context): Tree = - tpd.cpy.DefDef(mdef)(rhs = Inliner.bodyToInline(mdef.symbol)) - def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = typed(tree, pt)(ctx retractMode Mode.PatternOrTypeBits) def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = // todo: retract mode between Type and Pattern? @@ -2353,7 +2344,7 @@ class Typer extends Namer // - the current tree is a synthetic apply which is not expandable (eta-expasion would simply undo that) if (arity >= 0 && !tree.symbol.isConstructor && - !tree.symbol.is(TransparentMethod) && + !tree.symbol.is(RewriteMethod) && !ctx.mode.is(Mode.Pattern) && !(isSyntheticApply(tree) && !isExpandableApply)) simplify(typed(etaExpand(tree, wtp, arity), pt), pt, locked) @@ -2380,7 +2371,10 @@ class Typer extends Namer checkEqualityEvidence(tree, pt) tree } - else if (Inliner.isInlineable(tree)) { + else if (Inliner.isInlineable(tree) && + !ctx.settings.YnoInline.value && + !ctx.isAfterTyper && + !ctx.reporter.hasErrors) { tree.tpe <:< wildApprox(pt) readaptSimplified(Inliner.inlineCall(tree, pt)) } diff --git a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala index fa626f8b6825..a5d3a1878d3b 100644 --- a/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala +++ b/compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala @@ -8,7 +8,7 @@ import Decorators._ import Variances._ import NameKinds._ import util.Positions._ -import rewrite.Rewrites.patch +import rewrites.Rewrites.patch import config.Printers.variances import reporting.trace diff --git a/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala index 2ab838ac271e..0505162b57a3 100644 --- a/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala @@ -12,7 +12,7 @@ class InlineBytecodeTests extends DottyBytecodeTest { @Test def inlineUnit = { val source = """ |class Foo { - | transparent def foo: Int = 1 + | rewrite def foo: Int = 1 | @forceInline def bar: Int = 1 | | def meth1: Unit = foo diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 53af8e996140..6820fa8bb6f4 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -244,7 +244,7 @@ class CompilationTests extends ParallelTesting { compileShallowFilesInDir("compiler/src/dotty/tools/dotc/parsing", opt) + compileShallowFilesInDir("compiler/src/dotty/tools/dotc/printing", opt) + compileShallowFilesInDir("compiler/src/dotty/tools/dotc/reporting", opt) + - compileShallowFilesInDir("compiler/src/dotty/tools/dotc/rewrite", opt) + + compileShallowFilesInDir("compiler/src/dotty/tools/dotc/rewrites", opt) + compileShallowFilesInDir("compiler/src/dotty/tools/dotc/transform", opt) + compileShallowFilesInDir("compiler/src/dotty/tools/dotc/typer", opt) + compileShallowFilesInDir("compiler/src/dotty/tools/dotc/util", opt) + diff --git a/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala b/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala index 4068f440547b..3eaca3ee95a9 100644 --- a/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala +++ b/compiler/test/dotty/tools/dotc/parsing/ModifiersParsingTest.scala @@ -121,6 +121,7 @@ class ModifiersParsingTest { | | abstract override def f: Boolean | transparent def g(n: Int) = ??? + | rewrite def h(n: Int) = ??? | } """.stripMargin) @@ -129,6 +130,7 @@ class ModifiersParsingTest { assert(source.field("c").modifiers == List(Mod.Final())) assert(source.field("f").modifiers == List(Mod.Abstract(), Mod.Override())) assert(source.field("g").modifiers == List(Mod.Transparent())) + assert(source.field("h").modifiers == List(Mod.Rewrite())) } @Test def paramDef = { diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index 8678a6b2a94b..e2e97e8c9a8f 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -993,7 +993,7 @@ class ErrorMessagesTests extends ErrorMessagesTest { |} | |class B extends A { - | transparent def bar(): Unit = super.foo() + | rewrite def bar(): Unit = super.foo() |} """.stripMargin } @@ -1001,7 +1001,7 @@ class ErrorMessagesTests extends ErrorMessagesTest { implicit val ctx: Context = ictx assertMessageCount(1, messages) val err :: Nil = messages - val SuperCallsNotAllowedTransparent(symbol) = err + val SuperCallsNotAllowedInlineable(symbol) = err assertEquals("method bar", symbol.show) } @@ -1102,7 +1102,7 @@ class ErrorMessagesTests extends ErrorMessagesTest { @Test def noReturnInInline = checkMessagesAfter(FrontEnd.name) { """class BadFunction { - | transparent def usesReturn: Int = { return 42 } + | rewrite def usesReturn: Int = { return 42 } |} """.stripMargin }.expect { (ictx, messages) => @@ -1110,7 +1110,7 @@ class ErrorMessagesTests extends ErrorMessagesTest { assertMessageCount(1, messages) - val NoReturnFromTransparent(method) :: Nil = messages + val NoReturnFromInlineable(method) :: Nil = messages assertEquals("method usesReturn", method.show) } diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index b4c5d19c6b16..4dd9c3e8ff20 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -161,8 +161,9 @@ BlockResult ::= [FunArgMods] FunParams ‘=>’ Block FunParams ::= Bindings | id | ‘_’ -Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] ‘else’ Expr] If(Parens(cond), thenp, elsep?) - | ‘if’ Expr ‘then’ Expr [[semi] ‘else’ Expr] If(cond, thenp, elsep?) +Expr1 ::= [‘rewrite’] ‘if’ ‘(’ Expr ‘)’ {nl} + Expr [[semi] ‘else’ Expr] If(Parens(cond), thenp, elsep?) + | [‘rewrite’] ‘if’ Expr ‘then’ Expr [[semi] ‘else’ Expr] If(cond, thenp, elsep?) | ‘while’ ‘(’ Expr ‘)’ {nl} Expr WhileDo(Parens(cond), body) | ‘while’ Expr ‘do’ Expr WhileDo(cond, body) | ‘do’ Expr [semi] ‘while’ Expr DoWhile(expr, cond) @@ -174,7 +175,7 @@ Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] ‘else | [SimpleExpr ‘.’] id ‘=’ Expr Assign(expr, expr) | SimpleExpr1 ArgumentExprs ‘=’ Expr Assign(expr, expr) | PostfixExpr [Ascription] - | PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’ Match(expr, cases) -- point on match + | [‘rewrite’] PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’ Match(expr, cases) -- point on match | ‘implicit’ ‘match’ ‘{’ ImplicitCaseClauses ‘}’ Ascription ::= ‘:’ InfixType Typed(expr, tp) | ‘:’ Annotation {Annotation} Typed(expr, Annotated(EmptyTree, annot)*) @@ -289,6 +290,9 @@ LocalModifier ::= ‘abstract’ | ‘sealed’ | ‘implicit’ | ‘lazy’ + | ‘transparent’ + | ‘rewrite’ + | ‘erased’ AccessModifier ::= (‘private’ | ‘protected’) [AccessQualifier] AccessQualifier ::= ‘[’ (id | ‘this’) ‘]’ diff --git a/docs/docs/reference/inline.md b/docs/docs/reference/inline.md index 56400170c8a9..4e787cf7df2a 100644 --- a/docs/docs/reference/inline.md +++ b/docs/docs/reference/inline.md @@ -1,9 +1,9 @@ --- layout: doc-page -title: Transparent +title: Rewrite and Transparent --- -`transparent` is a new modifier that guarantees that a definition will be +`rewrite` is a new modifier that guarantees that a definition will be inlined at the point of use. Example: object Config { @@ -14,7 +14,7 @@ inlined at the point of use. Example: private var indent = 0 - transparent def log[T](msg: => String)(op: => T): T = + rewrite def log[T](msg: => String)(op: => T): T = if (Config.logging) { println(s"${" " * indent}start $msg") indent += 1 @@ -26,15 +26,15 @@ inlined at the point of use. Example: else op } -The `Config` object contains a definition of an `transparent` value +The `Config` object contains a definition of a `transparent` value `logging`. This means that `logging` is treated as a constant value, equivalent to its right-hand side `false`. The right-hand side of such -an transparent val must itself be a [constant +a transparent val must itself be a [constant expression](#the-definition-of-constant-expression). Used in this way, `transparent` is equivalent to Java and Scala 2's `final`. `final` meaning "constant" is still supported in Dotty, but will be phased out. -The `Logger` object contains a definition of an `transparent` method `log`. +The `Logger` object contains a definition of a `rewrite` method `log`. This method will always be inlined at the point of call. In the inlined code, an if-then-else with a constant condition will be @@ -57,29 +57,29 @@ If `Config.logging == false`, this will be rewritten to } Note that the arguments corresponding to the parameters `msg` and `op` -of the transparent method `log` are defined before the inlined body (which +of the rewrite method `log` are defined before the inlined body (which is in this case simply `op`). By-name parameters of the inlined method correspond to `def` bindings whereas by-value parameters correspond to `val` bindings. So if `log` was defined like this: - transparent def log[T](msg: String)(op: => T): T = ... + rewrite def log[T](msg: String)(op: => T): T = ... we'd get val msg = s"factorial($n)" -instead. This behavior is designed so that calling a transparent method is +instead. This behavior is designed so that calling a rewrite method is semantically the same as calling a normal method: By-value arguments are evaluated before the call whereas by-name arguments are evaluated each time they are referenced. As a consequence, it is often -preferable to make arguments of transparent methods by-name in order to +preferable to make arguments of rewrite methods by-name in order to avoid unnecessary evaluations. For instance, here is how we can define a zero-overhead `foreach` method that translates into a straightforward while loop without any indirection or overhead: - transparent def foreach(op: => Int => Unit): Unit = { + rewrite def foreach(op: => Int => Unit): Unit = { var i = from while (i < end) { op(i) @@ -91,9 +91,9 @@ By contrast, if `op` is a call-by-value parameter, it would be evaluated separat Transparent methods can be recursive. For instance, when called with a constant exponent `n`, the following method for `power` will be implemented by -straight transparent code without any loop or recursion. +straight inline code without any loop or recursion. - transparent def power(x: Double, n: Int): Double = + rewrite def power(x: Double, n: Int): Double = if (n == 0) 1.0 else if (n == 1) x else { @@ -110,19 +110,19 @@ straight transparent code without any loop or recursion. // val y3 = y2 * x // ^5 // y3 * y3 // ^10 -Parameters of transparent methods can themselves be marked `transparent`. This means +Parameters of rewrite methods can be marked `transparent`. This means that actual arguments to these parameters must be constant expressions. ### Relationship to `@inline`. Scala also defines a `@inline` annotation which is used as a hint -for the backend to inline. The `transparent` modifier is a more powerful +for the backend to inline. The `rewrite` modifier is a more powerful option: Expansion is guaranteed instead of best effort, it happens in the frontend instead of in the backend, and it also applies to recursive methods. To cross compile between both Dotty and Scalac, we introduce a new `@forceInline` -annotation which is equivalent to the new `transparent` modifier. Note that +annotation which is equivalent to the new `rewrite` modifier. Note that Scala 2 ignores the `@forceInline` annotation, so one must use both annotations to guarantee inlining for Dotty and at the same time hint inlining for Scala 2 (i.e. `@forceInline @inline`). @@ -137,5 +137,5 @@ pure numeric computations. ### Reference -For more info, see [PR #4768](https://github.com/lampepfl/dotty/pull/4768), which explains how -transparent methods can be used for typelevel programming and code specialization. +For more info, see [PR #4927](https://github.com/lampepfl/dotty/pull/4768), which explains how +rewrite methods can be used for typelevel programming and code specialization. diff --git a/docs/docs/reference/principled-meta-programming.md b/docs/docs/reference/principled-meta-programming.md index c971ecff6d22..9d245a3b3fd8 100644 --- a/docs/docs/reference/principled-meta-programming.md +++ b/docs/docs/reference/principled-meta-programming.md @@ -19,14 +19,14 @@ operations: quotation and splicing. Quotation is expressed as `'(...)` or `'{...}` for expressions (both forms are equivalent) and as `'[...]` for types. Splicing is expressed as a prefix `~` operator. -For example, the code below presents a transparent function `assert` +For example, the code below presents a rewrite function `assert` which calls at compile-time a method `assertImpl` with a boolean expression tree as argument. `assertImpl` evaluates the expression and prints it again in an error message if it evaluates to `false`. import scala.quoted._ - transparent def assert(expr: => Boolean): Unit = + rewrite def assert(expr: => Boolean): Unit = ~ assertImpl('(expr)) def assertImpl(expr: Expr[Boolean]) = @@ -220,10 +220,10 @@ is handled by the compiler, using the algorithm sketched above. ### Example Expansion -Assume an `Array` class with a transparent `map` method that forwards to a macro implementation. +Assume an `Array` class with a rewrite `map` method that forwards to a macro implementation. class Array[T] { - transparent def map[U](f: T => U): Array[U] = ~ Macros.mapImpl[T, U]('[U], '(this), '(f)) + rewrite def map[U](f: T => U): Array[U] = ~ Macros.mapImpl[T, U]('[U], '(this), '(f)) } Here’s the definition of the `mapImpl` macro, which takes quoted types and expressions to a quoted expression: @@ -307,7 +307,7 @@ Here’s an application of `map` and how it rewrites to optimized code: Seen by itself, principled meta-programming looks more like a framework for staging than one for compile-time meta programming with -macros. But combined with Dotty’s `transparent` feature it can be turned into a +macros. But combined with Dotty’s `rewrite` feature it can be turned into a compile-time system. The idea is that macro elaboration can be understood as a combination of a macro library and a quoted program. For instance, here’s the `assert` macro again together with a @@ -315,7 +315,7 @@ program that calls `assert`. object Macros { - transparent def assert(expr: => Boolean): Unit = + rewrite def assert(expr: => Boolean): Unit = ~ assertImpl('(expr)) def assertImpl(expr: Expr[Boolean]) = @@ -363,7 +363,7 @@ If `program` is treated as a quoted expression, the call to program are conceptualized as local definitions. But what about the call from `assert` to `assertImpl`? Here, we need a -tweak of the typing rules. A transparent function such as `assert` that +tweak of the typing rules. A rewrite function such as `assert` that contains a splice operation outside an enclosing quote is called a _macro_. Macros are supposed to be expanded in a subsequent phase, i.e. in a quoted context. Therefore, they are also type checked as if @@ -372,13 +372,13 @@ they were in a quoted context. For instance, the definition of the call from `assert` to `assertImpl` phase-correct, even if we assume that both definitions are local. -The second role of `transparent` in Dotty is to mark a `val` that is +The `transparent` modifier is used to declare a `val` that is either a constant or is a parameter that will be a constant when instantiated. This aspect is also important for macro expansion. To illustrate this, consider an implementation of the `power` function that makes use of a statically known exponent: - transparent def power(transparent n: Int, x: Double) = ~powerCode(n, '(x)) + rewrite def power(transparent n: Int, x: Double) = ~powerCode(n, '(x)) private def powerCode(n: Int, x: Expr[Double]): Expr[Double] = if (n == 0) '(1.0) @@ -396,7 +396,7 @@ constant, so the value of `n` will in fact be known at this point. To reflect this, we loosen the phase consistency requirements as follows: - - If `x` is a transparent value (or a transparent parameter of a transparent + - If `x` is a transparent value (or a transparent parameter of a rewrite function) of type Boolean, Byte, Short, Int, Long, Float, Double, Char or String, it can be accessed in all contexts where the number of splices minus the number of quotes between use and definition @@ -433,11 +433,11 @@ Providing an interpreter for the full language is quite difficult, and it is even more difficult to make that interpreter run efficiently. So we currently impose the following restrictions on the use of splices. - 1. A top-level splice must appear in a transparent function (turning that function + 1. A top-level splice must appear in a rewrite method (turning that method into a macro) - 2. The splice must call a previously compiled (previous to the call of the transparent definition) - static method passing quoted arguments, constant arguments or transparent arguments. + 2. The splice must call a previously compiled + method passing quoted arguments, constant arguments or transparent arguments. 3. Splices inside splices (but no intervening quotes) are not allowed. @@ -770,7 +770,7 @@ version of `power` that generates the multiplications directly if the exponent is statically known and falls back to the dynamic implementation of power otherwise. - transparent def power(n: Int, x: Double): Double = ~{ + rewrite def power(n: Int, x: Double): Double = ~{ '(n) match { case Constant(n1) => powerCode(n1, '(x)) case _ => '{ dynamicPower(n, x) } diff --git a/docs/sidebar.yml b/docs/sidebar.yml index f45373e6ad24..1da6f5358340 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -43,7 +43,7 @@ sidebar: url: docs/reference/multiversal-equality.html - title: Trait Parameters url: docs/reference/trait-parameters.html - - title: Inlining with Transparent + - title: Inlining by Rewriting url: docs/reference/inline.html - title: Meta Programming url: docs/reference/principled-meta-programming.html diff --git a/library/src/scala/annotation/internal/Body.scala b/library/src/scala/annotation/internal/Body.scala index abc5ba1b7682..334e1442a74f 100644 --- a/library/src/scala/annotation/internal/Body.scala +++ b/library/src/scala/annotation/internal/Body.scala @@ -3,6 +3,6 @@ package scala.annotation.internal import scala.annotation.Annotation /** The class associated with a `BodyAnnotation`, which indicates - * a transparent method's right hand side + * a transparent or rewrite method's right hand side */ final class Body() extends Annotation diff --git a/library/src/scala/quoted/Expr.scala b/library/src/scala/quoted/Expr.scala index 161ebe53a18a..5368d9e632b5 100644 --- a/library/src/scala/quoted/Expr.scala +++ b/library/src/scala/quoted/Expr.scala @@ -7,7 +7,7 @@ sealed abstract class Expr[+T] { /** Evaluate the contents of this expression and return the result. * - * May throw a FreeVariableError on expressions that came from a transparent macro. + * May throw a FreeVariableError on expressions that came from a macro. */ final def run(implicit toolbox: Toolbox): T = toolbox.run(this) @@ -44,7 +44,7 @@ object Exprs { /** An Expr backed by a tree. Only the current compiler trees are allowed. * - * These expressions are used for arguments of transparent macros. They contain and actual tree + * These expressions are used for arguments of macros. They contain and actual tree * from the program that is being expanded by the macro. * * May contain references to code defined outside this TastyTreeExpr instance. diff --git a/library/src/scala/quoted/QuoteError.scala b/library/src/scala/quoted/QuoteError.scala index 1b800240fc44..fbd85e51411d 100644 --- a/library/src/scala/quoted/QuoteError.scala +++ b/library/src/scala/quoted/QuoteError.scala @@ -1,6 +1,6 @@ package scala.quoted -/** Throwing this error in the implementation of a transparent macro +/** Throwing this error in the implementation of a macro * will result in a compilation error with the given message. */ class QuoteError(message: String) extends Throwable(message) diff --git a/library/src/scala/tasty/TopLevelSplice.scala b/library/src/scala/tasty/TopLevelSplice.scala index 034f211c0c2a..a425adf78a06 100644 --- a/library/src/scala/tasty/TopLevelSplice.scala +++ b/library/src/scala/tasty/TopLevelSplice.scala @@ -3,5 +3,5 @@ package scala.tasty /** Context in a top level ~ at inline site, intrinsically as `import TopLevelSplice._` */ object TopLevelSplice { /** Compiler tasty context available in a top level ~ at inline site */ - implicit def tastyContext: Tasty = throw new Exception("Not in transparent macro.") + implicit def tastyContext: Tasty = throw new Exception("Not in macro.") } diff --git a/library/src/scala/tasty/reflect/FlagSet.scala b/library/src/scala/tasty/reflect/FlagSet.scala index 4ef2f838bc44..12507694ebbc 100644 --- a/library/src/scala/tasty/reflect/FlagSet.scala +++ b/library/src/scala/tasty/reflect/FlagSet.scala @@ -11,7 +11,8 @@ trait FlagSet { def isLazy: Boolean def isOverride: Boolean def isTransparent: Boolean - def isMacro: Boolean // transparent method containing toplevel splices + def isRewrite: Boolean + def isMacro: Boolean // rewrite method containing toplevel splices def isStatic: Boolean // mapped to static Java member def isObject: Boolean // an object or its class (used for a ValDef or a ClassDef extends Modifier respectively) def isTrait: Boolean // a trait (used for a ClassDef) diff --git a/library/src/scala/tasty/util/ShowSourceCode.scala b/library/src/scala/tasty/util/ShowSourceCode.scala index 66e45970b8bc..f67d8c8bc8dc 100644 --- a/library/src/scala/tasty/util/ShowSourceCode.scala +++ b/library/src/scala/tasty/util/ShowSourceCode.scala @@ -245,6 +245,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty val flags = ddef.symbol.flags if (flags.isImplicit) this += "implicit " if (flags.isTransparent) this += "transparent " + if (flags.isRewrite) this += "rewrite " if (flags.isOverride) this += "override " printProtectedOrPrivate(ddef) diff --git a/sbt-dotty/sbt-test/source-dependencies/inline/changes/B1.scala b/sbt-dotty/sbt-test/source-dependencies/inline/changes/B1.scala index 1032753814f2..5734bc4a5299 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inline/changes/B1.scala +++ b/sbt-dotty/sbt-test/source-dependencies/inline/changes/B1.scala @@ -1,4 +1,4 @@ object B { - transparent def getInline: Int = + rewrite def getInline: Int = A.get } diff --git a/sbt-dotty/sbt-test/source-dependencies/inline/changes/B2.scala b/sbt-dotty/sbt-test/source-dependencies/inline/changes/B2.scala index f2383d73748a..8d8d8733fad0 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inline/changes/B2.scala +++ b/sbt-dotty/sbt-test/source-dependencies/inline/changes/B2.scala @@ -1,4 +1,4 @@ object B { - transparent def getInline: String = + rewrite def getInline: String = A.get.toString } diff --git a/sbt-dotty/sbt-test/source-dependencies/inline/changes/B3.scala b/sbt-dotty/sbt-test/source-dependencies/inline/changes/B3.scala index a121f6672300..df4d07305735 100644 --- a/sbt-dotty/sbt-test/source-dependencies/inline/changes/B3.scala +++ b/sbt-dotty/sbt-test/source-dependencies/inline/changes/B3.scala @@ -1,4 +1,4 @@ object B { - transparent def getInline: Int = + rewrite def getInline: Int = sys.error("This is an expected failure when running C") } diff --git a/tests/neg-with-compiler/quote-run-in-macro-1/quoted_1.scala b/tests/neg-with-compiler/quote-run-in-macro-1/quoted_1.scala index 07dfdec021a8..00fb086f18bc 100644 --- a/tests/neg-with-compiler/quote-run-in-macro-1/quoted_1.scala +++ b/tests/neg-with-compiler/quote-run-in-macro-1/quoted_1.scala @@ -3,7 +3,7 @@ import scala.quoted._ import scala.quoted.Toolbox.Default._ object Macros { - transparent def foo(i: => Int): Int = ~fooImpl('(i)) + rewrite def foo(i: => Int): Int = ~fooImpl('(i)) def fooImpl(i: Expr[Int]): Expr[Int] = { val y: Int = i.run y.toExpr diff --git a/tests/neg-with-compiler/quote-run-in-macro-2/quoted_1.scala b/tests/neg-with-compiler/quote-run-in-macro-2/quoted_1.scala index 07dfdec021a8..00fb086f18bc 100644 --- a/tests/neg-with-compiler/quote-run-in-macro-2/quoted_1.scala +++ b/tests/neg-with-compiler/quote-run-in-macro-2/quoted_1.scala @@ -3,7 +3,7 @@ import scala.quoted._ import scala.quoted.Toolbox.Default._ object Macros { - transparent def foo(i: => Int): Int = ~fooImpl('(i)) + rewrite def foo(i: => Int): Int = ~fooImpl('(i)) def fooImpl(i: Expr[Int]): Expr[Int] = { val y: Int = i.run y.toExpr diff --git a/tests/neg/i1568.scala b/tests/neg/i1568.scala index 2e3b2dae2685..b837cc6daca3 100644 --- a/tests/neg/i1568.scala +++ b/tests/neg/i1568.scala @@ -1,3 +1,3 @@ object Test { - transparent def foo(n: Int) = foo(n) // error: cyclic reference + rewrite def foo(n: Int) = foo(n) // error: cyclic reference } diff --git a/tests/neg/i1605.scala b/tests/neg/i1605.scala index 0515ec751df0..e615e3178b3d 100644 --- a/tests/neg/i1605.scala +++ b/tests/neg/i1605.scala @@ -1,5 +1,5 @@ object Test { def foo = inlineMe - transparent def inlineMe = 1 + x2233 // error + rewrite def inlineMe = 1 + x2233 // error } diff --git a/tests/neg/i2006.scala b/tests/neg/i2006.scala index 910d5fc1e2f6..ff36e89f164b 100644 --- a/tests/neg/i2006.scala +++ b/tests/neg/i2006.scala @@ -1,7 +1,7 @@ object Test { - transparent def foo(f: ImplicitFunction1[Int, Int]): AnyRef = f // error - transparent def bar(f: ImplicitFunction1[Int, Int]) = f // error + rewrite def foo(f: ImplicitFunction1[Int, Int]): AnyRef = f // error + rewrite def bar(f: ImplicitFunction1[Int, Int]) = f // error def main(args: Array[String]) = { foo(implicit thisTransaction => 43) diff --git a/tests/neg/i2421.scala b/tests/neg/i2421.scala index ff2ef194b430..c4f5d548c746 100644 --- a/tests/neg/i2421.scala +++ b/tests/neg/i2421.scala @@ -1,10 +1,10 @@ -transparent object Foo // OK (error would be detected later, in PostTyper) -transparent class Bar // error: modifier(s) `transparent' incompatible with type definition -transparent abstract class Baz // error: modifier(s) `transparent' incompatible with type definition -transparent trait Qux // error: modifier(s) `transparent' incompatible with type definition +rewrite object Foo // OK (error would be detected later, in PostTyper) +rewrite class Bar // error: modifier(s) `rewrite' incompatible with type definition +rewrite abstract class Baz // error: modifier(s) `rewrite' incompatible with type definition +rewrite trait Qux // error: modifier(s) `rewrite' incompatible with type definition object Quux { - transparent type T // error: modifier(s) `transparent' incompatible with type definition - transparent var x: Int = 42 // error: modifier(s) `transparent' incompatible with var definition - transparent lazy val y: Int = 43 // error: modifier(s) `transparent' incompatible with lazy val definition + rewrite type T // error: modifier(s) `rewrite' incompatible with type definition + rewrite var x: Int = 42 // error: modifier(s) `rewrite' incompatible with var definition + rewrite lazy val y: Int = 43 // error: modifier(s) `rewrite' incompatible with lazy val definition } diff --git a/tests/neg/i2564.scala b/tests/neg/i2564.scala index f0f63dc4b642..71f4534a9cf2 100644 --- a/tests/neg/i2564.scala +++ b/tests/neg/i2564.scala @@ -1,4 +1,4 @@ object Foo { - transparent def bar = new Bar // error + rewrite def bar = new Bar // error class Bar private[Foo]() } diff --git a/tests/neg/i2564b.scala b/tests/neg/i2564b.scala index 48e230654bb8..31010ada0993 100644 --- a/tests/neg/i2564b.scala +++ b/tests/neg/i2564b.scala @@ -1,3 +1,3 @@ class Foo private() { - transparent def foo = new Foo // error + rewrite def foo = new Foo // error } diff --git a/tests/neg/i2901.scala b/tests/neg/i2901.scala index a1f13dfa4ee1..fc017d2e2350 100644 --- a/tests/neg/i2901.scala +++ b/tests/neg/i2901.scala @@ -2,7 +2,7 @@ trait Foo { def foo = 4 } object Bar extends Foo { - transparent def bar = super[Foo].foo // error + rewrite def bar = super[Foo].foo // error } object Main { Bar.bar diff --git a/tests/neg/i4433.scala b/tests/neg/i4433.scala index 71cbf64ac00e..8af71891813c 100644 --- a/tests/neg/i4433.scala +++ b/tests/neg/i4433.scala @@ -1,6 +1,6 @@ object Foo { - transparent def g(transparent p: Int => Boolean): Boolean = ~{ // error + rewrite def g(transparent p: Int => Boolean): Boolean = ~{ // error if(p(5)) '(true) else '(false) } diff --git a/tests/neg/i4493-b.scala b/tests/neg/i4493-b.scala index e73e8e1f61a6..2214268105d9 100644 --- a/tests/neg/i4493-b.scala +++ b/tests/neg/i4493-b.scala @@ -1,6 +1,6 @@ class Index[K] object Index { - transparent def succ[K](x: K): Unit = ~{ // error + rewrite def succ[K](x: K): Unit = ~{ // error implicit val t: quoted.Type[K] = '[K] '(new Index[K]) } diff --git a/tests/neg/i4493.scala b/tests/neg/i4493.scala index 3752634ccfa5..e646d3667f8f 100644 --- a/tests/neg/i4493.scala +++ b/tests/neg/i4493.scala @@ -1,6 +1,6 @@ class Index[K] object Index { - transparent def succ[K]: Unit = ~{ // error + rewrite def succ[K]: Unit = ~{ // error implicit val t: quoted.Type[K] = '[K] '(new Index[K]) } diff --git a/tests/neg/implicitMatch-ambiguous.scala b/tests/neg/implicitMatch-ambiguous.scala index c7d485b8a29b..6a0f2e5c5c82 100644 --- a/tests/neg/implicitMatch-ambiguous.scala +++ b/tests/neg/implicitMatch-ambiguous.scala @@ -4,7 +4,7 @@ object Test { implicit val a1: A = new A implicit val a2: A = new A - transparent def f: Any = implicit match { + rewrite def f: Any = implicit match { case _: A => ??? // error: ambiguous implicits } diff --git a/tests/neg/implicitMatch-syntax.scala b/tests/neg/implicitMatch-syntax.scala index 97a47f20f66b..2c87f548c816 100644 --- a/tests/neg/implicitMatch-syntax.scala +++ b/tests/neg/implicitMatch-syntax.scala @@ -2,28 +2,28 @@ object Test { import collection.immutable.TreeSet import collection.immutable.HashSet - transparent def f1[T] = implicit implicit match { // error: repeated modifier // error: illegal modifier + rewrite def f1[T] = implicit implicit match { // error: repeated modifier // error: illegal modifier case ord: Ordered[T] => new TreeSet[T] // error: no implicit case _ => new HashSet[T] } - transparent def f2[T] = implicit erased match { // error: illegal modifier + rewrite def f2[T] = implicit erased match { // error: illegal modifier case ord: Ordered[T] => new TreeSet[T] // error: no implicit case _ => new HashSet[T] } - transparent def f3[T] = erased implicit match { // error: illegal modifier + rewrite def f3[T] = erased implicit match { // error: illegal modifier case ord: Ordered[T] => new TreeSet[T] // error: no implicit case _ => new HashSet[T] } - transparent def f4() = implicit match { + rewrite def f4() = implicit match { case Nil => ??? // error: not a legal pattern case x :: xs => ??? // error: not a legal pattern } - transparent def f5[T] = locally { implicit match { // error: implicit match cannot be used here + rewrite def f5[T] = locally { implicit match { // Ok case _ => new HashSet[T] }} diff --git a/tests/neg/inline-i1773.scala b/tests/neg/inline-i1773.scala index 9e377b23213f..94a5409e74cb 100644 --- a/tests/neg/inline-i1773.scala +++ b/tests/neg/inline-i1773.scala @@ -1,7 +1,7 @@ object Test { implicit class Foo(sc: StringContext) { object q { - transparent def unapply(arg: Any): Option[(Any, Any)] = + rewrite def unapply(arg: Any): Option[(Any, Any)] = Some((sc.parts(0), sc.parts(1))) } } diff --git a/tests/neg/inline-position/A_1.scala b/tests/neg/inline-position/A_1.scala index b031a5df69cd..524f0c4b26d1 100644 --- a/tests/neg/inline-position/A_1.scala +++ b/tests/neg/inline-position/A_1.scala @@ -1,5 +1,5 @@ object A { - transparent def f(x: => Object) = (x, x) + rewrite def f(x: => Object) = (x, x) } \ No newline at end of file diff --git a/tests/neg/inlineAccess/C_1.scala b/tests/neg/inlineAccess/C_1.scala index f35ef60c88d3..c2c0450a408f 100644 --- a/tests/neg/inlineAccess/C_1.scala +++ b/tests/neg/inlineAccess/C_1.scala @@ -1,7 +1,7 @@ package p private class D class C { - transparent def inl(): Unit = { + rewrite def inl(): Unit = { val d = new D() // error (when inlined): not accessible } } diff --git a/tests/neg/inlinevals.scala b/tests/neg/inlinevals.scala index c754991e567c..e3710667ec7a 100644 --- a/tests/neg/inlinevals.scala +++ b/tests/neg/inlinevals.scala @@ -2,16 +2,18 @@ object Test { def power0(x: Double, transparent n: Int): Double = ??? // error - transparent def power(x: Double, transparent n: Int): Double = ??? // ok + rewrite def power(x: Double, transparent n: Int): Double = ??? // ok transparent val N = 10 def X = 20 transparent transparent val twice = 30 // error: repeated modifier + rewrite transparent val twice = 30 // error: rewrite & transparent + class C(transparent x: Int, private transparent val y: Int) { // error // error transparent val foo: Int // error: abstract member may not be inline - transparent def bar: Int // error: abstract member may not be inline + rewrite def bar: Int // error: abstract member may not be inline } power(2.0, N) // ok, since it's a by-name parameter @@ -21,7 +23,7 @@ object Test { transparent val xs = List(1, 2, 3) // error: must be a constant expression - transparent def foo(x: Int) = { + rewrite def foo(x: Int) = { def f(transparent xs: List[Int]) = xs // error @@ -30,6 +32,6 @@ object Test { } - transparent def byname(transparent f: => String): Int = ??? // ok + rewrite def byname(transparent f: => String): Int = ??? // ok } diff --git a/tests/neg/power.scala b/tests/neg/power.scala index 8b17717495a1..c19b7304a45b 100644 --- a/tests/neg/power.scala +++ b/tests/neg/power.scala @@ -1,6 +1,6 @@ object Test { - transparent def power(x: Double, n: Int): Double = + rewrite def power(x: Double, n: Int): Double = if (n == 0) 1.0 else if (n == 1) x else { diff --git a/tests/neg/quote-MacroOverride.scala b/tests/neg/quote-MacroOverride.scala index 8863ba82191e..e70f48eb1ade 100644 --- a/tests/neg/quote-MacroOverride.scala +++ b/tests/neg/quote-MacroOverride.scala @@ -2,11 +2,11 @@ object Test { abstract class A { def f(): Unit - transparent def g(): Unit = () + rewrite def g(): Unit = () } object B extends A { - transparent def f() = ~('()) // error: may not override + rewrite def f() = ~('()) // error: may not override override def g() = () // error: may not override } diff --git a/tests/neg/quote-complex-top-splice.scala b/tests/neg/quote-complex-top-splice.scala index e7c5324796ac..f6cf8ec62dda 100644 --- a/tests/neg/quote-complex-top-splice.scala +++ b/tests/neg/quote-complex-top-splice.scala @@ -4,22 +4,22 @@ import scala.quoted._ object Test { - transparent def foo1: Unit = ~{ // error + rewrite def foo1: Unit = ~{ // error val x = 1 impl(x) } - transparent def foo2: Unit = ~impl({ // error + rewrite def foo2: Unit = ~impl({ // error val x = 1 x }) - transparent def foo3: Unit = ~impl({ // error + rewrite def foo3: Unit = ~impl({ // error println("foo3") 3 }) - transparent def foo4: Unit = ~{ // error + rewrite def foo4: Unit = ~{ // error println("foo4") impl(1) } diff --git a/tests/neg/quote-error-2/Macro_1.scala b/tests/neg/quote-error-2/Macro_1.scala index dd65339495db..b676d5956d02 100644 --- a/tests/neg/quote-error-2/Macro_1.scala +++ b/tests/neg/quote-error-2/Macro_1.scala @@ -1,7 +1,7 @@ import quoted._ object Macro_1 { - transparent def foo(transparent b: Boolean): Unit = ~fooImpl(b) + rewrite def foo(transparent b: Boolean): Unit = ~fooImpl(b) def fooImpl(b: Boolean): Expr[Unit] = '(println(~msg(b))) diff --git a/tests/neg/quote-error/Macro_1.scala b/tests/neg/quote-error/Macro_1.scala index aae163486c95..79c32571ea68 100644 --- a/tests/neg/quote-error/Macro_1.scala +++ b/tests/neg/quote-error/Macro_1.scala @@ -1,7 +1,7 @@ import quoted._ object Macro_1 { - transparent def foo(transparent b: Boolean): Unit = ~fooImpl(b) + rewrite def foo(transparent b: Boolean): Unit = ~fooImpl(b) def fooImpl(b: Boolean): Expr[Unit] = if (b) '(println("foo(true)")) else QuoteError("foo cannot be called with false") diff --git a/tests/neg/quote-exception/Macro_1.scala b/tests/neg/quote-exception/Macro_1.scala index 3f18f2001cc0..b72f82a20717 100644 --- a/tests/neg/quote-exception/Macro_1.scala +++ b/tests/neg/quote-exception/Macro_1.scala @@ -1,7 +1,7 @@ import quoted._ object Macro_1 { - transparent def foo(transparent b: Boolean): Unit = ~fooImpl(b) + rewrite def foo(transparent b: Boolean): Unit = ~fooImpl(b) def fooImpl(b: Boolean): Expr[Unit] = if (b) '(println("foo(true)")) else ??? diff --git a/tests/neg/quote-interpolator-core-old.scala b/tests/neg/quote-interpolator-core-old.scala index 5ad1f7a87e57..809d79c74a20 100644 --- a/tests/neg/quote-interpolator-core-old.scala +++ b/tests/neg/quote-interpolator-core-old.scala @@ -5,9 +5,9 @@ import scala.quoted._ object FInterpolation { implicit class FInterpolatorHelper(val sc: StringContext) extends AnyVal { - transparent def ff(arg1: Any): String = ~fInterpolation(sc, Seq('(arg1))) // error: Inline macro method must be a static method - transparent def ff(arg1: Any, arg2: Any): String = ~fInterpolation(sc, Seq('(arg1), '(arg2))) // error: Inline macro method must be a static method - transparent def ff(arg1: Any, arg2: Any, arg3: Any): String = ~fInterpolation(sc, Seq('(arg1), '(arg2), '(arg3))) // error: Inline macro method must be a static method + rewrite def ff(arg1: Any): String = ~fInterpolation(sc, Seq('(arg1))) // error: Inline macro method must be a static method + rewrite def ff(arg1: Any, arg2: Any): String = ~fInterpolation(sc, Seq('(arg1), '(arg2))) // error: Inline macro method must be a static method + rewrite def ff(arg1: Any, arg2: Any, arg3: Any): String = ~fInterpolation(sc, Seq('(arg1), '(arg2), '(arg3))) // error: Inline macro method must be a static method // ... } diff --git a/tests/neg/quote-macro-2-splices.scala b/tests/neg/quote-macro-2-splices.scala index fac2cfc64dab..59c1907f17fb 100644 --- a/tests/neg/quote-macro-2-splices.scala +++ b/tests/neg/quote-macro-2-splices.scala @@ -2,7 +2,7 @@ import scala.quoted._ object Macro { - transparent def foo(b: Boolean): Int = { // error + rewrite def foo(b: Boolean): Int = { // error if (b) ~bar(true) else ~bar(false) } diff --git a/tests/neg/quote-macro-complex-arg-0.scala b/tests/neg/quote-macro-complex-arg-0.scala index d27dc66e6843..cf0605717f04 100644 --- a/tests/neg/quote-macro-complex-arg-0.scala +++ b/tests/neg/quote-macro-complex-arg-0.scala @@ -1,6 +1,6 @@ import scala.quoted._ object Macros { - transparent def foo(transparent i: Int, dummy: Int, j: Int): Int = ~bar(i + 1, '(j)) // error: i + 1 is not a parameter or field reference + rewrite def foo(transparent i: Int, dummy: Int, j: Int): Int = ~bar(i + 1, '(j)) // error: i + 1 is not a parameter or field reference def bar(x: Int, y: Expr[Int]): Expr[Int] = '{ ~x.toExpr + ~y } } diff --git a/tests/neg/quote-macro-splice.scala b/tests/neg/quote-macro-splice.scala index 52c7042c32d0..bb19ec8c184d 100644 --- a/tests/neg/quote-macro-splice.scala +++ b/tests/neg/quote-macro-splice.scala @@ -2,22 +2,22 @@ import scala.quoted._ object Test { - transparent def foo1: Int = { // error + rewrite def foo1: Int = { // error println() ~impl(1.toExpr) } - transparent def foo2: Int = { // error + rewrite def foo2: Int = { // error ~impl(1.toExpr) ~impl(2.toExpr) } - transparent def foo3: Int = { // error + rewrite def foo3: Int = { // error val a = 1 ~impl('(a)) } - transparent def foo4: Int = { // error + rewrite def foo4: Int = { // error ~impl('(1)) 1 } diff --git a/tests/neg/quote-pcp-in-arg.scala b/tests/neg/quote-pcp-in-arg.scala index 0c31dd66328a..075586141271 100644 --- a/tests/neg/quote-pcp-in-arg.scala +++ b/tests/neg/quote-pcp-in-arg.scala @@ -1,6 +1,6 @@ import scala.quoted._ object Foo { - transparent def foo(x: Int): Int = ~bar('{ '(x); x }) // error + rewrite def foo(x: Int): Int = ~bar('{ '(x); x }) // error def bar(i: Expr[Int]): Expr[Int] = i } diff --git a/tests/neg/quote-splice-interpret-1.scala b/tests/neg/quote-splice-interpret-1.scala index 26fd25f5e299..0dd007af97c8 100644 --- a/tests/neg/quote-splice-interpret-1.scala +++ b/tests/neg/quote-splice-interpret-1.scala @@ -2,7 +2,7 @@ import scala.quoted._ object Macros { - transparent def isZero(transparent n: Int): Boolean = ~{ // error + rewrite def isZero(transparent n: Int): Boolean = ~{ // error if (n == 0) '(true) else '(false) } diff --git a/tests/neg/splice-in-top-level-splice-1.scala b/tests/neg/splice-in-top-level-splice-1.scala index 7b8c1f1ed940..c060a9819811 100644 --- a/tests/neg/splice-in-top-level-splice-1.scala +++ b/tests/neg/splice-in-top-level-splice-1.scala @@ -1,7 +1,7 @@ import scala.quoted._ object Foo { - transparent def foo(): Int = ~bar(~x) // error + rewrite def foo(): Int = ~bar(~x) // error def x: Expr[Int] = '(1) def bar(i: Int): Expr[Int] = i.toExpr } diff --git a/tests/neg/splice-in-top-level-splice-2.scala b/tests/neg/splice-in-top-level-splice-2.scala index d28e46ddf8e4..3d9606470c95 100644 --- a/tests/neg/splice-in-top-level-splice-2.scala +++ b/tests/neg/splice-in-top-level-splice-2.scala @@ -1,6 +1,6 @@ import scala.quoted._ object Foo { - transparent def foo(): Int = ~(~x) // error + rewrite def foo(): Int = ~(~x) // error def x: Expr[Expr[Int]] = '( '(1) ) } diff --git a/tests/neg/tasty-macro-assert/quoted_1.scala b/tests/neg/tasty-macro-assert/quoted_1.scala index 76f444240ffe..9a9c0ccffb3e 100644 --- a/tests/neg/tasty-macro-assert/quoted_1.scala +++ b/tests/neg/tasty-macro-assert/quoted_1.scala @@ -11,7 +11,7 @@ object Asserts { object Ops - transparent def macroAssert(cond: => Boolean): Unit = + rewrite def macroAssert(cond: => Boolean): Unit = ~impl('(cond))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl(cond: Expr[Boolean])(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/neg/transparent-override/A_1.scala b/tests/neg/transparent-override/A_1.scala index d80fc2a5462d..896e44882792 100644 --- a/tests/neg/transparent-override/A_1.scala +++ b/tests/neg/transparent-override/A_1.scala @@ -1,6 +1,6 @@ abstract class A { def f(x: Int): Int - transparent def g(x: Int): Int = x + rewrite def g(x: Int): Int = x } diff --git a/tests/neg/transparent-override/B_2.scala b/tests/neg/transparent-override/B_2.scala index c4613f91e9e8..cab68bbfc5f1 100644 --- a/tests/neg/transparent-override/B_2.scala +++ b/tests/neg/transparent-override/B_2.scala @@ -1,5 +1,5 @@ class B extends A { - transparent def f(x: Int): Int = x match { // error + rewrite def f(x: Int): Int = rewrite x match { // error case 0 => 1 case _ => x } diff --git a/tests/neg/typelevel-erased-leak.scala b/tests/neg/typelevel-erased-leak.scala index e55a47486d89..83d1ed212fe3 100644 --- a/tests/neg/typelevel-erased-leak.scala +++ b/tests/neg/typelevel-erased-leak.scala @@ -5,7 +5,7 @@ object typelevel { object Test { - transparent def test[T] = typelevel.erasedValue[T] match { // error + rewrite def test[T] = rewrite typelevel.erasedValue[T] match { // error case b: Byte => b case c: Char => "A" } diff --git a/tests/neg/typelevel-noeta.scala b/tests/neg/typelevel-noeta.scala index c25cd6971b6b..c9e524f270d8 100644 --- a/tests/neg/typelevel-noeta.scala +++ b/tests/neg/typelevel-noeta.scala @@ -2,12 +2,12 @@ object Test { def anyValue[T]: T = ??? - transparent def test(x: Int) = x match { + rewrite def test(x: Int) = rewrite x match { case _: Byte => case _: Char => } - transparent def test2() = 1 match { + rewrite def test2() = rewrite 1 match { case _: Byte => case _: Char => } diff --git a/tests/neg/typelevel-nomatch.scala b/tests/neg/typelevel-nomatch.scala index a4dc222336f5..19faf33348ef 100644 --- a/tests/neg/typelevel-nomatch.scala +++ b/tests/neg/typelevel-nomatch.scala @@ -2,7 +2,7 @@ object Test { def anyValue[T]: T = ??? - transparent def test[T] = anyValue[T] match { // error + rewrite def test[T] = rewrite anyValue[T] match { // error case _: Byte => case _: Char => } diff --git a/tests/neg/typelevel.scala b/tests/neg/typelevel.scala index 201722ded1d9..c1b7896749ee 100644 --- a/tests/neg/typelevel.scala +++ b/tests/neg/typelevel.scala @@ -2,43 +2,43 @@ trait HList { def length: Int def head: Any def tail: HList - transparent def isEmpty: Boolean = + rewrite def isEmpty: Boolean = length == 0 } // () case object HNil extends HList { - transparent def length = 0 + rewrite def length = 0 def head: Nothing = ??? def tail: Nothing = ??? } // (H, T) case class HCons[H, T <: HList](hd: H, tl: T) extends HList { - transparent def length = 1 + tl.length + rewrite def length = 1 + tl.length def head: H = this.hd def tail: T = this.tl } object Test { - transparent def concat(xs: HList, ys: HList): HList = + rewrite def concat(xs: HList, ys: HList): HList = if xs.isEmpty then ys else HCons(xs.head, concat(xs.tail, ys)) class Deco(private val as: HList) { - transparent def ++ (bs: HList) = concat(as, bs) + rewrite def ++ (bs: HList) = concat(as, bs) } class Deco0(val as: HList) { println("HI") - transparent def ++ (bs: HList) = concat(as, bs) + rewrite def ++ (bs: HList) = concat(as, bs) } class Eff { println("HI") } class Deco1(val as: HList) extends Eff { - transparent def ++ (bs: HList) = concat(as, bs) + rewrite def ++ (bs: HList) = concat(as, bs) } // Test that selections from impure classes cannot be projected away @@ -53,6 +53,6 @@ object Test { val rr1a: HCons[Int, HNil.type] = rr1 // error (type error because no inline) class Deco2(val as: HList) extends java.lang.Cloneable with java.lang.Comparable[Deco2] { - transparent def ++ (bs: HList) = concat(as, bs) + rewrite def ++ (bs: HList) = concat(as, bs) } } \ No newline at end of file diff --git a/tests/pickling/i2166.scala b/tests/pickling/i2166.scala index 9b4addb2436b..4c5e1c020f53 100644 --- a/tests/pickling/i2166.scala +++ b/tests/pickling/i2166.scala @@ -1,5 +1,5 @@ object Test { - transparent def f = "" match { case _ => false } + rewrite def f = rewrite "" match { case _ => false } def main(args: Array[String]): Unit = f } \ No newline at end of file diff --git a/tests/pickling/i3608.scala b/tests/pickling/i3608.scala index f4131874cbbc..fb246c63ef38 100644 --- a/tests/pickling/i3608.scala +++ b/tests/pickling/i3608.scala @@ -1,6 +1,6 @@ class A { class Foo { - transparent def inlineMeth: Unit = new Bar + rewrite def inlineMeth: Unit = new Bar } class Bar } diff --git a/tests/pickling/i4006.scala b/tests/pickling/i4006.scala index 485fdbe59d55..0fc43d753a9f 100644 --- a/tests/pickling/i4006.scala +++ b/tests/pickling/i4006.scala @@ -1,4 +1,4 @@ class Foo { - transparent def foo: Int = try { 1 } finally println("Hello") + rewrite def foo: Int = try { 1 } finally println("Hello") foo } diff --git a/tests/pickling/i4006b.scala b/tests/pickling/i4006b.scala index 286d8a64435a..d90950c2ca5c 100644 --- a/tests/pickling/i4006b.scala +++ b/tests/pickling/i4006b.scala @@ -1,4 +1,4 @@ class Foo { - transparent def foo: Int = try { 1 } catch { case _ => 4 } finally println("Hello") + rewrite def foo: Int = try { 1 } catch { case _ => 4 } finally println("Hello") foo } diff --git a/tests/pickling/i4006c.scala b/tests/pickling/i4006c.scala index fd1951008f20..de25404152c4 100644 --- a/tests/pickling/i4006c.scala +++ b/tests/pickling/i4006c.scala @@ -1,4 +1,4 @@ class Foo { - transparent def foo: Int = try { 1 } catch { case _ => 4 } + rewrite def foo: Int = try { 1 } catch { case _ => 4 } foo } diff --git a/tests/pickling/transparent.scala b/tests/pickling/transparent.scala index fbf01d91508e..9c8fa65826db 100644 --- a/tests/pickling/transparent.scala +++ b/tests/pickling/transparent.scala @@ -1,5 +1,5 @@ class Foo { - transparent def foo() = { + rewrite def foo() = { abstract class C[T] extends Object { def x: T println(x) diff --git a/tests/pos-with-compiler/quote-0.scala b/tests/pos-with-compiler/quote-0.scala index bdb64a6bf26c..02b1b228e776 100644 --- a/tests/pos-with-compiler/quote-0.scala +++ b/tests/pos-with-compiler/quote-0.scala @@ -4,7 +4,7 @@ import scala.quoted.Toolbox.Default._ object Macros { - transparent def assert(expr: => Boolean): Unit = + rewrite def assert(expr: => Boolean): Unit = ~assertImpl('(expr)) def assertImpl(expr: Expr[Boolean]) = @@ -12,7 +12,7 @@ object Macros { def showExpr[T](expr: Expr[T]): Expr[String] = expr.toString.toExpr - transparent def power(transparent n: Int, x: Double) = ~powerCode(n, '(x)) + rewrite def power(transparent n: Int, x: Double) = ~powerCode(n, '(x)) def powerCode(n: Int, x: Expr[Double]): Expr[Double] = if (n == 0) '(1.0) diff --git a/tests/pos-with-compiler/quote-assert/quoted_2.scala b/tests/pos-with-compiler/quote-assert/quoted_2.scala index c5525f86781b..3f94c46b11b7 100644 --- a/tests/pos-with-compiler/quote-assert/quoted_2.scala +++ b/tests/pos-with-compiler/quote-assert/quoted_2.scala @@ -4,7 +4,7 @@ import Macros._ object Test { - transparent def assert(expr: => Boolean): Unit = + rewrite def assert(expr: => Boolean): Unit = ~ assertImpl('(expr)) diff --git a/tests/pos-with-compiler/tasty/definitions.scala b/tests/pos-with-compiler/tasty/definitions.scala index 2d1bd6003f8d..b7ee82ee4ee9 100644 --- a/tests/pos-with-compiler/tasty/definitions.scala +++ b/tests/pos-with-compiler/tasty/definitions.scala @@ -236,7 +236,7 @@ object definitions { def isLazy: Boolean def isOverride: Boolean def isInline: Boolean - def isMacro: Boolean // transparent method containing toplevel splices + def isMacro: Boolean // rewrite method containing toplevel splices def isStatic: Boolean // mapped to static Java member def isObject: Boolean // an object or its class (used for a ValDef or a ClassDef extends Modifier respectively) def isTrait: Boolean // a trait (used for a ClassDef) diff --git a/tests/pos/SI-7060.scala b/tests/pos/SI-7060.scala index 7e0eab453b61..6a1d7c71227a 100644 --- a/tests/pos/SI-7060.scala +++ b/tests/pos/SI-7060.scala @@ -1,6 +1,6 @@ object Test { - transparent final def mbarray_apply_minibox(array: Any, tag: Byte): Long = + rewrite final def mbarray_apply_minibox(array: Any, tag: Byte): Long = if (tag == 0) { array.asInstanceOf[Array[Long]](0) } else diff --git a/tests/pos/depfuntype.scala b/tests/pos/depfuntype.scala index 43afbb0c434b..409c44aa8d24 100644 --- a/tests/pos/depfuntype.scala +++ b/tests/pos/depfuntype.scala @@ -19,7 +19,7 @@ object Test { // Reproduced here because the one from DottyPredef is lacking a Tasty tree and // therefore can't be inlined when testing non-bootstrapped. // But inlining `implicitly` is vital to make the definition of `ifun` below work. - transparent final def implicitly[T](implicit ev: T): T = ev + rewrite final def implicitly[T](implicit ev: T): T = ev type IDF = implicit (x: C) => x.M diff --git a/tests/pos/i1570.decompiled b/tests/pos/i1570.decompiled index 31051997bd70..7cc7a23c7ed5 100644 --- a/tests/pos/i1570.decompiled +++ b/tests/pos/i1570.decompiled @@ -1,5 +1,5 @@ /** Decompiled from out/posTestFromTasty/pos/i1570/Test.class */ object Test { - transparent def foo(n: scala.Int): scala.Int = Test.bar(n) - transparent def bar(n: scala.Int): scala.Int = n + rewrite def foo(n: scala.Int): scala.Int = Test.bar(n) + rewrite def bar(n: scala.Int): scala.Int = n } diff --git a/tests/pos/i1570.scala b/tests/pos/i1570.scala index c3fa7538d800..2c2b0b134b2d 100644 --- a/tests/pos/i1570.scala +++ b/tests/pos/i1570.scala @@ -1,4 +1,4 @@ object Test { - transparent def foo(transparent n: Int) = bar(n) - transparent def bar(transparent n: Int) = n + rewrite def foo(transparent n: Int) = bar(n) + rewrite def bar(transparent n: Int) = n } diff --git a/tests/pos/i1891.scala b/tests/pos/i1891.scala index d994e6d4118e..129a57035d11 100644 --- a/tests/pos/i1891.scala +++ b/tests/pos/i1891.scala @@ -4,7 +4,7 @@ object Test { type T2[A, B] = CC2[A, B] class ArrowAssoc[A](val self: A) { - transparent def f[B](y: B): CC2[A, B] = new CC2(self, y) + rewrite def f[B](y: B): CC2[A, B] = new CC2(self, y) } def foo = (new ArrowAssoc(1)).f(2) diff --git a/tests/pos/i1990.scala b/tests/pos/i1990.scala index 432b17f253fe..7273e28302cc 100644 --- a/tests/pos/i1990.scala +++ b/tests/pos/i1990.scala @@ -1,6 +1,6 @@ class A { class Foo { - transparent def inlineMeth: Unit = { + rewrite def inlineMeth: Unit = { new Bar } } diff --git a/tests/pos/i1990a.scala b/tests/pos/i1990a.scala index d01cd8460019..f26ee5cdce6b 100644 --- a/tests/pos/i1990a.scala +++ b/tests/pos/i1990a.scala @@ -1,6 +1,6 @@ class A { self => class Foo { - transparent def inlineMeth: Unit = { + rewrite def inlineMeth: Unit = { println(self) } } diff --git a/tests/pos/i2056.scala b/tests/pos/i2056.scala index 7a19810ec46b..64abb08de6fb 100644 --- a/tests/pos/i2056.scala +++ b/tests/pos/i2056.scala @@ -1,5 +1,5 @@ object Test { - transparent def crash() = { + rewrite def crash() = { try { println("hi") } catch { diff --git a/tests/pos/i2980.scala b/tests/pos/i2980.scala index 7512c35bfed1..e118a2598f2c 100644 --- a/tests/pos/i2980.scala +++ b/tests/pos/i2980.scala @@ -3,7 +3,7 @@ trait Foo { } object Foo { - transparent def foo: Foo = new Foo { + rewrite def foo: Foo = new Foo { def apply[~>[_,_]](x: Int ~> Int): Int ~> Int = x } diff --git a/tests/pos/i3050.scala b/tests/pos/i3050.scala index 6469bf3dad42..03490380b2fd 100644 --- a/tests/pos/i3050.scala +++ b/tests/pos/i3050.scala @@ -3,17 +3,17 @@ object Test { case object None extends Option[Nothing] case class Some[+T](x: T) extends Option[T] - transparent def openImpl(): Int = + rewrite def openImpl(): Int = Some(42) match { case Some(i) => i } def open() = openImpl() - transparent def openImpl1(): Int = + rewrite def openImpl1(): Int = new Some(42) match { case Some(i) => i } def open1() = openImpl1() - transparent def openImpl2(): Int = + rewrite def openImpl2(): Int = None match { case None => 42 } def open2(): Int = openImpl2() @@ -21,17 +21,17 @@ object Test { // Same as Test, with Scala2 case classes object Test2 { - transparent def openImpl(): Int = + rewrite def openImpl(): Int = Some(42) match { case Some(i) => i } def open() = openImpl() - transparent def openImpl1(): Int = + rewrite def openImpl1(): Int = new Some(42) match { case Some(i) => i } def open1() = openImpl1() - transparent def openImpl2(): Int = + rewrite def openImpl2(): Int = None match { case None => 42 } def open2(): Int = openImpl2() diff --git a/tests/pos/i3082.scala b/tests/pos/i3082.scala index 3b4b285bc2fb..143e61a9bf9f 100644 --- a/tests/pos/i3082.scala +++ b/tests/pos/i3082.scala @@ -1,6 +1,6 @@ object Test { private def foo(arg1: Int): Int = { - transparent def bar: Int = foo(0) + rewrite def bar: Int = foo(0) if (arg1 == 0) 0 else bar } assert(foo(11) == 0) diff --git a/tests/pos/i3129.scala b/tests/pos/i3129.scala index 85b248b52428..8bd52bf351ea 100644 --- a/tests/pos/i3129.scala +++ b/tests/pos/i3129.scala @@ -1,5 +1,5 @@ object companions2 { - transparent def foo() = { + rewrite def foo() = { class C { println(C.p) } @@ -15,7 +15,7 @@ class A { class B { private def getAncestor2(p: A): A = p - private transparent def getAncestor(p: A): A = { + private rewrite def getAncestor(p: A): A = { p.b.getAncestor(p) } } diff --git a/tests/pos/i3130a.scala b/tests/pos/i3130a.scala index c3e2b0115e50..9b56ca9776ac 100644 --- a/tests/pos/i3130a.scala +++ b/tests/pos/i3130a.scala @@ -5,6 +5,6 @@ object O { class D(val x: Int) { class DD() object DD { - transparent def apply() = x // new DD() + rewrite def apply() = x // new DD() } } diff --git a/tests/pos/i3130b.scala b/tests/pos/i3130b.scala index ac2d63766eec..e5d448793693 100644 --- a/tests/pos/i3130b.scala +++ b/tests/pos/i3130b.scala @@ -1,6 +1,6 @@ class Outer { trait F { def f(): Int } - transparent def inner: F = { + rewrite def inner: F = { class InnerClass(x: Int) extends F { def this() = this(3) def f() = x diff --git a/tests/pos/i3130c.scala b/tests/pos/i3130c.scala index 70610330588a..4467a8e2dc1e 100644 --- a/tests/pos/i3130c.scala +++ b/tests/pos/i3130c.scala @@ -6,7 +6,7 @@ trait Test { trait TreeBuilder { val global: Global - transparent def set(tree: global.Tree) = {} + rewrite def set(tree: global.Tree) = {} } val nsc: Global diff --git a/tests/pos/i3130d.scala b/tests/pos/i3130d.scala index 760955167dfb..1c1490512a5b 100644 --- a/tests/pos/i3130d.scala +++ b/tests/pos/i3130d.scala @@ -1,6 +1,6 @@ class D(x: Int) { class DD { - transparent def apply() = new DD() + rewrite def apply() = new DD() } val inner = new DD } diff --git a/tests/pos/i3488.scala b/tests/pos/i3488.scala index 2f4c1a3a3589..7357ce01abbf 100644 --- a/tests/pos/i3488.scala +++ b/tests/pos/i3488.scala @@ -4,7 +4,7 @@ class Sett[A] { def incl(elem: A): Sett[A] = ??? - transparent final def + (elem: A): Sett[A] = incl(elem) + rewrite final def + (elem: A): Sett[A] = incl(elem) } object Sett { diff --git a/tests/pos/i3608.scala b/tests/pos/i3608.scala index f4131874cbbc..fb246c63ef38 100644 --- a/tests/pos/i3608.scala +++ b/tests/pos/i3608.scala @@ -1,6 +1,6 @@ class A { class Foo { - transparent def inlineMeth: Unit = new Bar + rewrite def inlineMeth: Unit = new Bar } class Bar } diff --git a/tests/pos/i3633.scala b/tests/pos/i3633.scala index 0eb758310026..f712e07b9885 100644 --- a/tests/pos/i3633.scala +++ b/tests/pos/i3633.scala @@ -1,4 +1,4 @@ class Test { - transparent def foo = 1 + rewrite def foo = 1 def test = -foo } diff --git a/tests/pos/i3636.scala b/tests/pos/i3636.scala index 768ff7a7ddec..0cfb0561bcc7 100644 --- a/tests/pos/i3636.scala +++ b/tests/pos/i3636.scala @@ -1,11 +1,11 @@ trait Iterable[A] { def concat[B >: A](that: Iterable[B]): Iterable[B] = ??? - transparent final def ++ [B >: A](that: Iterable[B]): Iterable[B] = concat(that) + rewrite final def ++ [B >: A](that: Iterable[B]): Iterable[B] = concat(that) } class BitSet extends Iterable[Int] { def concat(that: Iterable[Int]): BitSet = ??? - transparent final def ++ (that: Iterable[Int]): BitSet = concat(that) + rewrite final def ++ (that: Iterable[Int]): BitSet = concat(that) } class Test { diff --git a/tests/pos/i3873.scala b/tests/pos/i3873.scala index ea9aa41c8ec6..d03560b4a58d 100644 --- a/tests/pos/i3873.scala +++ b/tests/pos/i3873.scala @@ -1,5 +1,5 @@ object Test { - transparent def sum2(ys: List[Int]): Unit = { + rewrite def sum2(ys: List[Int]): Unit = { ys.foldLeft(1) } val h1 = (xs: List[Int]) => sum2(xs) diff --git a/tests/pos/i3898/quoted_1.scala b/tests/pos/i3898/quoted_1.scala index f59c55ac94f5..3fde6cb8f521 100644 --- a/tests/pos/i3898/quoted_1.scala +++ b/tests/pos/i3898/quoted_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { - transparent def ff(args: Any*): String = ~impl('(args)) + rewrite def ff(args: Any*): String = ~impl('(args)) def impl(args: Expr[Seq[Any]]): Expr[String] = '("") } diff --git a/tests/pos/i3898b/quoted_1.scala b/tests/pos/i3898b/quoted_1.scala index ca551862af67..cc6e85a797bf 100644 --- a/tests/pos/i3898b/quoted_1.scala +++ b/tests/pos/i3898b/quoted_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { - transparent def ff(x: Int, transparent y: Int): String = ~impl('(x)) + rewrite def ff(x: Int, transparent y: Int): String = ~impl('(x)) def impl(x: Expr[Int]): Expr[String] = '("") } diff --git a/tests/pos/i3898c/quoted_1.scala b/tests/pos/i3898c/quoted_1.scala index ca551862af67..cc6e85a797bf 100644 --- a/tests/pos/i3898c/quoted_1.scala +++ b/tests/pos/i3898c/quoted_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { - transparent def ff(x: Int, transparent y: Int): String = ~impl('(x)) + rewrite def ff(x: Int, transparent y: Int): String = ~impl('(x)) def impl(x: Expr[Int]): Expr[String] = '("") } diff --git a/tests/pos/i3912-1/i3912_1.scala b/tests/pos/i3912-1/i3912_1.scala index 63c9565dacd7..cfaabcef638f 100644 --- a/tests/pos/i3912-1/i3912_1.scala +++ b/tests/pos/i3912-1/i3912_1.scala @@ -1,7 +1,7 @@ import scala.quoted._ object Macros { - transparent def foo(): Int = { ~impl() } + rewrite def foo(): Int = { ~impl() } def impl(): Expr[Int] = '(1) } \ No newline at end of file diff --git a/tests/pos/i3912-2/i3912_1.scala b/tests/pos/i3912-2/i3912_1.scala index 828d161e2609..956f236be6a3 100644 --- a/tests/pos/i3912-2/i3912_1.scala +++ b/tests/pos/i3912-2/i3912_1.scala @@ -1,7 +1,7 @@ import scala.quoted._ object Macros { - transparent def foo2(): Unit = ~impl() + rewrite def foo2(): Unit = ~impl() def impl(): Expr[Int] = '(1) } \ No newline at end of file diff --git a/tests/pos/i3912-3/i3912_1.scala b/tests/pos/i3912-3/i3912_1.scala index 3d0a78eb491e..9bae237b0658 100644 --- a/tests/pos/i3912-3/i3912_1.scala +++ b/tests/pos/i3912-3/i3912_1.scala @@ -1,7 +1,7 @@ import scala.quoted._ object Macros { - transparent def foo3(): Int = { + rewrite def foo3(): Int = { { ~impl() } diff --git a/tests/pos/i4023/Macro_1.scala b/tests/pos/i4023/Macro_1.scala index a68cf3467f05..2e038e31c1c1 100644 --- a/tests/pos/i4023/Macro_1.scala +++ b/tests/pos/i4023/Macro_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { - transparent def ff[T: Type](x: T): T = ~impl('(x)) + rewrite def ff[T: Type](x: T): T = ~impl('(x)) def impl[T](x: Expr[T]): Expr[T] = x } diff --git a/tests/pos/i4023b/Macro_1.scala b/tests/pos/i4023b/Macro_1.scala index e1d1559c649a..3e12d2904527 100644 --- a/tests/pos/i4023b/Macro_1.scala +++ b/tests/pos/i4023b/Macro_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { - transparent def ff[T](implicit t: Type[T]): Int = ~impl[T] + rewrite def ff[T](implicit t: Type[T]): Int = ~impl[T] def impl[T]: Expr[Int] = '(4) } diff --git a/tests/pos/i4023c/Macro_1.scala b/tests/pos/i4023c/Macro_1.scala index 1f5521b974c7..f07bbdf28d77 100644 --- a/tests/pos/i4023c/Macro_1.scala +++ b/tests/pos/i4023c/Macro_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { - transparent def ff[T](x: T): T = ~impl('(x), '[T]) + rewrite def ff[T](x: T): T = ~impl('(x), '[T]) def impl[T](x: Expr[T], t: Type[T]): Expr[T] = '{ (~x): ~t } } diff --git a/tests/pos/i4322.scala b/tests/pos/i4322.scala index dcddc7da1e84..4a176fdf1b95 100644 --- a/tests/pos/i4322.scala +++ b/tests/pos/i4322.scala @@ -3,12 +3,12 @@ object Foo { private def x(n: String): Int = n.toInt - transparent def foo: Int = x + x + x("22") + rewrite def foo: Int = x + x + x("22") - transparent def bar = { + rewrite def bar = { x += 1 x += 1 } - transparent def baz = { x += x("11") } + rewrite def baz = { x += x("11") } } diff --git a/tests/pos/i4493-c.scala b/tests/pos/i4493-c.scala index 0b81937d3714..401622c0e521 100644 --- a/tests/pos/i4493-c.scala +++ b/tests/pos/i4493-c.scala @@ -1,6 +1,6 @@ class Index[K] object Index { - transparent def succ[K]: Unit = ~{ + rewrite def succ[K]: Unit = ~{ '(new Index[K]) } } diff --git a/tests/pos/i4514.scala b/tests/pos/i4514.scala index dcb17865cb3a..5f19c6c58298 100644 --- a/tests/pos/i4514.scala +++ b/tests/pos/i4514.scala @@ -1,4 +1,4 @@ object Foo { - transparent def foo[X](x: X): Unit = ~fooImpl('(x)) + rewrite def foo[X](x: X): Unit = ~fooImpl('(x)) def fooImpl[X: quoted.Type](x: X): quoted.Expr[Unit] = '() } diff --git a/tests/pos/i4586.scala b/tests/pos/i4586.scala index 12ba8a8f7c94..889a777dec6d 100644 --- a/tests/pos/i4586.scala +++ b/tests/pos/i4586.scala @@ -1,4 +1,4 @@ class Foo { - transparent def foo1(f: => Int => Int): Int = f(7) + rewrite def foo1(f: => Int => Int): Int = f(7) def bar1 = foo1(x => x + 1) } diff --git a/tests/pos/i4590.scala b/tests/pos/i4590.scala index bf07b0e3a08c..dec47cf028b6 100644 --- a/tests/pos/i4590.scala +++ b/tests/pos/i4590.scala @@ -1,7 +1,7 @@ package test class ArrayDeque { - transparent def isResizeNecessary(len: Int) = len > ArrayDeque.StableSize + rewrite def isResizeNecessary(len: Int) = len > ArrayDeque.StableSize } object ArrayDeque { @@ -9,7 +9,7 @@ object ArrayDeque { } class List { - transparent def foo(x: List.Cons): Unit = { + rewrite def foo(x: List.Cons): Unit = { x.next = this } } diff --git a/tests/pos/i4773.scala b/tests/pos/i4773.scala index 9ed2e098682b..c17e8bd16b12 100644 --- a/tests/pos/i4773.scala +++ b/tests/pos/i4773.scala @@ -1,7 +1,7 @@ import scala.quoted._ object Foo { - transparent def foo2(): Unit = ~foo2Impl() + rewrite def foo2(): Unit = ~foo2Impl() def foo2Impl(): Expr[Unit] = '() - transparent def foo(): Unit = foo2() + rewrite def foo(): Unit = foo2() } diff --git a/tests/pos/i4846.scala b/tests/pos/i4846.scala index c19ea709ebbf..e4e256490ce5 100644 --- a/tests/pos/i4846.scala +++ b/tests/pos/i4846.scala @@ -1,6 +1,6 @@ import scala.quoted._ object Test { - transparent def foo(transparent x: Int): Int = ~fooImpl(x, '(x), '( '(x) ), '( '( '(x) ) )) + rewrite def foo(transparent x: Int): Int = ~fooImpl(x, '(x), '( '(x) ), '( '( '(x) ) )) def fooImpl(a: Int, b: Expr[Int], c: Expr[Expr[Int]], d: Expr[Expr[Expr[Int]]]): Expr[Int] = ??? } diff --git a/tests/pos/inline-access-levels/A_1.scala b/tests/pos/inline-access-levels/A_1.scala index 6bbb3a44d173..7ec5fdba783d 100644 --- a/tests/pos/inline-access-levels/A_1.scala +++ b/tests/pos/inline-access-levels/A_1.scala @@ -4,7 +4,7 @@ object A { private var x: Int = 0 - transparent def actOnX(f: Int => Int) = { + rewrite def actOnX(f: Int => Int) = { x = f(x) } } diff --git a/tests/pos/inline-apply.scala b/tests/pos/inline-apply.scala index 66a5c392512f..6e3f3b76591d 100644 --- a/tests/pos/inline-apply.scala +++ b/tests/pos/inline-apply.scala @@ -3,7 +3,7 @@ class Context object Test { def transform()(implicit ctx: Context) = { - transparent def withLocalOwner[T](op: Context => T) = op(ctx) + rewrite def withLocalOwner[T](op: Context => T) = op(ctx) withLocalOwner { implicit ctx => } diff --git a/tests/pos/inline-i2570.scala b/tests/pos/inline-i2570.scala index e520878c356c..2bc5938f761b 100644 --- a/tests/pos/inline-i2570.scala +++ b/tests/pos/inline-i2570.scala @@ -1,4 +1,4 @@ object Test { - transparent def sum2(ys: List[Int]): Int = (1 /: ys)(_ + _) + rewrite def sum2(ys: List[Int]): Int = (1 /: ys)(_ + _) val h1 = (xs: List[Int]) => sum2(xs) } diff --git a/tests/pos/inline-named-typeargs.scala b/tests/pos/inline-named-typeargs.scala index 3d09f1af8c22..0b8c4891d7b8 100644 --- a/tests/pos/inline-named-typeargs.scala +++ b/tests/pos/inline-named-typeargs.scala @@ -1,5 +1,5 @@ object t1 { - transparent def construct[Elem, Coll[_]](xs: List[Elem]): Coll[Elem] = ??? + rewrite def construct[Elem, Coll[_]](xs: List[Elem]): Coll[Elem] = ??? val xs3 = construct[Coll = List](List(1, 2, 3)) } diff --git a/tests/pos/inline-t2425.scala b/tests/pos/inline-t2425.scala index 09f4e218ed48..ff3929bc5e3f 100644 --- a/tests/pos/inline-t2425.scala +++ b/tests/pos/inline-t2425.scala @@ -1,5 +1,5 @@ object Test extends App { - transparent def foo[T](bar: T) = { + rewrite def foo[T](bar: T) = { bar match { case _ => () } diff --git a/tests/pos/inlineAccesses.scala b/tests/pos/inlineAccesses.scala index 53fbd5aa49b8..e16da85b3e26 100644 --- a/tests/pos/inlineAccesses.scala +++ b/tests/pos/inlineAccesses.scala @@ -6,12 +6,12 @@ class C { private type T = C private var x = 0 - transparent def f = { + rewrite def f = { x += 1 x = x + 1 x } - transparent def dup = new T + rewrite def dup = new T } object Test { diff --git a/tests/pos/inliner2.scala b/tests/pos/inliner2.scala index 4d2acdc64d3e..d7d958056f37 100644 --- a/tests/pos/inliner2.scala +++ b/tests/pos/inliner2.scala @@ -3,7 +3,7 @@ // for inlining due to the bug. class A { private var debug = false - transparent private def ifelse[T](cond: => Boolean, ifPart: => T, elsePart: => T): T = + rewrite private def ifelse[T](cond: => Boolean, ifPart: => T, elsePart: => T): T = if (cond) ifPart else elsePart final def bob1() = ifelse(debug, 1, 2) diff --git a/tests/pos/macro-with-array/Macro_1.scala b/tests/pos/macro-with-array/Macro_1.scala index de42b4bb6726..3876d48674c4 100644 --- a/tests/pos/macro-with-array/Macro_1.scala +++ b/tests/pos/macro-with-array/Macro_1.scala @@ -1,29 +1,29 @@ object Macro { - transparent def foo0(i: Int): Unit = ~{ '() } - transparent def foo1(arr: Array[Boolean]): Unit = ~{ '() } - transparent def foo2(arr: Array[Byte]): Unit = ~{ '() } - transparent def foo3(arr: Array[Short]): Unit = ~{ '() } - transparent def foo4(arr: Array[Int]): Unit = ~{ '() } - transparent def foo5(arr: Array[Long]): Unit = ~{ '() } - transparent def foo6(arr: Array[Float]): Unit = ~{ '() } - transparent def foo7(arr: Array[Double]): Unit = ~{ '() } - transparent def foo8(arr: Array[Char]): Unit = ~{ '() } - transparent def foo9(arr: Array[Object]): Unit = ~{ '() } - transparent def foo10(arr: Array[String]): Unit = ~{ '() } - transparent def foo11[T](arr: Array[T]): Unit = ~{ '() } - transparent def foo12(arr: Array[Array[Int]]): Unit = ~{ '() } - transparent def foo13(arr: Array[Array[String]]): Unit = ~{ '() } - transparent def foo14(arr: Array[Array[Array[Int]]]): Unit = ~{ '() } - transparent def foo15(arr: Array[Any]): Unit = ~{ '() } - transparent def foo16(arr: Array[AnyVal]): Unit = ~{ '() } - transparent def foo17(arr: Array[AnyRef]): Unit = ~{ '() } - transparent def foo18(arr: Array[Foo]): Unit = ~{ '() } - transparent def foo19(arr: Array[Macro.type]): Unit = ~{ '() } - transparent def foo20(arr: Array[Bar]): Unit = ~{ '() } - transparent def foo21(arr: Array[Baz.type]): Unit = ~{ '() } - transparent def foo22(arr: Array[Foo#A]): Unit = ~{ '() } + rewrite def foo0(i: Int): Unit = ~{ '() } + rewrite def foo1(arr: Array[Boolean]): Unit = ~{ '() } + rewrite def foo2(arr: Array[Byte]): Unit = ~{ '() } + rewrite def foo3(arr: Array[Short]): Unit = ~{ '() } + rewrite def foo4(arr: Array[Int]): Unit = ~{ '() } + rewrite def foo5(arr: Array[Long]): Unit = ~{ '() } + rewrite def foo6(arr: Array[Float]): Unit = ~{ '() } + rewrite def foo7(arr: Array[Double]): Unit = ~{ '() } + rewrite def foo8(arr: Array[Char]): Unit = ~{ '() } + rewrite def foo9(arr: Array[Object]): Unit = ~{ '() } + rewrite def foo10(arr: Array[String]): Unit = ~{ '() } + rewrite def foo11[T](arr: Array[T]): Unit = ~{ '() } + rewrite def foo12(arr: Array[Array[Int]]): Unit = ~{ '() } + rewrite def foo13(arr: Array[Array[String]]): Unit = ~{ '() } + rewrite def foo14(arr: Array[Array[Array[Int]]]): Unit = ~{ '() } + rewrite def foo15(arr: Array[Any]): Unit = ~{ '() } + rewrite def foo16(arr: Array[AnyVal]): Unit = ~{ '() } + rewrite def foo17(arr: Array[AnyRef]): Unit = ~{ '() } + rewrite def foo18(arr: Array[Foo]): Unit = ~{ '() } + rewrite def foo19(arr: Array[Macro.type]): Unit = ~{ '() } + rewrite def foo20(arr: Array[Bar]): Unit = ~{ '() } + rewrite def foo21(arr: Array[Baz.type]): Unit = ~{ '() } + rewrite def foo22(arr: Array[Foo#A]): Unit = ~{ '() } class Bar object Baz diff --git a/tests/pos/macro-with-type/Macro_1.scala b/tests/pos/macro-with-type/Macro_1.scala index f75c48270604..32f667b39d8b 100644 --- a/tests/pos/macro-with-type/Macro_1.scala +++ b/tests/pos/macro-with-type/Macro_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macro { - transparent def ff: Unit = ~impl('[Int]) + rewrite def ff: Unit = ~impl('[Int]) def impl(t: Type[Int]): Expr[Unit] = '() } diff --git a/tests/pos/pos_valueclasses/t5853.scala b/tests/pos/pos_valueclasses/t5853.scala index 8edc734a4754..07354ee29e3f 100644 --- a/tests/pos/pos_valueclasses/t5853.scala +++ b/tests/pos/pos_valueclasses/t5853.scala @@ -41,7 +41,7 @@ class Foo2 { object Arrow { implicit final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal { - transparent def ->>[B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) + rewrite def ->>[B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) } def foo = 1 ->> 2 @@ -50,7 +50,7 @@ object Arrow { object SpecArrow { implicit final class ArrowAssoc[A](val __leftOfArrow: A) extends AnyVal { - transparent def ->> [@specialized(Int) B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) + rewrite def ->> [@specialized(Int) B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) } def foo = 1 ->> 2 diff --git a/tests/pos/power-macro/Macro_1.scala b/tests/pos/power-macro/Macro_1.scala index 1881dcb467cc..6b75626b1b1f 100644 --- a/tests/pos/power-macro/Macro_1.scala +++ b/tests/pos/power-macro/Macro_1.scala @@ -3,7 +3,7 @@ import scala.quoted.Expr object PowerMacro { - transparent def power(transparent n: Long, x: Double) = ~powerCode(n, '(x)) + rewrite def power(transparent n: Long, x: Double) = ~powerCode(n, '(x)) def powerCode(n: Long, x: Expr[Double]): Expr[Double] = if (n == 0) '(1.0) diff --git a/tests/pos/quote-lift-inline-params-b.scala b/tests/pos/quote-lift-inline-params-b.scala index d1c90d375183..bb0cd85f6d99 100644 --- a/tests/pos/quote-lift-inline-params-b.scala +++ b/tests/pos/quote-lift-inline-params-b.scala @@ -1,7 +1,7 @@ import scala.quoted.Expr import quoted.Liftable.{IntIsLiftable => _} object Macro { - transparent def foo(transparent n: Int): Int = ~{ + rewrite def foo(transparent n: Int): Int = ~{ '(n) } } \ No newline at end of file diff --git a/tests/pos/quote-lift-inline-params/Macro_1.scala b/tests/pos/quote-lift-inline-params/Macro_1.scala index 257adddc39e0..9564d8f29c0f 100644 --- a/tests/pos/quote-lift-inline-params/Macro_1.scala +++ b/tests/pos/quote-lift-inline-params/Macro_1.scala @@ -1,7 +1,7 @@ import scala.quoted.Expr object Macro { import quoted.Liftable.{IntIsLiftable => _} - transparent def foo(transparent n: Int): Int = ~{ + rewrite def foo(transparent n: Int): Int = ~{ '(n) } } \ No newline at end of file diff --git a/tests/pos/quote-nested-object/Macro_1.scala b/tests/pos/quote-nested-object/Macro_1.scala index cda302351c2b..859ae96b17ad 100644 --- a/tests/pos/quote-nested-object/Macro_1.scala +++ b/tests/pos/quote-nested-object/Macro_1.scala @@ -6,7 +6,7 @@ object Macro { object Implementation { - transparent def plus(transparent n: Int, m: Int): Int = ~plus(n, '(m)) + rewrite def plus(transparent n: Int, m: Int): Int = ~plus(n, '(m)) def plus(n: Int, m: Expr[Int]): Expr[Int] = if (n == 0) m @@ -14,7 +14,7 @@ object Macro { object Implementation2 { - transparent def plus(transparent n: Int, m: Int): Int = ~plus(n, '(m)) + rewrite def plus(transparent n: Int, m: Int): Int = ~plus(n, '(m)) def plus(n: Int, m: Expr[Int]): Expr[Int] = if (n == 0) m diff --git a/tests/pos/quote-non-static-macro.scala b/tests/pos/quote-non-static-macro.scala index 00df6d9b1c3a..4aea5f85406d 100644 --- a/tests/pos/quote-non-static-macro.scala +++ b/tests/pos/quote-non-static-macro.scala @@ -1,18 +1,18 @@ import scala.quoted._ class Foo { - transparent def foo: Unit = ~Foo.impl + rewrite def foo: Unit = ~Foo.impl object Bar { - transparent def foo: Unit = ~Foo.impl + rewrite def foo: Unit = ~Foo.impl } } object Foo { class Baz { - transparent def foo: Unit = ~impl + rewrite def foo: Unit = ~impl } object Quox { - transparent def foo: Unit = ~Foo.impl + rewrite def foo: Unit = ~Foo.impl } def impl: Expr[Unit] = '() } diff --git a/tests/pos/rbtree.scala b/tests/pos/rbtree.scala index baba24a72eb7..a3c92a7f000b 100644 --- a/tests/pos/rbtree.scala +++ b/tests/pos/rbtree.scala @@ -457,11 +457,11 @@ object RedBlackTree { } object RedTree { - transparent def apply[A, B](key: A, value: B, left: Tree[A, B], right: Tree[A, B]) = new RedTree(key, value, left, right) + rewrite def apply[A, B](key: A, value: B, left: Tree[A, B], right: Tree[A, B]) = new RedTree(key, value, left, right) def unapply[A, B](t: RedTree[A, B]) = Some((t.key, t.value, t.left, t.right)) } object BlackTree { - transparent def apply[A, B](key: A, value: B, left: Tree[A, B], right: Tree[A, B]) = new BlackTree(key, value, left, right) + rewrite def apply[A, B](key: A, value: B, left: Tree[A, B], right: Tree[A, B]) = new BlackTree(key, value, left, right) def unapply[A, B](t: BlackTree[A, B]) = Some((t.key, t.value, t.left, t.right)) } diff --git a/tests/pos/reference/inlines.scala b/tests/pos/reference/inlines.scala index f87510d0c927..abc3855d3d9d 100644 --- a/tests/pos/reference/inlines.scala +++ b/tests/pos/reference/inlines.scala @@ -8,7 +8,7 @@ object Logger { private var indent = 0 - transparent def log[T](msg: String)(op: => T): T = + rewrite def log[T](msg: String)(op: => T): T = if (Config.logging) { println(s"${" " * indent}start $msg") indent += 1 diff --git a/tests/pos/sealed-final.scala b/tests/pos/sealed-final.scala index fc2c551c1518..7a5bd0d2039d 100644 --- a/tests/pos/sealed-final.scala +++ b/tests/pos/sealed-final.scala @@ -1,5 +1,5 @@ sealed abstract class Foo { - transparent def bar(x: Int) = x + 1 + rewrite def bar(x: Int) = x + 1 } object Foo { def mkFoo(): Foo = new Baz2 diff --git a/tests/pos/simpleInline.decompiled b/tests/pos/simpleInline.decompiled index d2a4ff00f1eb..4efaa78ffa2f 100644 --- a/tests/pos/simpleInline.decompiled +++ b/tests/pos/simpleInline.decompiled @@ -1,6 +1,6 @@ /** Decompiled from out/posTestFromTasty/pos/simpleInline/Foo.class */ class Foo() { - transparent def foo: scala.Int = 9 + rewrite def foo: scala.Int = 9 def bar: scala.Int = { // inlined 9 } diff --git a/tests/pos/simpleInline.scala b/tests/pos/simpleInline.scala index 6710461f8a0d..87cb66d707de 100644 --- a/tests/pos/simpleInline.scala +++ b/tests/pos/simpleInline.scala @@ -1,4 +1,4 @@ class Foo { - transparent def foo: Int = 9 + rewrite def foo: Int = 9 def bar: Int = foo } diff --git a/tests/pos/t6157.scala b/tests/pos/t6157.scala index 5a0a7f52fea5..672ca38d7cf4 100644 --- a/tests/pos/t6157.scala +++ b/tests/pos/t6157.scala @@ -12,7 +12,7 @@ import java.io.IOException object ErrorHandler { - transparent def defaultIfIOException[T](default: => T)(closure: => T): T = { + rewrite def defaultIfIOException[T](default: => T)(closure: => T): T = { try { closure } catch { diff --git a/tests/pos/t6562.scala b/tests/pos/t6562.scala index 2750c6f4b203..fa3b45e6a9ad 100644 --- a/tests/pos/t6562.scala +++ b/tests/pos/t6562.scala @@ -1,11 +1,11 @@ class Test { - transparent def foo: Unit = { + rewrite def foo: Unit = { def it = new {} (_: Any) => it } - transparent private def bar: Unit = { + rewrite private def bar: Unit = { def it = new {} (_: Any) => it } diff --git a/tests/pos/transparent-nested.scala b/tests/pos/transparent-nested.scala index 7c7bd10941f4..64446160f13c 100644 --- a/tests/pos/transparent-nested.scala +++ b/tests/pos/transparent-nested.scala @@ -1,14 +1,14 @@ object Test0 { def f(x: Int) = { - transparent def g(x: Int) = x match { + rewrite def g(x: Int) = rewrite x match { case 0 => 0 } g(0) transparent val Y = 0 g(Y) - transparent def h(x: Int) = x match { + rewrite def h(x: Int) = rewrite x match { case Y => 0 } h(0) @@ -20,15 +20,15 @@ object Test0 { object Test1 { - erased transparent def f(x: Int) = { - erased transparent def g(x: Int) = x match { + erased rewrite def f(x: Int) = { + erased rewrite def g(x: Int) = rewrite x match { case 0 => 0 } g(0) transparent val Y = 0 g(Y) - transparent def h(x: Int) = x match { + rewrite def h(x: Int) = rewrite x match { case Y => 0 } h(0) diff --git a/tests/pos/transparent-overload.scala b/tests/pos/transparent-overload.scala index 66189d16e6d9..cbc961a7a344 100644 --- a/tests/pos/transparent-overload.scala +++ b/tests/pos/transparent-overload.scala @@ -4,8 +4,8 @@ object Test { def f(x: String): String = x def f(x: Any): Any = x - transparent def g(x: Any) = f(x) - transparent def h(x: Any) = this.f(x) + rewrite def g(x: Any) = f(x) + rewrite def h(x: Any) = this.f(x) locally { val x1 = g(1) diff --git a/tests/pos/typelevel-vector1.scala b/tests/pos/typelevel-vector1.scala index d48dadd12331..379e52d664ca 100644 --- a/tests/pos/typelevel-vector1.scala +++ b/tests/pos/typelevel-vector1.scala @@ -13,7 +13,7 @@ object Test { import typelevel._ type Z = Z.type - transparent def add(x: Nat, y: Nat): Nat = x match { + rewrite def add(x: Nat, y: Nat): Nat = rewrite x match { case Z => y case S(x1) => S(add(x1, y)) } @@ -22,7 +22,7 @@ object Test { val y = add(x, x) val z: S[S[S[S[Z]]]] = y - transparent def concat[T, N1 <: Nat, N2 <: Nat](xs: Vec[T, N1], ys: Vec[T, N2]): Vec[T, _] = { + rewrite def concat[T, N1 <: Nat, N2 <: Nat](xs: Vec[T, N1], ys: Vec[T, N2]): Vec[T, _] = { val length = Typed(add(erasedValue[N1], erasedValue[N2])) Vec[T, length.Type](xs.elems ++ ys.elems) } diff --git a/tests/run-with-compiler/i3876-d.scala b/tests/run-with-compiler/i3876-d.scala index aee19298a597..7baa3e8209da 100644 --- a/tests/run-with-compiler/i3876-d.scala +++ b/tests/run-with-compiler/i3876-d.scala @@ -13,5 +13,5 @@ object Test { println(f4(x).show) } - transparent def inlineLambda: Int => Int = x => x + x + rewrite def inlineLambda: Int => Int = x => x + x } \ No newline at end of file diff --git a/tests/run-with-compiler/quote-impure-by-name/quoted_1.scala b/tests/run-with-compiler/quote-impure-by-name/quoted_1.scala index 76d9afc3352f..f8c976860521 100644 --- a/tests/run-with-compiler/quote-impure-by-name/quoted_1.scala +++ b/tests/run-with-compiler/quote-impure-by-name/quoted_1.scala @@ -9,7 +9,7 @@ object Index { implicit def zero[K, T]: Index[K, (K, T)] = new Index("0") - implicit transparent def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ~succImpl('(prev))('[K], '[H], '[T]) + implicit rewrite def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ~succImpl('(prev))('[K], '[H], '[T]) def succImpl[K, H, T](prev: Expr[Index[K, T]])(implicit k: Type[K], h: Type[H], t: Type[T]): Expr[Index[K, (H, T)]] = { val value = s"1 + {${prev.show}}" diff --git a/tests/run-with-compiler/quote-inline-function/quoted_1.scala b/tests/run-with-compiler/quote-inline-function/quoted_1.scala index 545309d39ede..8320539048e4 100644 --- a/tests/run-with-compiler/quote-inline-function/quoted_1.scala +++ b/tests/run-with-compiler/quote-inline-function/quoted_1.scala @@ -4,8 +4,8 @@ import scala.quoted.Toolbox.Default._ object Macros { - transparent def foreach1(start: Int, end: Int, f: Int => Unit): String = ~impl('(start), '(end), '(f)) - transparent def foreach2(start: Int, end: Int, f: => Int => Unit): String = ~impl('(start), '(end), '(f)) + rewrite def foreach1(start: Int, end: Int, f: Int => Unit): String = ~impl('(start), '(end), '(f)) + rewrite def foreach2(start: Int, end: Int, f: => Int => Unit): String = ~impl('(start), '(end), '(f)) def impl(start: Expr[Int], end: Expr[Int], f: Expr[Int => Unit]): Expr[String] = { val res = '{ diff --git a/tests/run-with-compiler/tasty-extractors-constants-2/quoted_1.scala b/tests/run-with-compiler/tasty-extractors-constants-2/quoted_1.scala index d959e26ab6c2..d8eaa2011178 100644 --- a/tests/run-with-compiler/tasty-extractors-constants-2/quoted_1.scala +++ b/tests/run-with-compiler/tasty-extractors-constants-2/quoted_1.scala @@ -6,7 +6,7 @@ import scala.tasty.util._ object Macros { - transparent def testMacro: Unit = + rewrite def testMacro: Unit = ~impl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/Tuple.scala b/tests/run/Tuple.scala index a40afd5bae29..84a540b617e0 100644 --- a/tests/run/Tuple.scala +++ b/tests/run/Tuple.scala @@ -16,32 +16,32 @@ object Tuple { type Empty = Empty.type class TupleOps(val xs: Tuple) extends AnyVal { - transparent def *: [H] (x: H): Tuple = new *:(x, xs) - transparent def size: Int = xs match { + rewrite def *: [H] (x: H): Tuple = new *:(x, xs) + rewrite def size: Int = rewrite xs match { case Empty => 0 case _ *: xs1 => xs1.size + 1 } - transparent def apply(n: Int): Any = xs match { + rewrite def apply(n: Int): Any = rewrite xs match { case x *: _ if n == 0 => x case _ *: xs1 if n > 0 => xs1.apply(n - 1) } - transparent def **: (ys: Tuple): Tuple = ys match { + rewrite def **: (ys: Tuple): Tuple = rewrite ys match { case Empty => xs case y *: ys1 => y *: (ys1 **: xs) } - transparent def head = xs match { + rewrite def head = rewrite xs match { case x *: _ => x } - transparent def tail = xs match { + rewrite def tail = rewrite xs match { case _ *: xs => xs } } val emptyArray = Array[Object]() - transparent def toObj(t: Any) = t.asInstanceOf[Object] + rewrite def toObj(t: Any) = t.asInstanceOf[Object] - transparent def toArray(t: Tuple): Array[Object] = t.size match { + rewrite def toArray(t: Tuple): Array[Object] = rewrite t.size match { case 0 => emptyArray case 1 => Array(toObj(t(0))) case 2 => Array(toObj(t(0)), toObj(t(1))) @@ -49,12 +49,12 @@ object Tuple { case 4 => Array(toObj(t(0)), toObj(t(1)), toObj(t(2)), toObj(t(3))) } - transparent implicit def tupleDeco(xs: Tuple): TupleOps = new TupleOps(xs) + rewrite implicit def tupleDeco(xs: Tuple): TupleOps = new TupleOps(xs) - transparent def apply(): Tuple = Empty - transparent def apply(x1: Any): Tuple = x1 *: Empty - transparent def apply(x1: Any, x2: Any) = x1 *: x2 *: Empty - transparent def apply(x1: Any, x2: Any, x3: Any) = x1 *: x2 *: x3 *: Empty + rewrite def apply(): Tuple = Empty + rewrite def apply(x1: Any): Tuple = x1 *: Empty + rewrite def apply(x1: Any, x2: Any) = x1 *: x2 *: Empty + rewrite def apply(x1: Any, x2: Any, x3: Any) = x1 *: x2 *: x3 *: Empty val xs0 = Tuple() val xs1 = Tuple(2) diff --git a/tests/run/TupleAbstract.scala b/tests/run/TupleAbstract.scala index 1d7b01912f53..1abd74259fcd 100644 --- a/tests/run/TupleAbstract.scala +++ b/tests/run/TupleAbstract.scala @@ -35,34 +35,34 @@ object Tuples { private final val MaxSpecialized = 7 // 22 in real life - private transparent def _empty: Tuple = erasedValue[Empty] - private transparent def _pair[H, T <: Tuple] (x: H, xs: T): Tuple = erasedValue[H *: T] + private rewrite def _empty: Tuple = erasedValue[Empty] + private rewrite def _pair[H, T <: Tuple] (x: H, xs: T): Tuple = erasedValue[H *: T] - private transparent def _size(xs: Tuple): Int = xs match { + private rewrite def _size(xs: Tuple): Int = rewrite xs match { case _: Empty => 0 case _: (_ *: xs1) => _size(erasedValue[xs1]) + 1 } - private transparent def _index(xs: Tuple, n: Int): Any = xs match { + private rewrite def _index(xs: Tuple, n: Int): Any = rewrite xs match { case _: (x *: _) if n == 0 => erasedValue[x] case _: (_ *: xs1) if n > 0 => _index(erasedValue[xs1], n - 1) } - private transparent def _head(xs: Tuple): Any = xs match { + private rewrite def _head(xs: Tuple): Any = rewrite xs match { case _: (x *: _) => erasedValue[x] } - private transparent def _tail(xs: Tuple): Tuple = xs match { + private rewrite def _tail(xs: Tuple): Tuple = rewrite xs match { case _: (_ *: xs1) => erasedValue[xs1] } - private transparent def _concat(xs: Tuple, ys: Tuple): Tuple = xs match { + private rewrite def _concat(xs: Tuple, ys: Tuple): Tuple = rewrite xs match { case _: Empty => ys case _: (x1 *: xs1) => _pair(erasedValue[x1], _concat(erasedValue[xs1], ys)) } - transparent def fromArray[T <: Tuple](xs: Array[Object]): T = - _size(erasedValue[T]) match { + rewrite def fromArray[T <: Tuple](xs: Array[Object]): T = + rewrite _size(erasedValue[T]) match { case 0 => ().asInstanceOf[T] case 1 => Tuple1(xs(0)).asInstanceOf[T] case 2 => Tuple2(xs(0), xs(1)).asInstanceOf[T] @@ -76,11 +76,11 @@ object Tuples { val emptyArray = Array[Object]() - transparent implicit def tupleDeco(xs: Tuple): TupleOps = new TupleOps(xs) + rewrite implicit def tupleDeco(xs: Tuple): TupleOps = new TupleOps(xs) class TupleOps(val xs: Tuple) extends AnyVal { - transparent def toArray: Array[Object] = _size(xs) match { + rewrite def toArray: Array[Object] = rewrite _size(xs) match { case 0 => emptyArray case 1 => @@ -108,9 +108,9 @@ object Tuples { xs.asInstanceOf[TupleXXL].elems } - transparent def *: [H] (x: H): Tuple = { + rewrite def *: [H] (x: H): Tuple = { erased val resTpe = Typed(_pair(x, xs)) - _size(xs) match { + rewrite _size(xs) match { case 0 => Tuple1(x).asInstanceOf[resTpe.Type] case 1 => @@ -136,9 +136,9 @@ object Tuples { elems1 } - transparent def head: Any = { + rewrite def head: Any = { erased val resTpe = Typed(_head(xs)) - _size(xs) match { + rewrite _size(xs) match { case 1 => val t = xs.asInstanceOf[Tuple1[_]] t._1.asInstanceOf[resTpe.Type] @@ -159,9 +159,9 @@ object Tuples { } } - transparent def tail: Any = { + rewrite def tail: Any = { erased val resTpe = Typed(_tail(xs)) - _size(xs) match { + rewrite _size(xs) match { case 1 => unit case 2 => @@ -181,30 +181,30 @@ object Tuples { } } - transparent def apply(n: Int): Any = { + rewrite def apply(n: Int): Any = { erased val resTpe = Typed(_index(xs, n)) - _size(xs) match { + rewrite _size(xs) match { case 1 => val t = xs.asInstanceOf[Tuple1[_]] - n match { + rewrite n match { case 0 => t._1.asInstanceOf[resTpe.Type] } case 2 => val t = xs.asInstanceOf[Tuple2[_, _]] - n match { + rewrite n match { case 0 => t._1.asInstanceOf[resTpe.Type] case 1 => t._2.asInstanceOf[resTpe.Type] } case 3 => val t = xs.asInstanceOf[Tuple3[_, _, _]] - n match { + rewrite n match { case 0 => t._1.asInstanceOf[resTpe.Type] case 1 => t._2.asInstanceOf[resTpe.Type] case 2 => t._3.asInstanceOf[resTpe.Type] } case 4 => val t = xs.asInstanceOf[Tuple4[_, _, _, _]] - n match { + rewrite n match { case 0 => t._1.asInstanceOf[resTpe.Type] case 1 => t._2.asInstanceOf[resTpe.Type] case 2 => t._3.asInstanceOf[resTpe.Type] @@ -217,16 +217,16 @@ object Tuples { } } - transparent def ++(ys: Tuple): Tuple = { + rewrite def ++(ys: Tuple): Tuple = { erased val resTpe = Typed(_concat(xs, ys)) - _size(xs) match { + rewrite _size(xs) match { case 0 => ys case 1 => if (_size(ys) == 0) xs else xs.head *: ys case 2 => val t = xs.asInstanceOf[Tuple2[_, _]] - _size(ys) match { + rewrite _size(ys) match { case 0 => xs case 1 => val u = ys.asInstanceOf[Tuple1[_]] @@ -239,7 +239,7 @@ object Tuples { } case 3 => val t = xs.asInstanceOf[Tuple3[_, _, _]] - _size(ys) match { + rewrite _size(ys) match { case 0 => xs case 1 => val u = ys.asInstanceOf[Tuple1[_]] @@ -253,7 +253,7 @@ object Tuples { } } - transparent def genericConcat[T <: Tuple](xs: Tuple, ys: Tuple): Tuple = + rewrite def genericConcat[T <: Tuple](xs: Tuple, ys: Tuple): Tuple = fromArray[T](xs.toArray ++ ys.toArray) } } diff --git a/tests/run/TupleImpl.scala b/tests/run/TupleImpl.scala deleted file mode 100644 index 3d382f99038b..000000000000 --- a/tests/run/TupleImpl.scala +++ /dev/null @@ -1,125 +0,0 @@ -package test { - -import annotation.showAsInfix - -object typelevel { - erased def erasedValue[T]: T = ??? - case class Typed[T](val value: T) { type Type = T } -} - -sealed trait Tuple -object Empty extends Tuple - -@showAsInfix -case class *: [+H, +T <: Tuple](hd: H, tl: T) extends Tuple - -object Tuple { - import typelevel._ - type Empty = Empty.type - - transparent def _cons[H, T <: Tuple] (x: H, xs: T): Tuple = new *:(x, xs) - - transparent def _size(xs: Tuple): Int = xs match { - case Empty => 0 - case _ *: xs1 => _size(xs1) + 1 - } - - transparent def _index(xs: Tuple, n: Int): Any = xs match { - case x *: _ if n == 0 => x - case _ *: xs1 if n > 0 => _index(xs1, n - 1) - } - - class TupleOps(val xs: Tuple) extends AnyVal { - - transparent def *: [H] (x: H): Tuple = new *:(x, xs) - transparent def size: Int = _size(xs) - - transparent def apply(n: Int): Any = { - erased val typed = Typed(_index(xs, n)) - val result = _size(xs) match { - case 1 => - n match { - case 1 => xs.asInstanceOf[Tuple1[_]].__1 - } - case 2 => - n match { - case 1 => xs.asInstanceOf[Tuple2[_, _]].__1 - case 2 => xs.asInstanceOf[Tuple2[_, _]].__2 - } - case 3 => - n match { - case 1 => xs.asInstanceOf[Tuple3[_, _, _]].__1 - case 2 => xs.asInstanceOf[Tuple3[_, _, _]].__2 - case 3 => xs.asInstanceOf[Tuple3[_, _, _]].__3 - } - case 4 => - n match { - case 1 => xs.asInstanceOf[Tuple4[_, _, _, _]].__1 - case 2 => xs.asInstanceOf[Tuple4[_, _, _, _]].__2 - case 3 => xs.asInstanceOf[Tuple4[_, _, _, _]].__3 - case 4 => xs.asInstanceOf[Tuple4[_, _, _, _]].__4 - } - } - result.asInstanceOf[typed.Type] - } - transparent def **: (ys: Tuple): Tuple = ys match { - case Empty => xs - case y *: ys1 => y *: (ys1 **: xs) - } - transparent def head = xs match { - case x *: _ => x - } - transparent def tail = xs match { - case _ *: xs => xs - } - } - - val emptyArray = Array[Object]() - - transparent def toObj(t: Any) = t.asInstanceOf[Object] - - transparent def toArray(t: Tuple): Array[Object] = t.size match { - case 0 => emptyArray - case 1 => Array(toObj(t(0))) - case 2 => Array(toObj(t(0)), toObj(t(1))) - case 3 => Array(toObj(t(0)), toObj(t(1)), toObj(t(2))) - case 4 => Array(toObj(t(0)), toObj(t(1)), toObj(t(2)), toObj(t(3))) - } - - transparent implicit def tupleDeco(xs: Tuple): TupleOps = new TupleOps(xs) - - transparent def apply(): Tuple = Empty - transparent def apply(x1: Any): Tuple = x1 *: Empty - transparent def apply(x1: Any, x2: Any) = x1 *: x2 *: Empty - transparent def apply(x1: Any, x2: Any, x3: Any) = x1 *: x2 *: x3 *: Empty - - val xs0 = Tuple() - val xs1 = Tuple(2) - val xs2 = Tuple(2, "a") - val xs3 = Tuple(true, 1, 2.0) - transparent val s0 = xs0.size; val s0c: 0 = s0 - transparent val s1 = xs1.size; val s1c: 1 = s1 - transparent val s2 = xs2.size; val s2c: 2 = s2 - transparent val s3 = xs3.size; val s3c: 3 = s3 - val e0 = xs3(0); val e0c: Boolean = e0 - val e1 = xs3(1); val e1c: Int = e1 - val e2 = xs3(2); val e2c: Double = e2 - - val conc0 = xs0 **: xs3 - val conc1 = xs3 **: xs0 - val conc2 = xs2 **: xs3 - val e3c: Int = conc0(1) - val e4c: Int = conc1(1) - val e5c: Int = conc2(0) - val e6c: Double = conc2(4) - -} - -class Tuple1[+T1](val __1: T1) extends *:(__1, Empty) -class Tuple2[+T1, +T2](val __1: T1, val __2: T2) extends *:(__1, *:(__2, Empty)) -class Tuple3[+T1, +T2, +T3](val __1: T1, val __2: T2, val __3: T3) extends *:(__1, *:(__2, *:(__3, Empty))) -class Tuple4[+T1, +T2, +T3, +T4](val __1: T1, val __2: T2, val __3: T3, val __4: T4) extends *:(__1, *:(__2, *:(__3, *:(__4, Empty)))) - -} - -object Test extends App \ No newline at end of file diff --git a/tests/run/dead-code-elimination.scala b/tests/run/dead-code-elimination.scala index 61d7eecdf717..951f299e7780 100644 --- a/tests/run/dead-code-elimination.scala +++ b/tests/run/dead-code-elimination.scala @@ -18,7 +18,7 @@ final class A { def f1 = true def f2 = true - transparent def f3 = f1 || f2 + rewrite def f3 = f1 || f2 class B { def f() = 1 to 10 foreach (_ => f3) } diff --git a/tests/run/generic-tuples.scala b/tests/run/generic-tuples.scala index 8a90a410db3d..344eda1323e7 100644 --- a/tests/run/generic-tuples.scala +++ b/tests/run/generic-tuples.scala @@ -7,7 +7,7 @@ class HNil extends Tuple case object HNil extends HNil trait Pair[H, T <: Tuple] { - erased transparent def size = ??? + erased rewrite def size = ??? } } diff --git a/tests/run/genericValueClass.scala b/tests/run/genericValueClass.scala index e2fdb79cc69b..9f387a000507 100644 --- a/tests/run/genericValueClass.scala +++ b/tests/run/genericValueClass.scala @@ -3,12 +3,12 @@ import scala.language.implicitConversions object Test extends dotty.runtime.LegacyApp { class ArrowAssocClass[A](val __leftOfArrow: A) extends AnyVal { - transparent def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) + rewrite def -> [B](y: B): Tuple2[A, B] = Tuple2(__leftOfArrow, y) def →[B](y: B): Tuple2[A, B] = ->(y) } { - transparent implicit def ArrowAssoc[A](x: A): ArrowAssocClass[A] = new ArrowAssocClass(x) + rewrite implicit def ArrowAssoc[A](x: A): ArrowAssocClass[A] = new ArrowAssocClass(x) val x = 1 -> "abc" println(x) } diff --git a/tests/run/i1569.scala b/tests/run/i1569.scala index ef64021e016e..aa159a5a2ff6 100644 --- a/tests/run/i1569.scala +++ b/tests/run/i1569.scala @@ -1,5 +1,5 @@ object Test { - transparent def foo(transparent n: => Int) = n + n + rewrite def foo(transparent n: => Int) = n + n def main(args: Array[String]): Unit = foo({ println("foo"); 42 }) } diff --git a/tests/run/i1990b.scala b/tests/run/i1990b.scala index 63d6a5fd93c0..4a44f2c6540d 100644 --- a/tests/run/i1990b.scala +++ b/tests/run/i1990b.scala @@ -1,6 +1,6 @@ trait A { self => class Foo { - transparent def inlineMeth: Unit = { + rewrite def inlineMeth: Unit = { println(self) } } diff --git a/tests/run/i2360.scala b/tests/run/i2360.scala index 584cab6f4ce6..1d05aaa63c51 100644 --- a/tests/run/i2360.scala +++ b/tests/run/i2360.scala @@ -7,7 +7,7 @@ object Test { } object Foo extends Bar { - transparent def foo: Int = bar + rewrite def foo: Int = bar } class Bar { diff --git a/tests/run/i2895a.scala b/tests/run/i2895a.scala index a37ae2ce0943..1fe2dec5e20a 100644 --- a/tests/run/i2895a.scala +++ b/tests/run/i2895a.scala @@ -3,7 +3,7 @@ trait Foo[A <: Foo[A]] { def next: A - transparent final def once: A = next + rewrite final def once: A = next def once1: A = once diff --git a/tests/run/i4431/quoted_1.scala b/tests/run/i4431/quoted_1.scala index ba4a4e743077..ae39e15dbe37 100644 --- a/tests/run/i4431/quoted_1.scala +++ b/tests/run/i4431/quoted_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macros { - transparent def h(f: => Int => String): String = ~ '(f(42)) + rewrite def h(f: => Int => String): String = ~ '(f(42)) } diff --git a/tests/run/i4455/Macro_1.scala b/tests/run/i4455/Macro_1.scala index 840f3677a5b3..cb2b0ff5bbba 100644 --- a/tests/run/i4455/Macro_1.scala +++ b/tests/run/i4455/Macro_1.scala @@ -1,8 +1,8 @@ import scala.quoted._ object Macros { - transparent def foo(transparent i: Int): Int = ~bar('(i)) + rewrite def foo(transparent i: Int): Int = ~bar('(i)) - transparent def foo2(transparent i: Int): Int = ~bar('(i + 1)) + rewrite def foo2(transparent i: Int): Int = ~bar('(i + 1)) def bar(x: Expr[Int]): Expr[Int] = x } diff --git a/tests/run/i4492/quoted_1.scala b/tests/run/i4492/quoted_1.scala index d41d07a29f4a..02b309542b73 100644 --- a/tests/run/i4492/quoted_1.scala +++ b/tests/run/i4492/quoted_1.scala @@ -2,5 +2,5 @@ trait Index object Index { - transparent def succ(prev: Index): Unit = ~{ '(println("Ok")) } + rewrite def succ(prev: Index): Unit = ~{ '(println("Ok")) } } diff --git a/tests/run/i4496b.scala b/tests/run/i4496b.scala index 82d8967e5beb..39b1c838fe28 100644 --- a/tests/run/i4496b.scala +++ b/tests/run/i4496b.scala @@ -24,7 +24,7 @@ object Test { // These accesses are also clearly well-typed def consume(v: T) = v.a - transparent def consumeInl(v: T) = v.a + rewrite def consumeInl(v: T) = v.a def verify(v: T) = { assert(consume(v) == 10) assert(consumeInl(v) == 10) @@ -58,7 +58,7 @@ object Test { def upcast2(v: Foo2): T = v def upcast3(v: Foo3): T = v def consume(v: T) = v.a - transparent def consumeInl(v: T) = v.a + rewrite def consumeInl(v: T) = v.a def verify(v: T) = { assert(consume(v) == 10) assert(consumeInl(v) == 10) @@ -88,7 +88,7 @@ object Test { type T = {val a: Int; def a_=(x: Int): Unit} def upcast3(v: Foo3): T = v def consume(v: T) = v.a - transparent def consumeInl(v: T) = v.a + rewrite def consumeInl(v: T) = v.a def verify(v: T) = { assert(consume(v) == 10) assert(consumeInl(v) == 10) diff --git a/tests/run/i4735/App_2.scala b/tests/run/i4735/App_2.scala index 3f374a321031..c531a234d6d6 100644 --- a/tests/run/i4735/App_2.scala +++ b/tests/run/i4735/App_2.scala @@ -10,5 +10,5 @@ object Test { } class Unrolled(arr: Array[Int]) extends AnyVal { - transparent def foreach(f: => Int => Unit): Unit = Macro.unrolledForeach(3, arr, f) + rewrite def foreach(f: => Int => Unit): Unit = Macro.unrolledForeach(3, arr, f) } diff --git a/tests/run/i4735/Macro_1.scala b/tests/run/i4735/Macro_1.scala index ffc609f8e3d2..14161ba92bef 100644 --- a/tests/run/i4735/Macro_1.scala +++ b/tests/run/i4735/Macro_1.scala @@ -3,7 +3,7 @@ import scala.quoted._ object Macro { - transparent def unrolledForeach(transparent unrollSize: Int, seq: Array[Int], f: => Int => Unit): Unit = // or f: Int => Unit + rewrite def unrolledForeach(transparent unrollSize: Int, seq: Array[Int], f: => Int => Unit): Unit = // or f: Int => Unit ~unrolledForeachImpl(unrollSize, '(seq), '(f)) private def unrolledForeachImpl(unrollSize: Int, seq: Expr[Array[Int]], f: Expr[Int => Unit]): Expr[Unit] = '{ diff --git a/tests/run/i4754.scala b/tests/run/i4754.scala index f2763526fa9a..393849991471 100644 --- a/tests/run/i4754.scala +++ b/tests/run/i4754.scala @@ -6,7 +6,7 @@ object Foo { class Foo { import Foo._ - transparent def foo = x + Foo.x + y + Foo.y + z + Foo.z + rewrite def foo = x + Foo.x + y + Foo.y + z + Foo.z } object Test { diff --git a/tests/run/i4803/App_2.scala b/tests/run/i4803/App_2.scala index fa550642c722..395fd0970d12 100644 --- a/tests/run/i4803/App_2.scala +++ b/tests/run/i4803/App_2.scala @@ -1,6 +1,6 @@ class Num2(x: Double) { - transparent def power(transparent n: Long) = ~PowerMacro.powerCode('(x), n) + rewrite def power(transparent n: Long) = ~PowerMacro.powerCode('(x), n) } object Test { diff --git a/tests/run/i4803/Macro_1.scala b/tests/run/i4803/Macro_1.scala index deae9bead04e..eb0eaebfbaed 100644 --- a/tests/run/i4803/Macro_1.scala +++ b/tests/run/i4803/Macro_1.scala @@ -8,5 +8,5 @@ object PowerMacro { } class Num(x: Double) { - transparent def power(transparent n: Long) = ~PowerMacro.powerCode('(x), n) + rewrite def power(transparent n: Long) = ~PowerMacro.powerCode('(x), n) } diff --git a/tests/run/i4803b/App_2.scala b/tests/run/i4803b/App_2.scala index 2e93422e36cf..36f445d98bd2 100644 --- a/tests/run/i4803b/App_2.scala +++ b/tests/run/i4803b/App_2.scala @@ -2,7 +2,7 @@ class Nums { class Num(x: Double) { - transparent def power(transparent n: Long) = ~PowerMacro.powerCode('(x), n) + rewrite def power(transparent n: Long) = ~PowerMacro.powerCode('(x), n) } } diff --git a/tests/run/i4803c/App_2.scala b/tests/run/i4803c/App_2.scala index f3b2655b8c2c..be249df0c8fd 100644 --- a/tests/run/i4803c/App_2.scala +++ b/tests/run/i4803c/App_2.scala @@ -2,7 +2,7 @@ object Test { def main(args: Array[String]): Unit = { class Num(x: Double) { - transparent def power(transparent n: Long) = ~PowerMacro.powerCode('(x), n) + rewrite def power(transparent n: Long) = ~PowerMacro.powerCode('(x), n) } val n = new Num(1.5) println(n.power(0)) @@ -10,7 +10,7 @@ object Test { println(n.power(2)) println(n.power(5)) - transparent def power(x: Double, transparent n: Long) = ~PowerMacro.powerCode('(x), n) + rewrite def power(x: Double, transparent n: Long) = ~PowerMacro.powerCode('(x), n) val x: Double = 1.5 diff --git a/tests/run/i4803d/App_2.scala b/tests/run/i4803d/App_2.scala index 293882746f0b..adb7992a8fff 100644 --- a/tests/run/i4803d/App_2.scala +++ b/tests/run/i4803d/App_2.scala @@ -10,8 +10,8 @@ object Test { println(power2(x3)) } - transparent def power2(x: Double) = { - transparent def power(x: Double, transparent n: Long) = ~PowerMacro.powerCode('(x), n) + rewrite def power2(x: Double) = { + rewrite def power(x: Double, transparent n: Long) = ~PowerMacro.powerCode('(x), n) power(x, 2) } } diff --git a/tests/run/i4803e/App_2.scala b/tests/run/i4803e/App_2.scala index 33fe9a015e03..23df2d823ab3 100644 --- a/tests/run/i4803e/App_2.scala +++ b/tests/run/i4803e/App_2.scala @@ -10,5 +10,5 @@ object Test { println(power2(x3)) } - transparent def power2(x: Double) = ~PowerMacro.power2('(x)) + rewrite def power2(x: Double) = ~PowerMacro.power2('(x)) } diff --git a/tests/run/i4803e/Macro_1.scala b/tests/run/i4803e/Macro_1.scala index 13667220618d..335e157bd2cd 100644 --- a/tests/run/i4803e/Macro_1.scala +++ b/tests/run/i4803e/Macro_1.scala @@ -2,7 +2,7 @@ import scala.quoted._ object PowerMacro { def power2(x: Expr[Double]) = '{ - transparent def power(x: Double, n: Long): Double = + rewrite def power(x: Double, n: Long): Double = if (n == 0) 1.0 else if (n % 2 == 0) { val y = x * x; power(y, n / 2) } else x * power(x, n - 1) diff --git a/tests/run/i4803f/App_2.scala b/tests/run/i4803f/App_2.scala index 33fe9a015e03..23df2d823ab3 100644 --- a/tests/run/i4803f/App_2.scala +++ b/tests/run/i4803f/App_2.scala @@ -10,5 +10,5 @@ object Test { println(power2(x3)) } - transparent def power2(x: Double) = ~PowerMacro.power2('(x)) + rewrite def power2(x: Double) = ~PowerMacro.power2('(x)) } diff --git a/tests/run/i4803f/Macro_1.scala b/tests/run/i4803f/Macro_1.scala index fe022306989c..cda076c3d671 100644 --- a/tests/run/i4803f/Macro_1.scala +++ b/tests/run/i4803f/Macro_1.scala @@ -7,7 +7,7 @@ object PowerMacro { else '{ ~x * ~powerCode(x, n - 1) } def power2(x: Expr[Double]) = '{ - transparent def power(x: Double): Double = ~powerCode('(x), 2) + rewrite def power(x: Double): Double = ~powerCode('(x), 2) power(~x) } } diff --git a/tests/run/implicitMatch.scala b/tests/run/implicitMatch.scala index c11888e8897b..d38e9f4584e1 100644 --- a/tests/run/implicitMatch.scala +++ b/tests/run/implicitMatch.scala @@ -2,7 +2,7 @@ object Test extends App { import collection.immutable.TreeSet import collection.immutable.HashSet - transparent def f[T]() = implicit match { + rewrite def f[T]() = implicit match { case ord: Ordering[T] => new TreeSet[T] case _ => new HashSet[T] } @@ -11,7 +11,7 @@ object Test extends App { class B implicit val b: B = new B - transparent def g = implicit match { + rewrite def g = implicit match { case _: A => println("A") case _: B => println("B") } diff --git a/tests/run/lst/Lst.scala b/tests/run/lst/Lst.scala index 85ef6729c081..ae158c4b4b40 100644 --- a/tests/run/lst/Lst.scala +++ b/tests/run/lst/Lst.scala @@ -15,7 +15,7 @@ import reflect.ClassTag class Lst[+T](val elems: Any) extends AnyVal { self => import Lst._ - transparent def locally[T](body: => T): T = body + rewrite def locally[T](body: => T): T = body def length: Int = elems match { case null => 0 @@ -26,7 +26,7 @@ class Lst[+T](val elems: Any) extends AnyVal { self => def isEmpty = elems == null def nonEmpty = elems != null - transparent def foreach(op: => T => Unit): Unit = locally { + rewrite def foreach(op: => T => Unit): Unit = { def sharedOp(x: T) = op(x) elems match { case null => @@ -37,7 +37,7 @@ class Lst[+T](val elems: Any) extends AnyVal { self => } } - transparent def foreachReversed(transparent op: T => Unit): Unit = locally { + rewrite def foreachReversed(transparent op: T => Unit): Unit = { def sharedOp(x: T) = op(x) elems match { case null => @@ -51,7 +51,7 @@ class Lst[+T](val elems: Any) extends AnyVal { self => /** Like `foreach`, but completely inlines `op`, at the price of generating the code twice. * Should be used only of `op` is small */ - transparent def foreachInlined(op: => T => Unit): Unit = locally { + rewrite def foreachInlined(op: => T => Unit): Unit = { elems match { case null => case elems: Arr => def elem(i: Int) = elems(i).asInstanceOf[T] @@ -102,7 +102,7 @@ class Lst[+T](val elems: Any) extends AnyVal { self => } /** `f` is pulled out, not duplicated */ - transparent def map[U](f: => T => U): Lst[U] = locally { + rewrite def map[U](f: => T => U): Lst[U] = { def op(x: T) = f(x) elems match { case null => Empty @@ -194,7 +194,7 @@ class Lst[+T](val elems: Any) extends AnyVal { self => buf.toLst } - transparent def exists(p: => T => Boolean): Boolean = locally { + rewrite def exists(p: => T => Boolean): Boolean = { def op(x: T) = p(x) elems match { case null => false @@ -207,7 +207,7 @@ class Lst[+T](val elems: Any) extends AnyVal { self => } } - transparent def forall(p: => T => Boolean): Boolean = locally { + rewrite def forall(p: => T => Boolean): Boolean = { def op(x: T) = p(x) elems match { case null => true @@ -230,7 +230,7 @@ class Lst[+T](val elems: Any) extends AnyVal { self => elem == x } - transparent def foldLeft[U](z: U)(f: => (U, T) => U) = locally { + rewrite def foldLeft[U](z: U)(f: => (U, T) => U) = { def op(x: U, y: T) = f(x, y) elems match { case null => z @@ -244,7 +244,7 @@ class Lst[+T](val elems: Any) extends AnyVal { self => } } - transparent def /: [U](z: U)(op: => (U, T) => U) = foldLeft(z)(op) + rewrite def /: [U](z: U)(op: => (U, T) => U) = foldLeft(z)(op) def reduceLeft[U >: T](op: (U, U) => U) = elems match { case null => diff --git a/tests/run/quote-and-splice/Macros_1.scala b/tests/run/quote-and-splice/Macros_1.scala index 7e35671af6eb..bb38652aa03f 100644 --- a/tests/run/quote-and-splice/Macros_1.scala +++ b/tests/run/quote-and-splice/Macros_1.scala @@ -2,22 +2,22 @@ import scala.quoted._ object Macros { - transparent def macro1 = ~ macro1Impl + rewrite def macro1 = ~ macro1Impl def macro1Impl = '(3) - transparent def macro2(transparent p: Boolean) = ~ macro2Impl(p) + rewrite def macro2(transparent p: Boolean) = ~ macro2Impl(p) def macro2Impl(p: Boolean) = if (p) '(3) else '(4) - transparent def macro3(n: Int) = ~ macro3Impl('(n)) + rewrite def macro3(n: Int) = ~ macro3Impl('(n)) def macro3Impl(p: Expr[Int]) = '{ 2 + ~p } - transparent def macro4(i: Int)(j: Int) = ~ macro4Impl('(i))('(j)) + rewrite def macro4(i: Int)(j: Int) = ~ macro4Impl('(i))('(j)) def macro4Impl(i: Expr[Int])(j: Expr[Int]) = '{ ~i + ~j } - transparent def macro5(i: Int, j: Int) = ~ macro5Impl(j = '(j), i = '(i)) + rewrite def macro5(i: Int, j: Int) = ~ macro5Impl(j = '(j), i = '(i)) def macro5Impl(i: Expr[Int], j: Expr[Int]) = '{ ~i + ~j } - transparent def power(transparent n: Int, x: Double) = ~powerCode(n, '(x)) + rewrite def power(transparent n: Int, x: Double) = ~powerCode(n, '(x)) def powerCode(n: Int, x: Expr[Double]): Expr[Double] = if (n == 0) '(1.0) diff --git a/tests/run/quote-force/quoted_1.scala b/tests/run/quote-force/quoted_1.scala index c4eff1425993..82ea1d351388 100644 --- a/tests/run/quote-force/quoted_1.scala +++ b/tests/run/quote-force/quoted_1.scala @@ -4,7 +4,7 @@ case class Location(owners: List[String]) object Location { - implicit transparent def location: Location = ~impl + implicit rewrite def location: Location = ~impl def impl: Expr[Location] = { val list = List("a", "b", "c", "d", "e", "f") diff --git a/tests/run/quote-indexed-map-by-name/quoted_1.scala b/tests/run/quote-indexed-map-by-name/quoted_1.scala index 2a7003bc90e9..97ac7e38a831 100644 --- a/tests/run/quote-indexed-map-by-name/quoted_1.scala +++ b/tests/run/quote-indexed-map-by-name/quoted_1.scala @@ -5,7 +5,7 @@ object Index { implicit def zero[K, T]: Index[K, (K, T)] = new Index(0) - implicit transparent def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ~succImpl('[K], '[H], '[T]) + implicit rewrite def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ~succImpl('[K], '[H], '[T]) def succImpl[K, H, T](implicit k: Type[K], h: Type[H], t: Type[T]): Expr[Index[K, (H, T)]] = { '(new Index(0)) diff --git a/tests/run/quote-sep-comp-2/Test_2.scala b/tests/run/quote-sep-comp-2/Test_2.scala index 6d20480ae69a..5cfb660657c3 100644 --- a/tests/run/quote-sep-comp-2/Test_2.scala +++ b/tests/run/quote-sep-comp-2/Test_2.scala @@ -1,7 +1,7 @@ object Test { - transparent def assert2(expr: => Boolean): Unit = ~Macros.assertImpl('(expr)) + rewrite def assert2(expr: => Boolean): Unit = ~Macros.assertImpl('(expr)) def main(args: Array[String]): Unit = { val x = 1 diff --git a/tests/run/quote-sep-comp/Macro_1.scala b/tests/run/quote-sep-comp/Macro_1.scala index 5f7e539c4230..8d4fe85479d9 100644 --- a/tests/run/quote-sep-comp/Macro_1.scala +++ b/tests/run/quote-sep-comp/Macro_1.scala @@ -1,5 +1,5 @@ import scala.quoted._ object Macros { - transparent def assert2(expr: => Boolean): Unit = ~ assertImpl('(expr)) + rewrite def assert2(expr: => Boolean): Unit = ~ assertImpl('(expr)) def assertImpl(expr: Expr[Boolean]) = '{ println(~expr) } } diff --git a/tests/run/quote-simple-macro/quoted_1.scala b/tests/run/quote-simple-macro/quoted_1.scala index 04a49e3289d2..1ada947c3322 100644 --- a/tests/run/quote-simple-macro/quoted_1.scala +++ b/tests/run/quote-simple-macro/quoted_1.scala @@ -1,6 +1,6 @@ import scala.quoted._ object Macros { - transparent def foo(transparent i: Int, dummy: Int, j: Int): Int = ~bar(i, '(j)) + rewrite def foo(transparent i: Int, dummy: Int, j: Int): Int = ~bar(i, '(j)) def bar(x: Int, y: Expr[Int]): Expr[Int] = '{ ~x.toExpr + ~y } } diff --git a/tests/run/quote-unrolled-foreach/quoted_1.scala b/tests/run/quote-unrolled-foreach/quoted_1.scala index f5a8b5ee5049..b039633a95e9 100644 --- a/tests/run/quote-unrolled-foreach/quoted_1.scala +++ b/tests/run/quote-unrolled-foreach/quoted_1.scala @@ -3,7 +3,7 @@ import scala.quoted._ object Macro { - transparent def unrolledForeach(transparent unrollSize: Int, seq: Array[Int])(f: => Int => Unit): Unit = // or f: Int => Unit + rewrite def unrolledForeach(transparent unrollSize: Int, seq: Array[Int])(f: => Int => Unit): Unit = // or f: Int => Unit ~unrolledForeachImpl(unrollSize, '(seq), '(f)) private def unrolledForeachImpl(unrollSize: Int, seq: Expr[Array[Int]], f: Expr[Int => Unit]): Expr[Unit] = '{ diff --git a/tests/run/reduce-projections.scala b/tests/run/reduce-projections.scala index fc4099100404..a64eda588ae3 100644 --- a/tests/run/reduce-projections.scala +++ b/tests/run/reduce-projections.scala @@ -14,7 +14,7 @@ object Test { object O3a extends D(3) object O3b extends D(3) - transparent def f(): Unit = { + rewrite def f(): Unit = { println(new C( { println(1); 1 }, { println(2); 2 }, diff --git a/tests/run/tasty-custom-show/quoted_1.scala b/tests/run/tasty-custom-show/quoted_1.scala index 7f7d63e4c928..f0b7bf75a15b 100644 --- a/tests/run/tasty-custom-show/quoted_1.scala +++ b/tests/run/tasty-custom-show/quoted_1.scala @@ -6,7 +6,7 @@ import scala.tasty.util.{TreeTraverser, Show} object Macros { - implicit transparent def printOwners[T](x: => T): Unit = + implicit rewrite def printOwners[T](x: => T): Unit = ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-definitions-1/quoted_1.scala b/tests/run/tasty-definitions-1/quoted_1.scala index 5d88c186b0f4..2dd21d8d0819 100644 --- a/tests/run/tasty-definitions-1/quoted_1.scala +++ b/tests/run/tasty-definitions-1/quoted_1.scala @@ -5,7 +5,7 @@ import scala.tasty.util.TreeTraverser object Macros { - transparent def testDefinitions(): Unit = + rewrite def testDefinitions(): Unit = ~testDefinitionsImpl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def testDefinitionsImpl(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-eval/quoted_1.scala b/tests/run/tasty-eval/quoted_1.scala index 683ed0a970bb..38b863ce7f2f 100644 --- a/tests/run/tasty-eval/quoted_1.scala +++ b/tests/run/tasty-eval/quoted_1.scala @@ -5,14 +5,14 @@ import scala.tasty.util.TreeTraverser object Macros { - implicit transparent def foo(i: Int): String = + implicit rewrite def foo(i: Int): String = ~impl('(i))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl(i: Expr[Int])(implicit tasty: Tasty): Expr[String] = { value(i).toString.toExpr } - transparent implicit def value[X](e: Expr[X])(implicit tasty: Tasty, ev: Valuable[X]): Option[X] = ev.value(e) + rewrite implicit def value[X](e: Expr[X])(implicit tasty: Tasty, ev: Valuable[X]): Option[X] = ev.value(e) trait Valuable[X] { def value(e: Expr[X])(implicit tasty: Tasty): Option[X] diff --git a/tests/run/tasty-extractors-1/quoted_1.scala b/tests/run/tasty-extractors-1/quoted_1.scala index a04873a208cb..3e5679acb852 100644 --- a/tests/run/tasty-extractors-1/quoted_1.scala +++ b/tests/run/tasty-extractors-1/quoted_1.scala @@ -4,7 +4,7 @@ import scala.tasty._ object Macros { - implicit transparent def printTree[T](x: => T): Unit = + implicit rewrite def printTree[T](x: => T): Unit = ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-extractors-2/quoted_1.scala b/tests/run/tasty-extractors-2/quoted_1.scala index b8cb7d1cccb3..d8405f10c06a 100644 --- a/tests/run/tasty-extractors-2/quoted_1.scala +++ b/tests/run/tasty-extractors-2/quoted_1.scala @@ -4,7 +4,7 @@ import scala.tasty._ object Macros { - implicit transparent def printTree[T](x: => T): Unit = + implicit rewrite def printTree[T](x: => T): Unit = ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-extractors-3/quoted_1.scala b/tests/run/tasty-extractors-3/quoted_1.scala index 741212d1f5a3..7628654ea990 100644 --- a/tests/run/tasty-extractors-3/quoted_1.scala +++ b/tests/run/tasty-extractors-3/quoted_1.scala @@ -6,7 +6,7 @@ import scala.tasty.util.TreeTraverser object Macros { - implicit transparent def printTypes[T](x: => T): Unit = + implicit rewrite def printTypes[T](x: => T): Unit = ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-extractors-constants-1/quoted_1.scala b/tests/run/tasty-extractors-constants-1/quoted_1.scala index 47ebe1df8ba6..aad9755d2de8 100644 --- a/tests/run/tasty-extractors-constants-1/quoted_1.scala +++ b/tests/run/tasty-extractors-constants-1/quoted_1.scala @@ -5,7 +5,7 @@ import scala.tasty.util._ object Macros { - implicit transparent def testMacro: Unit = + implicit rewrite def testMacro: Unit = ~impl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-extractors-owners/quoted_1.scala b/tests/run/tasty-extractors-owners/quoted_1.scala index aec06a26f886..97ab658f508f 100644 --- a/tests/run/tasty-extractors-owners/quoted_1.scala +++ b/tests/run/tasty-extractors-owners/quoted_1.scala @@ -5,7 +5,7 @@ import scala.tasty.util.TreeTraverser object Macros { - implicit transparent def printOwners[T](x: => T): Unit = + implicit rewrite def printOwners[T](x: => T): Unit = ~impl('(x))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl[T](x: Expr[T])(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-extractors-types/quoted_1.scala b/tests/run/tasty-extractors-types/quoted_1.scala index 2b5b80112bc0..f24eea16e2ef 100644 --- a/tests/run/tasty-extractors-types/quoted_1.scala +++ b/tests/run/tasty-extractors-types/quoted_1.scala @@ -5,7 +5,7 @@ import scala.tasty.util.TreeTraverser object Macros { - implicit transparent def printType[T]: Unit = + implicit rewrite def printType[T]: Unit = ~impl('[T])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl[T](x: Type[T])(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-getfile/Macro_1.scala b/tests/run/tasty-getfile/Macro_1.scala index 57c10cdb3909..34d6bfb5402c 100644 --- a/tests/run/tasty-getfile/Macro_1.scala +++ b/tests/run/tasty-getfile/Macro_1.scala @@ -3,7 +3,7 @@ import scala.tasty.{Tasty, TopLevelSplice} object SourceFiles { - implicit transparent def getThisFile: String = + implicit rewrite def getThisFile: String = ~getThisFileImpl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ private def getThisFileImpl(implicit tasty: Tasty): Expr[String] = { diff --git a/tests/run/tasty-indexed-map/quoted_1.scala b/tests/run/tasty-indexed-map/quoted_1.scala index ac66c1c4a75b..7c3aa6f45d0b 100644 --- a/tests/run/tasty-indexed-map/quoted_1.scala +++ b/tests/run/tasty-indexed-map/quoted_1.scala @@ -24,7 +24,7 @@ object Index { implicit def zero[K, T]: Index[K, (K, T)] = new Index(0) - implicit transparent def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ~succImpl(TopLevelSplice.tastyContext)('[K], '[H], '[T]) + implicit rewrite def succ[K, H, T](implicit prev: => Index[K, T]): Index[K, (H, T)] = ~succImpl(TopLevelSplice.tastyContext)('[K], '[H], '[T]) def succImpl[K, H, T](tasty: Tasty)(implicit k: Type[K], h: Type[H], t: Type[T]): Expr[Index[K, (H, T)]] = { import tasty._ diff --git a/tests/run/tasty-linenumber-2/quoted_1.scala b/tests/run/tasty-linenumber-2/quoted_1.scala index 6349af730d8b..d825cce1e942 100644 --- a/tests/run/tasty-linenumber-2/quoted_1.scala +++ b/tests/run/tasty-linenumber-2/quoted_1.scala @@ -8,7 +8,7 @@ class LineNumber(val value: Int) { object LineNumber { - implicit transparent def line: LineNumber = + implicit rewrite def line: LineNumber = ~lineImpl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def lineImpl(implicit tasty: Tasty): Expr[LineNumber] = { diff --git a/tests/run/tasty-linenumber/quoted_1.scala b/tests/run/tasty-linenumber/quoted_1.scala index f7ab41c2ac52..4946c859be72 100644 --- a/tests/run/tasty-linenumber/quoted_1.scala +++ b/tests/run/tasty-linenumber/quoted_1.scala @@ -8,7 +8,7 @@ class LineNumber(val value: Int) { object LineNumber { - implicit transparent def line[T >: Unit <: Unit]: LineNumber = + implicit rewrite def line[T >: Unit <: Unit]: LineNumber = ~lineImpl('[T])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def lineImpl(x: Type[Unit])(implicit tasty: Tasty): Expr[LineNumber] = { diff --git a/tests/run/tasty-location/quoted_1.scala b/tests/run/tasty-location/quoted_1.scala index 48ee3668952c..c7b7fca9aa42 100644 --- a/tests/run/tasty-location/quoted_1.scala +++ b/tests/run/tasty-location/quoted_1.scala @@ -6,7 +6,7 @@ case class Location(owners: List[String]) object Location { - implicit transparent def location: Location = + implicit rewrite def location: Location = ~impl(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl(implicit tasty: Tasty): Expr[Location] = { diff --git a/tests/run/tasty-macro-assert/quoted_1.scala b/tests/run/tasty-macro-assert/quoted_1.scala index bafb9a454809..92c609bd2d72 100644 --- a/tests/run/tasty-macro-assert/quoted_1.scala +++ b/tests/run/tasty-macro-assert/quoted_1.scala @@ -11,7 +11,7 @@ object Asserts { object Ops - transparent def macroAssert(cond: => Boolean): Unit = + rewrite def macroAssert(cond: => Boolean): Unit = ~impl('(cond))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl(cond: Expr[Boolean])(implicit tasty: Tasty): Expr[Unit] = { diff --git a/tests/run/tasty-positioned/quoted_1.scala b/tests/run/tasty-positioned/quoted_1.scala index 74ee127a9a0f..799aaa0c9f05 100644 --- a/tests/run/tasty-positioned/quoted_1.scala +++ b/tests/run/tasty-positioned/quoted_1.scala @@ -9,7 +9,7 @@ case class Positioned[T](value: T, position: Position) object Positioned { - implicit transparent def apply[T](x: => T): Positioned[T] = + implicit rewrite def apply[T](x: => T): Positioned[T] = ~impl('(x))('[T], TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def impl[T](x: Expr[T])(implicit ev: Type[T], tasty: Tasty): Expr[Positioned[T]] = { diff --git a/tests/run/tasty-subtyping/quoted_1.scala b/tests/run/tasty-subtyping/quoted_1.scala index a9e398984f6e..5a5217662579 100644 --- a/tests/run/tasty-subtyping/quoted_1.scala +++ b/tests/run/tasty-subtyping/quoted_1.scala @@ -4,10 +4,10 @@ import scala.tasty._ object Macros { - transparent def isTypeEqual[T, U]: Boolean = + rewrite def isTypeEqual[T, U]: Boolean = ~isTypeEqualImpl('[T], '[U])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ - transparent def isSubTypeOf[T, U]: Boolean = + rewrite def isSubTypeOf[T, U]: Boolean = ~isSubTypeOfImpl('[T], '[U])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def isTypeEqualImpl[T, U](t: Type[T], u: Type[U])(implicit tasty: Tasty): Expr[Boolean] = { diff --git a/tests/run/transparent-foreach.scala b/tests/run/transparent-foreach.scala index a13134f4047c..50fc592c8c33 100644 --- a/tests/run/transparent-foreach.scala +++ b/tests/run/transparent-foreach.scala @@ -1,4 +1,4 @@ -// A demonstrator how `transparent override` can be used to sepcialize inherited methods +// A demonstrator how `rewrite override` can be used to sepcialize inherited methods trait Iterable[+A] { def foreach(f: A => Unit): Unit } @@ -35,7 +35,7 @@ abstract class Range extends Iterable[Int] { class UntilRange(val start: Int, val end: Int) extends Range { def step = 1 def inclusive = false - transparent override def foreach(f: Int => Unit): Unit = { + rewrite override def foreach(f: Int => Unit): Unit = { var idx = start while (idx < end) { f(idx) @@ -54,13 +54,13 @@ object Test extends App { // } class IntDeco(val x: Int) extends AnyVal { - transparent def until(y: Int) = new UntilRange(x, y) + rewrite def until(y: Int) = new UntilRange(x, y) } - implicit transparent def intDeco(x: Int): IntDeco = new IntDeco(x) + implicit rewrite def intDeco(x: Int): IntDeco = new IntDeco(x) // So far, the decorator has to be an explicit def, since // we can inline only methods defined in source. So an implicit class // will not work. We can make this work by making `Desugar` smarter - // and generate a transparent with pre-defined "BodyToInline" annotation. + // and generate a rewrite method with pre-defined "BodyToInline" annotation. // It's doable, just extra work. (1 until 10).foreach(x += _) diff --git a/tests/run/transparent-implicits.scala b/tests/run/transparent-implicits.scala index bd41c41eecb9..153313012657 100644 --- a/tests/run/transparent-implicits.scala +++ b/tests/run/transparent-implicits.scala @@ -11,7 +11,7 @@ object inlines { class C { implicit val x: X = new X() - transparent + rewrite def f(): (X, Y) = (implicitly[X], implicitly[Y]) } diff --git a/tests/run/transparent-object.scala b/tests/run/transparent-object.scala index 21d2566022df..3368fe4843d5 100644 --- a/tests/run/transparent-object.scala +++ b/tests/run/transparent-object.scala @@ -6,7 +6,7 @@ object Test { } object Foo extends Bar { - transparent def foo: Unit = bar + rewrite def foo: Unit = bar } class Bar { diff --git a/tests/run/transparent/inlines_1.scala b/tests/run/transparent/inlines_1.scala index 7fa71ba47ab9..502055c374a8 100644 --- a/tests/run/transparent/inlines_1.scala +++ b/tests/run/transparent/inlines_1.scala @@ -4,7 +4,7 @@ import collection.mutable object transparents { final val monitored = false - transparent def f(x: Int): Int = x * x + rewrite def f(x: Int): Int = x * x val hits = new mutable.HashMap[String, Int] { override def default(key: String): Int = 0 @@ -19,7 +19,7 @@ object transparents { @volatile private var stack: List[String] = Nil - transparent def track[T](fn: String)(op: => T) = + rewrite def track[T](fn: String)(op: => T) = if (monitored) { stack = fn :: stack record(fn) @@ -31,9 +31,9 @@ object transparents { def f = "Outer.f" class Inner { val msg = " Inner" - transparent def m = msg - transparent def g = f - transparent def h = f ++ m + rewrite def m = msg + rewrite def g = f + rewrite def h = f ++ m } val inner = new Inner } @@ -44,12 +44,12 @@ object transparents { } class TestPassing { - transparent def foo[A](x: A): (A, Int) = { + rewrite def foo[A](x: A): (A, Int) = { val c = new C[A](x) c.xx = c.x c.next(1) } - transparent def bar[A](x: A): (A, String) = { + rewrite def bar[A](x: A): (A, String) = { val c = new C[A](x) c.xx = c.x c.next("") diff --git a/tests/run/transparentAccess/C_1.scala b/tests/run/transparentAccess/C_1.scala index 45db8603e8c6..1de2bfbe8bb2 100644 --- a/tests/run/transparentAccess/C_1.scala +++ b/tests/run/transparentAccess/C_1.scala @@ -2,6 +2,6 @@ package p { class C { protected def f(): Unit = () - transparent def inl() = f() // error (when inlined): not accessible + rewrite def inl() = f() // error (when inlined): not accessible } } diff --git a/tests/run/transparentArrowAssoc.scala b/tests/run/transparentArrowAssoc.scala index 80dd0d90d3c3..e68986b6a18d 100644 --- a/tests/run/transparentArrowAssoc.scala +++ b/tests/run/transparentArrowAssoc.scala @@ -10,7 +10,7 @@ object Test { ) final implicit class ArrowAssoc[A](private val self: A) extends AnyVal { - transparent def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y) + rewrite def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y) def →[B](y: B): Tuple2[A, B] = ->(y) } diff --git a/tests/run/transparentAssign.scala b/tests/run/transparentAssign.scala index 5851550f857f..8821fd4351c3 100644 --- a/tests/run/transparentAssign.scala +++ b/tests/run/transparentAssign.scala @@ -1,11 +1,11 @@ object Test { - transparent def swap[T](x: T, x_= : => T => Unit, y: T, y_= : => T => Unit) = { + rewrite def swap[T](x: T, x_= : => T => Unit, y: T, y_= : => T => Unit) = { x_=(y) y_=(x) } - transparent def f(x: Int => Unit) = x + rewrite def f(x: Int => Unit) = x def main(args: Array[String]) = { var x = 1 diff --git a/tests/run/transparentByName.scala b/tests/run/transparentByName.scala index 837ecc7ff26a..33e76d25802d 100644 --- a/tests/run/transparentByName.scala +++ b/tests/run/transparentByName.scala @@ -1,7 +1,7 @@ object Test { class Range(from: Int, end: Int) { - transparent def foreach(op: => Int => Unit): Unit = { + rewrite def foreach(op: => Int => Unit): Unit = { var i = from while (i < end) { op(i) @@ -9,11 +9,11 @@ object Test { } } } - transparent def twice(op: => Int => Unit): Unit = { + rewrite def twice(op: => Int => Unit): Unit = { op(1) op(2) } - transparent def thrice(op: => Unit): Unit = { + rewrite def thrice(op: => Unit): Unit = { op op op diff --git a/tests/run/transparentForeach.scala b/tests/run/transparentForeach.scala index eda163707093..d64036fc58f5 100644 --- a/tests/run/transparentForeach.scala +++ b/tests/run/transparentForeach.scala @@ -36,7 +36,7 @@ object Test { } implicit class intArrayOps(arr: Array[Int]) { - transparent def foreach(op: => Int => Unit): Unit = { + rewrite def foreach(op: => Int => Unit): Unit = { var i = 0 while (i < arr.length) { op(arr(i)) diff --git a/tests/run/transparentPower/power_1.scala b/tests/run/transparentPower/power_1.scala index ef43488ce387..0f90b76963cc 100644 --- a/tests/run/transparentPower/power_1.scala +++ b/tests/run/transparentPower/power_1.scala @@ -2,7 +2,7 @@ package p object pow { - transparent def power(x: Double, n: Int): Double = + rewrite def power(x: Double, n: Int): Double = if (n == 0) 1.0 else if (n == 1) x else { diff --git a/tests/run/transparentPrivates.scala b/tests/run/transparentPrivates.scala index 8498203af9ba..11c0e568e0df 100644 --- a/tests/run/transparentPrivates.scala +++ b/tests/run/transparentPrivates.scala @@ -6,19 +6,19 @@ object Test { private var y: T = _ - transparent def get1 = x - transparent def get2[U](c: C[U]) = c.x + rewrite def get1 = x + rewrite def get2[U](c: C[U]) = c.x - transparent def foo1(x: Int) = foo(x) - transparent def foo2[U](c: C[U]) = c.foo(x) + rewrite def foo1(x: Int) = foo(x) + rewrite def foo2[U](c: C[U]) = c.foo(x) - transparent def set1(z: T) = { y = z; y } - transparent def set2[U](c: C[U]) = { c.y = c.x; c.y } + rewrite def set1(z: T) = { y = z; y } + rewrite def set2[U](c: C[U]) = { c.y = c.x; c.y } } object CC { private val x = 3 - transparent def get1 = x + rewrite def get1 = x } def main(args: Array[String]) = { diff --git a/tests/run/transparentProtected.scala b/tests/run/transparentProtected.scala index 478f599b2293..8e32e39387e2 100644 --- a/tests/run/transparentProtected.scala +++ b/tests/run/transparentProtected.scala @@ -7,7 +7,7 @@ package P { package Q { class D extends P.C { class Inner { - transparent def g() = f() + rewrite def g() = f() } } } diff --git a/tests/run/typelevel-defaultValue.scala b/tests/run/typelevel-defaultValue.scala index c31b363f3b18..86f0df230f67 100644 --- a/tests/run/typelevel-defaultValue.scala +++ b/tests/run/typelevel-defaultValue.scala @@ -5,7 +5,7 @@ object typelevel { object Test extends App { - transparent def defaultValue[T]: Option[Any] = typelevel.erasedValue[T] match { + rewrite def defaultValue[T]: Option[Any] = rewrite typelevel.erasedValue[T] match { case _: Byte => Some(0: Byte) case c: Char => Some(0: Char) case d @ (_: Short) => Some(0: Short) diff --git a/tests/run/typelevel-numeric.scala b/tests/run/typelevel-numeric.scala index 7934f961722f..0fb0e3505ef9 100644 --- a/tests/run/typelevel-numeric.scala +++ b/tests/run/typelevel-numeric.scala @@ -7,7 +7,7 @@ abstract class MathLib[N : Numeric] { object MathLib { - transparent def apply[N](implicit n: Numeric[N]) = new MathLib[N] { + rewrite def apply[N](implicit n: Numeric[N]) = new MathLib[N] { import n._ def dotProduct(xs: Array[N], ys: Array[N]): N = { require(xs.length == ys.length) diff --git a/tests/run/typelevel-overrides.scala b/tests/run/typelevel-overrides.scala index 67a9512048f5..293d8ed8cb0e 100644 --- a/tests/run/typelevel-overrides.scala +++ b/tests/run/typelevel-overrides.scala @@ -8,13 +8,13 @@ class A extends T { def f(x: Int) = x } class B extends A { - override transparent def f(x: Int) = x match { + override rewrite def f(x: Int) = rewrite x match { case 0 => 0 case x => x } } class C extends A with U { - override transparent def f(x: Int) = x match { + override rewrite def f(x: Int) = rewrite x match { case 0 => 0 case x => x } diff --git a/tests/run/typelevel-patmat.scala b/tests/run/typelevel-patmat.scala index 6bacf57e2037..b1df0fcab364 100644 --- a/tests/run/typelevel-patmat.scala +++ b/tests/run/typelevel-patmat.scala @@ -21,7 +21,7 @@ object Test extends App { type HNil = HNil.type type Z = Z.type - transparent def ToNat(transparent n: Int): Typed[Nat] = + rewrite def ToNat(transparent n: Int): Typed[Nat] = if n == 0 then Typed(Z) else Typed(S(ToNat(n - 1).value)) @@ -35,7 +35,7 @@ object Test extends App { println(x1) println(x2) - transparent def toInt(n: Nat): Int = n match { + rewrite def toInt(n: Nat): Int = rewrite n match { case Z => 0 case S(n1) => toInt(n1) + 1 } @@ -45,7 +45,7 @@ object Test extends App { transparent val i2 = toInt(y2) val j2: 2 = i2 - transparent def concat(xs: HList, ys: HList): HList = xs match { + rewrite def concat(xs: HList, ys: HList): HList = rewrite xs match { case HNil => ys case HCons(x, xs1) => HCons(x, concat(xs1, ys)) } @@ -68,7 +68,7 @@ object Test extends App { val r6 = concat(HCons(1, HCons("a", HNil)), HCons(true, HCons(1.0, HNil))) val c6: HCons[Int, HCons[String, HCons[Boolean, HCons[Double, HNil]]]] = r6 - transparent def nth(xs: HList, n: Int): Any = xs match { + rewrite def nth(xs: HList, n: Int): Any = rewrite xs match { case HCons(x, _) if n == 0 => x case HCons(_, xs1) if n > 0 => nth(xs1, n - 1) } @@ -78,7 +78,7 @@ object Test extends App { val e1 = nth(r2, 1) val ce1: String = e1 - transparent def concatTyped(xs: HList, ys: HList): Typed[_ <: HList] = xs match { + rewrite def concatTyped(xs: HList, ys: HList): Typed[_ <: HList] = rewrite xs match { case HNil => Typed(ys) case HCons(x, xs1) => Typed(HCons(x, concatTyped(xs1, ys).value)) } @@ -88,7 +88,7 @@ object Test extends App { case HCons(x, xs1) => HCons(x, concatImpl(xs1, ys)) } - transparent def concatErased(xs: HList, ys: HList): HList = { + rewrite def concatErased(xs: HList, ys: HList): HList = { erased val r = concatTyped(xs, ys) concatImpl(xs, ys).asInstanceOf[r.Type] } diff --git a/tests/run/typelevel.scala b/tests/run/typelevel.scala index ee7bf50521f2..52dcb643deaa 100644 --- a/tests/run/typelevel.scala +++ b/tests/run/typelevel.scala @@ -4,24 +4,24 @@ trait Nat { } case object Z extends Nat { - transparent override def toInt = 0 + rewrite override def toInt = 0 } case class S[N <: Nat](n: N) extends Nat { - transparent override def toInt = n.toInt + 1 + rewrite override def toInt = n.toInt + 1 } trait HList { def length: Int = ??? def head: Any def tail: HList - transparent def isEmpty: Boolean = + rewrite def isEmpty: Boolean = length == 0 } // () case object HNil extends HList { - transparent override def length = 0 + rewrite override def length = 0 def head: Nothing = ??? def tail: Nothing = ??? } @@ -29,7 +29,7 @@ case object HNil extends HList { // (H, T) @annotation.showAsInfix(true) case class HCons [H, T <: HList](hd: H, tl: T) extends HList { - transparent override def length = 1 + tl.length + rewrite override def length = 1 + tl.length def head: H = this.hd def tail: T = this.tl } @@ -42,7 +42,7 @@ object Test extends App { type HNil = HNil.type type Z = Z.type - transparent def ToNat(transparent n: Int): ToNat[Nat] = + rewrite def ToNat(transparent n: Int): ToNat[Nat] = if n == 0 then new ToNat(Z) else { val n1 = ToNat(n - 1) @@ -67,10 +67,10 @@ object Test extends App { val j2: 2 = i2 class HListDeco(private val as: HList) extends AnyVal { - transparent def :: [H] (a: H) = HCons(a, as) - transparent def ++ (bs: HList) = concat(as, bs) + rewrite def :: [H] (a: H) = HCons(a, as) + rewrite def ++ (bs: HList) = concat(as, bs) } - transparent def concat(xs: HList, ys: HList): HList = + rewrite def concat(xs: HList, ys: HList): HList = if xs.isEmpty then ys else HCons(xs.head, concat(xs.tail, ys)) @@ -85,11 +85,11 @@ object Test extends App { val r5 = concat(HCons(1, HCons("a", HNil)) , HNil) val r6 = concat(HCons(1, HCons("a", HNil)), HCons(true, HCons(1.0, HNil))) - transparent def size(xs: HList): Nat = + rewrite def size(xs: HList): Nat = if xs.isEmpty then Z else S(size(xs.tail)) - transparent def sizeDefensive(xs: HList): Nat = xs.isEmpty match { + rewrite def sizeDefensive(xs: HList): Nat = rewrite xs.isEmpty match { case true => Z case false => S(sizeDefensive(xs.tail)) } @@ -101,7 +101,7 @@ object Test extends App { transparent val l1 = xs.length val l1a: 2 = l1 - transparent def index(xs: HList, transparent idx: Int): Any = + rewrite def index(xs: HList, transparent idx: Int): Any = if idx == 0 then xs.head else index(xs.tail, idx - 1) @@ -117,7 +117,7 @@ object Test extends App { //val ys = 1 :: "a" :: HNil - transparent implicit def hlistDeco(xs: HList): HListDeco = new HListDeco(xs) + rewrite implicit def hlistDeco(xs: HList): HListDeco = new HListDeco(xs) val rr0 = new HListDeco(HNil).++(HNil) val rr1 = HNil ++ xs @@ -125,7 +125,7 @@ object Test extends App { val rr3 = xs ++ xs val rr3a: HCons[Int, HCons[String, HCons[Int, HCons[String, HNil]]]] = rr3 - transparent def f(c: Boolean): Nat = { + rewrite def f(c: Boolean): Nat = { def g[X <: Nat](x: X): X = x g(if (c) Z else S(Z)) } @@ -133,8 +133,8 @@ object Test extends App { val f1: Z = f(true) val f2: S[Z] = f(false) - transparent def mapHead[T, R](t: T)(implicit fh: T => R): R = fh(t) - transparent def map(xs: HList): HList = { + rewrite def mapHead[T, R](t: T)(implicit fh: T => R): R = fh(t) + rewrite def map(xs: HList): HList = { if (xs.isEmpty) HNil else HCons(mapHead(xs.head), map(xs.tail)) @@ -148,12 +148,12 @@ object Test extends App { val res1: Boolean `HCons` (Int `HCons` (String `HCons` HNil)) = res /* - transparent def toInt1[T]: Int = type T match { + rewrite def toInt1[T]: Int = type T match { case Z => 0 case S[type N] => toInt[N] + 1 } - transparent def toInt1[T]: Nat = implicit match { + rewrite def toInt1[T]: Nat = implicit match { case C[type T, type U], T =:= U => case T <:< S[type N] => toInt[N] + 1 } diff --git a/tests/run/typelevel1.scala b/tests/run/typelevel1.scala index d6de13790965..b3a9e8f30c73 100644 --- a/tests/run/typelevel1.scala +++ b/tests/run/typelevel1.scala @@ -4,17 +4,17 @@ trait HList { def head: Any def tail: HList - transparent def isEmpty: Boolean = length == 0 + rewrite def isEmpty: Boolean = length == 0 } case object HNil extends HList { - transparent override def length = 0 + rewrite override def length = 0 def head: Nothing = ??? def tail: Nothing = ??? } case class :: [H, T <: HList] (hd: H, tl: T) extends HList { - transparent override def length = 1 + tl.length + rewrite override def length = 1 + tl.length def head: H = this.hd def tail: T = this.tl } @@ -23,14 +23,14 @@ object Test extends App { type HNil = HNil.type class HListDeco(val as: HList) extends AnyVal { - transparent def :: [H] (a: H): HList = new :: (a, as) - transparent def ++ (bs: HList): HList = concat(as, bs) - transparent def apply(idx: Int): Any = index(as, idx) + rewrite def :: [H] (a: H): HList = new :: (a, as) + rewrite def ++ (bs: HList): HList = concat(as, bs) + rewrite def apply(idx: Int): Any = index(as, idx) } - transparent implicit def hlistDeco(xs: HList): HListDeco = new HListDeco(xs) + rewrite implicit def hlistDeco(xs: HList): HListDeco = new HListDeco(xs) - transparent def concat[T1, T2](xs: HList, ys: HList): HList = + rewrite def concat[T1, T2](xs: HList, ys: HList): HList = if xs.isEmpty then ys else new ::(xs.head, concat(xs.tail, ys)) @@ -40,7 +40,7 @@ object Test extends App { val control: Int :: String :: String :: Boolean :: Double :: HNil = zs - transparent def index(xs: HList, idx: Int): Any = + rewrite def index(xs: HList, idx: Int): Any = if idx == 0 then xs.head else index(xs.tail, idx - 1) diff --git a/tests/run/typelevel3.scala b/tests/run/typelevel3.scala index ca115f81ad6b..f4dcbd3b67ed 100644 --- a/tests/run/typelevel3.scala +++ b/tests/run/typelevel3.scala @@ -4,17 +4,17 @@ trait HList { def head: Any def tail: HList - transparent def isEmpty: Boolean = length == 0 + rewrite def isEmpty: Boolean = length == 0 } case object HNil extends HList { - transparent override def length = 0 + rewrite override def length = 0 def head: Nothing = ??? def tail: Nothing = ??? } case class HCons[H, T <: HList](hd: H, tl: T) extends HList { - transparent override def length = 1 + tl.length + rewrite override def length = 1 + tl.length def head: H = this.hd def tail: T = this.tl } @@ -24,7 +24,7 @@ case class Typed[T](val value: T) { type Type = T } object Test extends App { type HNil = HNil.type - transparent def concat(xs: HList, ys: HList): Typed[_ <: HList] = + rewrite def concat(xs: HList, ys: HList): Typed[_ <: HList] = if xs.isEmpty then Typed(ys) else Typed(HCons(xs.head, concat(xs.tail, ys).value)) @@ -35,7 +35,7 @@ object Test extends App { val control: HCons[Int, HCons[String, HCons[String, HCons[Boolean, HCons[Double, HNil]]]]] = zs.value - transparent def index(xs: HList, idx: Int): Typed[_] = + rewrite def index(xs: HList, idx: Int): Typed[_] = if idx == 0 then Typed(xs.head) else Typed(index(xs.tail, idx - 1).value) @@ -51,7 +51,7 @@ object Test extends App { if xs.isEmpty then ys else HCons(xs.head, opaqueConcat(xs.tail, ys)) - transparent def compactConcat(xs: HList, ys: HList): HList = { + rewrite def compactConcat(xs: HList, ys: HList): HList = { erased val r = concat(xs, ys) opaqueConcat(xs, ys).asInstanceOf[r.Type] } From f697eb01e94454de2e71040e0cbbac7755451a0a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 12 Aug 2018 20:56:46 +0200 Subject: [PATCH 03/11] Fix test --- compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala index 6d6385497949..6a92872e5213 100644 --- a/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/DottyBytecodeTests.scala @@ -314,7 +314,7 @@ class TestBCode extends DottyBytecodeTest { @Test def i4172 = { val source = """class Test { - | transparent def foo(first: Int*)(second: String = "") = {} + | rewrite def foo(first: Int*)(second: String = "") = {} | | def test = { | foo(1)() From e48a9c74a81ce6d95e655db88f9d73a7dea61b4c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Aug 2018 15:41:41 +0200 Subject: [PATCH 04/11] Change overriding rule for erased values erased can only override erased, non-erased can only override non-erased. --- compiler/src/dotty/tools/dotc/typer/RefChecks.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index ab5dbbf1c0bd..292bbe6cc70d 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -143,8 +143,8 @@ object RefChecks { * 1.8.1 M's type is a subtype of O's type, or * 1.8.2 M is of type []S, O is of type ()T and S <: T, or * 1.8.3 M is of type ()S, O is of type []T and S <: T, or - * 1.9 If M is an erased def, O must be as well - * 1.10 If `M` is a rewrite or Scala2x macro method, O cannot be deferred unless + * 1.9 If M or O are erased, they must be both erased + * 1.10 If M is a rewrite or Scala-2 macro method, O cannot be deferred unless * there's also a concrete method that M overrides. * 1.11. If O is a Scala-2 macro, M must be a Scala-2 macro. * 2. Check that only abstract classes have deferred members @@ -379,6 +379,8 @@ object RefChecks { overrideError("must be declared lazy to override a lazy value") } else if (member.is(Erased) && !other.is(Erased)) { // (1.9) overrideError("is erased, cannot override non-erased member") + } else if (other.is(Erased) && !member.is(Erased)) { // (1.9) + overrideError("is not erased, cannot override erased member") } else if ((member.is(Rewrite) || member.is(Scala2Macro)) && other.is(Deferred) && member.extendedOverriddenSymbols.forall(_.is(Deferred))) { // (1.10) overrideError("is a rewrite method, must override at least one concrete method") From aa96f350eff61b9b5fc4928fb5ff5300082a5818 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Aug 2018 15:43:29 +0200 Subject: [PATCH 05/11] Change test to use non-toplevel rewrite match --- tests/run/TupleAbstract.scala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/run/TupleAbstract.scala b/tests/run/TupleAbstract.scala index 1abd74259fcd..693d71e08224 100644 --- a/tests/run/TupleAbstract.scala +++ b/tests/run/TupleAbstract.scala @@ -138,25 +138,26 @@ object Tuples { rewrite def head: Any = { erased val resTpe = Typed(_head(xs)) - rewrite _size(xs) match { + val resVal = rewrite _size(xs) match { case 1 => val t = xs.asInstanceOf[Tuple1[_]] - t._1.asInstanceOf[resTpe.Type] + t._1 case 2 => val t = xs.asInstanceOf[Tuple2[_, _]] - t._1.asInstanceOf[resTpe.Type] + t._1 case 3 => val t = xs.asInstanceOf[Tuple3[_, _, _]] - t._1.asInstanceOf[resTpe.Type] + t._1 case 4 => val t = xs.asInstanceOf[Tuple4[_, _, _, _]] - t._1.asInstanceOf[resTpe.Type] + t._1 case n if n > 4 && n <= MaxSpecialized => - xs.asInstanceOf[Product].productElement(0).asInstanceOf[resTpe.Type] + xs.asInstanceOf[Product].productElement(0) case n if n > MaxSpecialized => val t = xs.asInstanceOf[TupleXXL] - t.elems(0).asInstanceOf[resTpe.Type] + t.elems(0) } + resVal.asInstanceOf[resTpe.Type] } rewrite def tail: Any = { From bbe88d140916c57ad3e4703796be230fbdaef9d4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 22 Aug 2018 18:42:58 +0200 Subject: [PATCH 06/11] Fix transparent -> rewrite ...in new code added through rebase --- tests/pos/i4734/Macro_1.scala | 2 +- tests/run/i4734/Macro_1.scala | 2 +- tests/run/tasty-definitions-2/Macro_1.scala | 2 +- tests/run/tasty-definitions-3/Macro_1.scala | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/pos/i4734/Macro_1.scala b/tests/pos/i4734/Macro_1.scala index 2d4155aed9a5..68ba04975521 100644 --- a/tests/pos/i4734/Macro_1.scala +++ b/tests/pos/i4734/Macro_1.scala @@ -2,7 +2,7 @@ import scala.annotation.tailrec import scala.quoted._ object Macros { - transparent def unrolledForeach(f: Int => Int): Int = + rewrite def unrolledForeach(f: Int => Int): Int = ~unrolledForeachImpl('(f)) def unrolledForeachImpl(f: Expr[Int => Int]): Expr[Int] = '{ diff --git a/tests/run/i4734/Macro_1.scala b/tests/run/i4734/Macro_1.scala index 1171966b6590..92b7512aa95a 100644 --- a/tests/run/i4734/Macro_1.scala +++ b/tests/run/i4734/Macro_1.scala @@ -2,7 +2,7 @@ import scala.annotation.tailrec import scala.quoted._ object Macros { - transparent def unrolledForeach(seq: IndexedSeq[Int], f: => Int => Unit, transparent unrollSize: Int): Unit = // or f: Int => Unit + rewrite def unrolledForeach(seq: IndexedSeq[Int], f: => Int => Unit, transparent unrollSize: Int): Unit = // or f: Int => Unit ~unrolledForeachImpl('(seq), '(f), unrollSize) def unrolledForeachImpl(seq: Expr[IndexedSeq[Int]], f: Expr[Int => Unit], unrollSize: Int): Expr[Unit] = '{ diff --git a/tests/run/tasty-definitions-2/Macro_1.scala b/tests/run/tasty-definitions-2/Macro_1.scala index cc4870d39e62..8345d9613828 100644 --- a/tests/run/tasty-definitions-2/Macro_1.scala +++ b/tests/run/tasty-definitions-2/Macro_1.scala @@ -3,7 +3,7 @@ import scala.tasty._ object Foo { - transparent def inspectBody(i: => Int): String = + rewrite def inspectBody(i: => Int): String = ~inspectBodyImpl('(i))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def inspectBodyImpl(x: Expr[Int])(implicit tasty: Tasty): Expr[String] = { diff --git a/tests/run/tasty-definitions-3/Macro_1.scala b/tests/run/tasty-definitions-3/Macro_1.scala index 02bbd8a351db..940bb827a7c9 100644 --- a/tests/run/tasty-definitions-3/Macro_1.scala +++ b/tests/run/tasty-definitions-3/Macro_1.scala @@ -3,7 +3,7 @@ import scala.tasty._ object Foo { - transparent def inspectBody(i: => Int): String = + rewrite def inspectBody(i: => Int): String = ~inspectBodyImpl('(i))(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ def inspectBodyImpl(x: Expr[Int])(implicit tasty: Tasty): Expr[String] = { From df8293abd2d3a98f265782e1eeaa473d7046710c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 27 Aug 2018 14:27:50 +0200 Subject: [PATCH 07/11] Drop debug printlns --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 596dce4fca49..f4abf16104bf 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -2543,8 +2543,6 @@ object Parsers { stats +++= defOrDcl(in.offset, defAnnotsMods(modifierTokens)) else if (!isStatSep) { exitOnError = mustStartStat - println(in.token) - println(in.next.token) syntaxErrorOrIncomplete("illegal start of definition") } acceptStatSepUnlessAtEnd() From 076a5dda508d119bf9cba611b68fe5ed4c4b0bae Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 27 Aug 2018 15:27:41 +0200 Subject: [PATCH 08/11] Fix tests --- tests/run/i4947a.scala | 2 +- tests/run/i4947b/Lib_1.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/run/i4947a.scala b/tests/run/i4947a.scala index aa0484b04e29..025220d9e86e 100644 --- a/tests/run/i4947a.scala +++ b/tests/run/i4947a.scala @@ -1,6 +1,6 @@ object Test { - transparent def fact[T](transparent i: Int)(f: => T): Int = { + rewrite def fact[T](transparent i: Int)(f: => T): Int = { printStack("track", i) printStack("track", i) f diff --git a/tests/run/i4947b/Lib_1.scala b/tests/run/i4947b/Lib_1.scala index 8f0799b9cc18..dd81f8b5ad2d 100644 --- a/tests/run/i4947b/Lib_1.scala +++ b/tests/run/i4947b/Lib_1.scala @@ -1,5 +1,5 @@ object Lib { - transparent def track[T](f: => T): T = { + rewrite def track[T](f: => T): T = { printStack("track") printStack("track") f @@ -12,7 +12,7 @@ object Lib { println(s"$tag (i = $i): ${new Exception().getStackTrace().apply(1)}") } - transparent def fact[T](transparent i: Int)(f: => T): Int = { + rewrite def fact[T](transparent i: Int)(f: => T): Int = { printStack("track", i) printStack("track", i) track { From 739efdbc63039655bb0be02c7d3743c25f4dd8a9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 27 Aug 2018 16:26:45 +0200 Subject: [PATCH 09/11] Fix more tests --- tests/run/i4947.scala | 2 +- tests/run/i4947c.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/run/i4947.scala b/tests/run/i4947.scala index 08648487f7fa..690608cd8038 100644 --- a/tests/run/i4947.scala +++ b/tests/run/i4947.scala @@ -1,6 +1,6 @@ object Test { - transparent def track[T](f: => T): T = { + rewrite def track[T](f: => T): T = { printStack("track") printStack("track") f diff --git a/tests/run/i4947c.scala b/tests/run/i4947c.scala index be1efe8cdb8e..42d7c12c6a9f 100644 --- a/tests/run/i4947c.scala +++ b/tests/run/i4947c.scala @@ -1,6 +1,6 @@ object Aux { - transparent def track[T](f: => T): T = { + rewrite def track[T](f: => T): T = { printStack("track") printStack("track") f From 006f9ef0dd6ac3954b73d8150da4a4ed63015744 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 27 Aug 2018 17:20:50 +0200 Subject: [PATCH 10/11] Fix even more tests --- .../tools/backend/jvm/InlineBytecodeTests.scala | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala b/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala index 0505162b57a3..e9d99dcd7f20 100644 --- a/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala +++ b/compiler/test/dotty/tools/backend/jvm/InlineBytecodeTests.scala @@ -44,7 +44,7 @@ class InlineBytecodeTests extends DottyBytecodeTest { @Test def i4947 = { val source = """class Foo { - | transparent def track[T](f: => T): T = { + | rewrite def track[T](f: => T): T = { | foo("tracking") // line 3 | f // line 4 | } @@ -103,11 +103,11 @@ class InlineBytecodeTests extends DottyBytecodeTest { @Test def i4947b = { val source = """class Foo { - | transparent def track2[T](f: => T): T = { + | rewrite def track2[T](f: => T): T = { | foo("tracking2") // line 3 | f // line 4 | } - | transparent def track[T](f: => T): T = { + | rewrite def track[T](f: => T): T = { | foo("tracking") // line 7 | track2 { // line 8 | f // line 9 @@ -163,11 +163,11 @@ class InlineBytecodeTests extends DottyBytecodeTest { @Test def i4947c = { val source = """class Foo { - | transparent def track2[T](f: => T): T = { + | rewrite def track2[T](f: => T): T = { | foo("tracking2") // line 3 | f // line 4 | } - | transparent def track[T](f: => T): T = { + | rewrite def track[T](f: => T): T = { | track2 { // line 7 | foo("fgh") // line 8 | f // line 9 @@ -223,11 +223,11 @@ class InlineBytecodeTests extends DottyBytecodeTest { @Test def i4947d = { val source = """class Foo { - | transparent def track2[T](f: => T): T = { + | rewrite def track2[T](f: => T): T = { | foo("tracking2") // line 3 | f // line 4 | } - | transparent def track[T](f: => T): T = { + | rewrite def track[T](f: => T): T = { | track2 { // line 7 | track2 { // line 8 | f // line 9 From 6ab608ea6be1de5a3ce8b26d8194f624449c5fd8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 27 Aug 2018 18:32:46 +0200 Subject: [PATCH 11/11] Fix yet another test --- .../dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala index 68f05e11881e..7ee1015b5f69 100644 --- a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala @@ -102,7 +102,7 @@ class BootstrappedOnlyCompilationTests extends ParallelTesting { compileDir("compiler/src/dotty/tools/dotc/parsing", picklingWithCompilerOptions) + compileDir("compiler/src/dotty/tools/dotc/printing", picklingWithCompilerOptions) + compileDir("compiler/src/dotty/tools/repl", picklingWithCompilerOptions) + - compileDir("compiler/src/dotty/tools/dotc/rewrite", picklingWithCompilerOptions) + + compileDir("compiler/src/dotty/tools/dotc/rewrites", picklingWithCompilerOptions) + compileDir("compiler/src/dotty/tools/dotc/transform", picklingWithCompilerOptions) + compileDir("compiler/src/dotty/tools/dotc/typer", picklingWithCompilerOptions) + compileDir("compiler/src/dotty/tools/dotc/util", picklingWithCompilerOptions) +