From a0dcb9e53204b7b16cd0e200d34307204045949c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 10 Apr 2019 14:16:15 +0000 Subject: [PATCH 1/4] Change `erased` syntax `erased` now follows `given` instead of `implicit`. --- .../dotty/tools/dotc/core/Definitions.scala | 4 +- .../dotty/tools/dotc/parsing/Parsers.scala | 50 ++++++++----------- .../tools/dotc/printing/PlainPrinter.scala | 8 +-- .../tools/dotc/printing/RefinedPrinter.scala | 4 +- compiler/test-resources/repl/erased | 4 +- compiler/test-resources/repl/erased-implicit | 4 +- docs/docs/internals/syntax.md | 15 +++--- .../other-new-features/erased-terms.md | 38 +++++++------- ...6217aaf5e71195b85b12ca59245f35152885.scala | 2 +- tests/generic-java-signatures/erased.scala | 2 +- tests/neg/erased-1.scala | 4 +- tests/neg/erased-2.scala | 4 +- tests/neg/erased-24.scala | 4 +- tests/neg/erased-3.scala | 4 +- tests/neg/erased-4.scala | 2 +- tests/neg/erased-assign.scala | 2 +- tests/neg/erased-case-class.scala | 2 +- tests/neg/erased-def-rhs.scala | 2 +- tests/neg/erased-if-else.scala | 2 +- tests/neg/erased-match.scala | 2 +- tests/neg/erased-pathdep-1.scala | 6 +-- tests/neg/erased-pathdep-2.scala | 2 +- tests/neg/erased-return.scala | 2 +- tests/neg/erased-try.scala | 4 +- tests/neg/erased-val-rhs.scala | 2 +- tests/neg/erased-value-class.scala | 2 +- tests/neg/i4060.scala | 4 +- tests/pos/erased-args-lifted.scala | 2 +- tests/pos/erased-asInstanceOf.scala | 2 +- tests/pos/erased-deep-context.scala | 6 +-- tests/pos/erased-extension-method.scala | 2 +- tests/pos/phantom-Eq.scala | 4 +- tests/pos/phantom-Eq2/Phantom-Eq_1.scala | 4 +- tests/pos/phantom-Evidence.scala | 4 +- tests/run/erased-1.scala | 2 +- tests/run/erased-10.scala | 2 +- tests/run/erased-11.scala | 6 +-- tests/run/erased-12.scala | 2 +- tests/run/erased-13.scala | 2 +- tests/run/erased-15.scala | 2 +- tests/run/erased-16.scala | 4 +- tests/run/erased-2.scala | 2 +- tests/run/erased-22.scala | 2 +- tests/run/erased-25.scala | 2 +- tests/run/erased-26.scala | 2 +- tests/run/erased-27.scala | 2 +- tests/run/erased-28.scala | 4 +- tests/run/erased-3.scala | 2 +- tests/run/erased-4.scala | 4 +- tests/run/erased-5.scala | 4 +- tests/run/erased-6.scala | 2 +- tests/run/erased-7.scala | 4 +- tests/run/erased-8.scala | 4 +- tests/run/erased-9.scala | 2 +- tests/run/erased-frameless.scala | 2 +- tests/run/erased-machine-state.scala | 4 +- tests/run/erased-poly-ref.scala | 4 +- tests/run/erased-select-prefix.scala | 2 +- tests/run/erased-value-class.scala | 2 +- tests/run/phantom-OnHList.scala | 4 +- 60 files changed, 136 insertions(+), 143 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 6383a07e6882..973e025d9c0f 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -106,13 +106,13 @@ class Definitions { * ErasedFunctionN traits follow this template: * * trait ErasedFunctionN[T0,...,T{N-1}, R] extends Object { - * def apply(erased $x0: T0, ..., $x{N_1}: T{N-1}): R + * def apply erased ($x0: T0, ..., $x{N_1}: T{N-1}): R * } * * ErasedImplicitFunctionN traits follow this template: * * trait ErasedImplicitFunctionN[T0,...,T{N-1}, R] extends Object { - * def apply given (erased $x0: T0, ..., $x{N_1}: T{N-1}): R + * def apply given erased ($x0: T0, ..., $x{N_1}: T{N-1}): R * } * * ErasedFunctionN and ErasedImplicitFunctionN erase to Function0. diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index d74bbfff8ab0..20944cb4aaa2 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1210,7 +1210,7 @@ object Parsers { def expr(location: Location.Value): Tree = { val start = in.offset - if (in.token == IMPLICIT || in.token == ERASED || in.token == GIVEN) { + if (closureMods.contains(in.token)) { val imods = modifiers(closureMods) if (in.token == MATCH) implicitMatch(start, imods) else implicitClosure(start, location, imods) @@ -1994,11 +1994,9 @@ object Parsers { normalize(loop(start)) } - /** FunArgMods ::= { `implicit` | `erased` } - * ClosureMods ::= { ‘implicit’ | ‘erased’ | ‘given’} + /** ClosureMods ::= { ‘implicit’ | ‘erased’ | ‘given’} * FunTypeMods ::= { ‘erased’ | ‘given’} */ - val funArgMods: BitSet = BitSet(IMPLICIT, ERASED) val closureMods: BitSet = BitSet(GIVEN, IMPLICIT, ERASED) val funTypeMods: BitSet = BitSet(GIVEN, ERASED) @@ -2083,11 +2081,12 @@ object Parsers { def typeParamClauseOpt(ownerKind: ParamOwner.Value): List[TypeDef] = if (in.token == LBRACKET) typeParamClause(ownerKind) else Nil - /** ClsParamClause ::= [nl | ‘with’] `(' [FunArgMods] [ClsParams] ')' + /** ClsParamClause ::= [nl] [‘erased’] ‘(’ [ClsParams] ‘)’ + * | ‘given’ [‘erased’] (‘(’ ClsParams ‘)’ | ContextTypes) * ClsParams ::= ClsParam {`' ClsParam} * ClsParam ::= {Annotation} [{ParamModifier} (`val' | `var') | `inline'] Param - * DefParamClause ::= [nl] `(' [FunArgMods] [DefParams] ')' | InferParamClause - * InferParamClause ::= ‘given’ (‘(’ DefParams ‘)’ | ContextTypes) + * DefParamClause ::= [nl] [‘erased’] ‘(’ [DefParams] ‘)’ | GivenParamClause + * GivenParamClause ::= ‘given’ [‘erased’] (‘(’ DefParams ‘)’ | ContextTypes) * ContextTypes ::= RefinedType {`,' RefinedType} * DefParams ::= DefParam {`,' DefParam} * DefParam ::= {Annotation} [`inline'] Param @@ -2158,17 +2157,10 @@ object Parsers { // begin paramClause inParens { - val isContextual = impliedMods.is(Given) - if (in.token == RPAREN && !prefix && !isContextual) Nil + if (in.token == RPAREN && !prefix && !impliedMods.is(Given)) Nil else { - def funArgMods(mods: Modifiers): Modifiers = - if (in.token == IMPLICIT && !isContextual) - funArgMods(addMod(mods, atSpan(accept(IMPLICIT)) { Mod.Implicit() })) - else if (in.token == ERASED) - funArgMods(addMod(mods, atSpan(accept(ERASED)) { Mod.Erased() })) - else mods - - impliedMods = funArgMods(impliedMods) + if (in.token == IMPLICIT && !impliedMods.is(Given | Erased)) + impliedMods = addMod(impliedMods, atSpan(accept(IMPLICIT)) { Mod.Implicit() }) val clause = if (prefix) param() :: Nil else commaSeparated(() => param()) @@ -2178,9 +2170,8 @@ object Parsers { } } - /** ClsParamClauses ::= {ClsParamClause} - * DefParamClauses ::= {DefParamClause} - * InferParamClauses ::= {InferParamClause} + /** ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ [‘implicit’] ClsParams ‘)’] + * DefParamClauses ::= {DefParamClause} [[nl] ‘(’ [‘implicit’] DefParams ‘)’] * * @return The parameter definitions */ @@ -2188,12 +2179,15 @@ object Parsers { ofCaseClass: Boolean = false, ofInstance: Boolean = false): List[List[ValDef]] = { def recur(firstClause: Boolean, nparams: Int): List[List[ValDef]] = { - val initialMods = - if (in.token == GIVEN) { - in.nextToken() - Modifiers(Given | Implicit) - } - else EmptyModifiers + var initialMods = EmptyModifiers + if (in.token == GIVEN) { + in.nextToken() + initialMods |= Given | Implicit + } + if (in.token == ERASED) { + in.nextToken() + initialMods |= Erased + } val isContextual = initialMods.is(Given) newLineOptWhenFollowedBy(LPAREN) if (in.token == LPAREN) { @@ -2617,7 +2611,7 @@ object Parsers { } /** InstanceDef ::= [id] InstanceParams InstanceBody - * InstanceParams ::= [DefTypeParamClause] {InferParamClause} + * InstanceParams ::= [DefTypeParamClause] {GivenParamClause} * InstanceBody ::= [‘of’ ConstrApp {‘,’ ConstrApp }] [TemplateBody] * | ‘of’ Type ‘=’ Expr */ @@ -2906,7 +2900,7 @@ object Parsers { else if (isExprIntro) stats += expr(Location.InBlock) else if (isDefIntro(localModifierTokens)) - if (in.token == IMPLICIT || in.token == ERASED || in.token == GIVEN) { + if (closureMods.contains(in.token)) { val start = in.offset var imods = modifiers(closureMods) if (isBindingIntro) diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 95b9f03d867a..9efd80c1424c 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -185,10 +185,10 @@ class PlainPrinter(_ctx: Context) extends Printer { "" case tp: MethodType => changePrec(GlobalPrec) { - (if (tp.isContextual) " given " else "") ~ - ("(" + (if (tp.isErasedMethod) "erased " else "") - + (if (tp.isImplicitMethod && !tp.isContextual) "implicit " else "") - ) ~ paramsText(tp) ~ + (if (tp.isContextual) " given" else "") ~ + (if (tp.isErasedMethod) " erased" else "") ~~ + ("(" + (if (tp.isImplicitMethod && !tp.isContextual) "implicit " else "")) ~ + paramsText(tp) ~ (if (tp.resultType.isInstanceOf[MethodType]) ")" else "): ") ~ toText(tp.resultType) } diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala index db6ee895450e..1056c8df4dca 100644 --- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -136,14 +136,14 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { atPrec(InfixPrec) { argText(args.head) } else toTextTuple(args.init) - (keywordText("erased ") provided isErased) ~ (keywordText("given ") provided isContextual) ~ + (keywordText("erased ") provided isErased) ~ argStr ~ " => " ~ argText(args.last) } def toTextDependentFunction(appType: MethodType): Text = - (keywordText("erased ") provided appType.isErasedMethod) ~ (keywordText("given ") provided appType.isImplicitMethod) ~ + (keywordText("erased ") provided appType.isErasedMethod) ~ "(" ~ paramsText(appType) ~ ") => " ~ toText(appType.resultType) def isInfixType(tp: Type): Boolean = tp match { diff --git a/compiler/test-resources/repl/erased b/compiler/test-resources/repl/erased index 9a67c1963769..878b99dce1a5 100644 --- a/compiler/test-resources/repl/erased +++ b/compiler/test-resources/repl/erased @@ -1,2 +1,2 @@ -scala> def f(erased a: Int): Int = ??? -def f(erased a: Int): Int +scala> def f erased (a: Int): Int = ??? +def f erased (a: Int): Int diff --git a/compiler/test-resources/repl/erased-implicit b/compiler/test-resources/repl/erased-implicit index 652b1e17e7a3..05252ff91aed 100644 --- a/compiler/test-resources/repl/erased-implicit +++ b/compiler/test-resources/repl/erased-implicit @@ -1,2 +1,2 @@ -scala> def f(erased implicit a: Int): Int = ??? -def f(erased implicit a: Int): Int +scala> def f given erased (a: Int): Int = ??? +def f given erased (a: Int): Int diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index bd0eada17306..6381d23ca996 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -290,22 +290,21 @@ HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’ HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (Id[HkTypeParamClause] | ‘_’) SubtypeBounds -ClsParamClauses ::= {ClsParamClause} -ClsParamClause ::= [nl] ‘(’ [[FunArgMods] ClsParams] ‘)’ - | ‘given’ (‘(’ ([[FunArgMods] ClsParams] ‘)’ | ContextTypes) +ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ [‘implicit’] ClsParams ‘)’] +ClsParamClause ::= [nl] [‘erased’] ‘(’ [ClsParams] ‘)’ + | ‘given’ [‘erased’] (‘(’ ClsParams ‘)’ | ContextTypes) ClsParams ::= ClsParam {‘,’ ClsParam} ClsParam ::= {Annotation} ValDef(mods, id, tpe, expr) -- point of mods on val/var [{Modifier} (‘val’ | ‘var’) | ‘inline’] Param Param ::= id ‘:’ ParamType [‘=’ Expr] | INT -DefParamClauses ::= {DefParamClause} [[nl] ‘(’ [FunArgMods] DefParams ‘)’] -DefParamClause ::= [nl] ‘(’ [DefParams] ‘)’ | InferParamClause -InferParamClause ::= ‘given’ (‘(’ [DefParams] ‘)’ | ContextTypes) +DefParamClauses ::= {DefParamClause} [[nl] ‘(’ [‘implicit’] DefParams ‘)’] +DefParamClause ::= [nl] [‘erased’] ‘(’ [DefParams] ‘)’ | GivenParamClause +GivenParamClause ::= ‘given’ [‘erased’] (‘(’ DefParams ‘)’ | ContextTypes) DefParams ::= DefParam {‘,’ DefParam} DefParam ::= {Annotation} [‘inline’] Param ValDef(mods, id, tpe, expr) -- point of mods at id. ContextTypes ::= RefinedType {‘,’ RefinedType} -FunArgMods ::= { ‘implicit’ | ‘erased’ } ClosureMods ::= { ‘implicit’ | ‘erased’ | ‘given’} ``` @@ -379,7 +378,7 @@ ConstrMods ::= {Annotation} [AccessModifier] ObjectDef ::= id [Template] ModuleDef(mods, name, template) // no constructor EnumDef ::= id ClassConstr InheritClauses EnumBody EnumDef(mods, name, tparams, template) InstanceDef ::= [id] InstanceParams InstanceBody -InstanceParams ::= [DefTypeParamClause] {InferParamClause} +InstanceParams ::= [DefTypeParamClause] {GivenParamClause} InstanceBody ::= [‘of’ ConstrApp {‘,’ ConstrApp }] [TemplateBody] | ‘of’ Type ‘=’ Expr Template ::= InheritClauses [TemplateBody] Template(constr, parents, self, stats) diff --git a/docs/docs/reference/other-new-features/erased-terms.md b/docs/docs/reference/other-new-features/erased-terms.md index c5b0981df487..c035f3019ca0 100644 --- a/docs/docs/reference/other-new-features/erased-terms.md +++ b/docs/docs/reference/other-new-features/erased-terms.md @@ -38,10 +38,10 @@ present in some form in the generated code to be able to do separate compilation How to define erased terms? ------------------------------- -Parameters of methods and functions can be declared as erased, placing `erased` at the start of the parameter list (like `implicit`). +Parameters of methods and functions can be declared as erased, placing `erased` in front of a parameter list (like `given`). ```scala -def methodWithErasedEv(erased ev: Ev): Int = 42 +def methodWithErasedEv erased (ev: Ev): Int = 42 val lambdaWithErasedEv: erased Ev => Int = erased (ev: Ev) => 42 @@ -50,10 +50,10 @@ val lambdaWithErasedEv: erased Ev => Int = `erased` parameters will not be usable for computations, though they can be used as arguments to other `erased` parameters. ```scala -def methodWithErasedInt1(erased i: Int): Int = +def methodWithErasedInt1 erased (i: Int): Int = i + 42 // ERROR: can not use i -def methodWithErasedInt2(erased i: Int): Int = +def methodWithErasedInt2 erased (i: Int): Int = methodWithErasedInt1(i) // OK ``` @@ -70,7 +70,7 @@ As `erased` are guaranteed not to be used in computations, they can and will be ```scala // becomes def methodWithErasedEv(): Int at runtime -def methodWithErasedEv(erased ev: Ev): Int = ... +def methodWithErasedEv erased (ev: Ev): Int = ... def evidence1: Ev = ... erased def erasedEvidence2: Ev = ... // does not exist at runtime @@ -83,13 +83,13 @@ methodWithErasedEv(evidence1) State machine with erased evidence example ------------------------------------------ The following example is an extended implementation of a simple state machine which can be in a state `On` or `Off`. -The machine can change state from `Off` to `On` with `turnedOn` only if it is currently `Off`, +The machine can change state from `Off` to `On` with `turnedOn` only if it is currently `Off`, conversely from `On` to `Off` with `turnedOff` only if it is currently `On`. These last constraint are -captured with the `IsOff[S]` and `IsOn[S]` implicit evidence only exist for `IsOff[Off]` and `IsOn[On]`. -For example, not allowing calling `turnedOff` on in an `Off` state as we would require an evidence `IsOn[Off]` +captured with the `IsOff[S]` and `IsOn[S]` implicit evidence only exist for `IsOff[Off]` and `IsOn[On]`. +For example, not allowing calling `turnedOff` on in an `Off` state as we would require an evidence `IsOn[Off]` that will not be found. -As the implicit evidences of `turnedOn` and `turnedOff` are not used in the bodies of those functions +As the implicit evidences of `turnedOn` and `turnedOff` are not used in the bodies of those functions we can mark them as `erased`. This will remove the evidence parameters at runtime, but we would still evaluate the `isOn` and `isOff` implicits that were found as arguments. As `isOn` and `isOff` are not used except as `erased` arguments, we can mark them as `erased`, hence @@ -117,9 +117,9 @@ object IsOn { } class Machine[S <: State] private { - // ev will disapear from both functions - def turnedOn(implicit erased ev: IsOff[S]): Machine[On] = new Machine[On] - def turnedOff(implicit erased ev: IsOn[S]): Machine[Off] = new Machine[Off] + // ev will disappear from both functions + def turnedOn given erased (ev: IsOff[S]): Machine[On] = new Machine[On] + def turnedOff given erased (ev: IsOn[S]): Machine[Off] = new Machine[Off] } object Machine { @@ -156,12 +156,12 @@ Rules erased val x = ... erased def f = ... - def g(erased x: Int) = ... + def g erased (x: Int) = ... - (erased x: Int) => ... + erased (x: Int) => ... def h(x: erased Int => Int) = ... - class K(erased x: Int) { ... } + class K erased (x: Int) { ... } ``` @@ -182,14 +182,14 @@ Rules 4. Eta expansion - if `def f(erased x: T): U` then `f: (erased T) => U`. + if `def f erased (x: T): U` then `f: erased (T) => U`. 5. Erasure Semantics * All `erased` parameters are removed from the function * All argument to `erased` parameters are not passed to the function * All `erased` definitions are removed - * All `(erased T1, T2, ..., TN) => R` and `(given erased T1, T2, ..., TN) => R` become `() => R` + * All ` erased (T1, T2, ..., TN) => R` and `(given erased T1, T2, ..., TN) => R` become `() => R` 6. Overloading @@ -198,6 +198,6 @@ Rules 7. Overriding - * Member definitions overidding each other must both be `erased` or not be `erased` - * `def foo(x: T): U` cannot be overridden by `def foo(erased x: T): U` an viceversa + * Member definitions overriding each other must both be `erased` or not be `erased` + * `def foo(x: T): U` cannot be overridden by `def foo erased (x: T): U` an vice-versa diff --git a/tests/fuzzy/5d506217aaf5e71195b85b12ca59245f35152885.scala b/tests/fuzzy/5d506217aaf5e71195b85b12ca59245f35152885.scala index 2b12dffd735e..193a1d5558fc 100644 --- a/tests/fuzzy/5d506217aaf5e71195b85b12ca59245f35152885.scala +++ b/tests/fuzzy/5d506217aaf5e71195b85b12ca59245f35152885.scala @@ -24,7 +24,7 @@ case List(i4: Int) => } } trait i5 { -def i3(erased i2: Int): Int = 0 +def i3 erased (i2: Int): Int = 0 def i2() = { class i3 } match { case i4 @ i5 => 1 case i6: i7 => i5 _ extends i5 => diff --git a/tests/generic-java-signatures/erased.scala b/tests/generic-java-signatures/erased.scala index a9731cc748fb..f22b6dc4699f 100644 --- a/tests/generic-java-signatures/erased.scala +++ b/tests/generic-java-signatures/erased.scala @@ -1,5 +1,5 @@ object MyErased { - def f1[U](erased a: Int): Int = 0 + def f1[U] erased (a: Int): Int = 0 } object Test { diff --git a/tests/neg/erased-1.scala b/tests/neg/erased-1.scala index 552d2cc7e086..7bb4cb95d826 100644 --- a/tests/neg/erased-1.scala +++ b/tests/neg/erased-1.scala @@ -1,6 +1,6 @@ object Test { def foo0(a: Int): Int = a - def foo1(erased a: Int): Int = { + def foo1 erased (a: Int): Int = { foo0( a // error ) @@ -24,7 +24,7 @@ object Test { foo3(a) // OK a // OK } - erased def foo3(erased a: Int): Int = { + erased def foo3 erased (a: Int): Int = { foo0(a) // OK foo1(a) // OK foo2(a) // OK diff --git a/tests/neg/erased-2.scala b/tests/neg/erased-2.scala index bab269061899..db7b46f34cec 100644 --- a/tests/neg/erased-2.scala +++ b/tests/neg/erased-2.scala @@ -1,6 +1,6 @@ object Test { def foo0(a: Int): Int = a - def foo1(erased a: Int): Int = { + def foo1 erased (a: Int): Int = { foo0( u // error ) @@ -22,7 +22,7 @@ object Test { u // warn u // OK } - erased def foo3(erased a: Int): Int = { + erased def foo3 erased (a: Int): Int = { foo0(u) // OK foo1(u) // OK foo2(u) // OK diff --git a/tests/neg/erased-24.scala b/tests/neg/erased-24.scala index dc39d4f9b653..3042ef29604e 100644 --- a/tests/neg/erased-24.scala +++ b/tests/neg/erased-24.scala @@ -6,11 +6,11 @@ object Test { println(fun(new Bar)) } - def fun(erased foo: Foo): foo.X = { // ok + def fun erased (foo: Foo): foo.X = { // ok null.asInstanceOf[foo.X] // ok } - def fun2(erased foo: Foo)(erased bar: foo.B): bar.X = { // error + def fun2 erased (foo: Foo) erased (bar: foo.B): bar.X = { // error null.asInstanceOf[bar.X] // error } } diff --git a/tests/neg/erased-3.scala b/tests/neg/erased-3.scala index 3858208afc2a..9654b91cca03 100644 --- a/tests/neg/erased-3.scala +++ b/tests/neg/erased-3.scala @@ -1,6 +1,6 @@ object Test { def foo0(a: Int): Int = a - def foo1(erased a: Int): Int = { + def foo1 erased (a: Int): Int = { foo0( u() // error ) @@ -22,7 +22,7 @@ object Test { u() // warn u() // OK } - erased def foo3(erased a: Int): Int = { + erased def foo3 erased (a: Int): Int = { foo0(u()) // OK foo1(u()) // OK foo2(u()) // OK diff --git a/tests/neg/erased-4.scala b/tests/neg/erased-4.scala index 2c60ad303dae..6f357ccb92b8 100644 --- a/tests/neg/erased-4.scala +++ b/tests/neg/erased-4.scala @@ -1,7 +1,7 @@ object Test { def main(args: Array[String]): Unit = { - def foo (erased i: Int) = 0 + def foo erased (i: Int) = 0 val f: erased Int => Int = erased (x: Int) => { diff --git a/tests/neg/erased-assign.scala b/tests/neg/erased-assign.scala index 5f1bd9250e84..28b4a242ae81 100644 --- a/tests/neg/erased-assign.scala +++ b/tests/neg/erased-assign.scala @@ -1,6 +1,6 @@ object Test { var i: Int = 1 - def foo(erased a: Int): Int = { + def foo erased (a: Int): Int = { i = a // error erased def r = { i = a diff --git a/tests/neg/erased-case-class.scala b/tests/neg/erased-case-class.scala index 692534d772b6..1d1458b7453d 100644 --- a/tests/neg/erased-case-class.scala +++ b/tests/neg/erased-case-class.scala @@ -1 +1 @@ -case class Foo1(erased x: Int) // error // error +case class Foo1 erased (x: Int) // error // error diff --git a/tests/neg/erased-def-rhs.scala b/tests/neg/erased-def-rhs.scala index 23417583f860..8afaa5a72c44 100644 --- a/tests/neg/erased-def-rhs.scala +++ b/tests/neg/erased-def-rhs.scala @@ -1,5 +1,5 @@ object Test { - def f(erased i: Int) = { + def f erased (i: Int) = { def j: Int = i // error j } diff --git a/tests/neg/erased-if-else.scala b/tests/neg/erased-if-else.scala index 503dfc0bd1e3..032b8d735802 100644 --- a/tests/neg/erased-if-else.scala +++ b/tests/neg/erased-if-else.scala @@ -1,6 +1,6 @@ object Test { var b = true - def foo(erased a: Boolean): Boolean = { + def foo erased (a: Boolean): Boolean = { if (a) // error true else diff --git a/tests/neg/erased-match.scala b/tests/neg/erased-match.scala index 2d8057519bfc..668ba905703d 100644 --- a/tests/neg/erased-match.scala +++ b/tests/neg/erased-match.scala @@ -1,6 +1,6 @@ object Test { var b = true - def foo(erased a: Int): Int = { + def foo erased (a: Int): Int = { a match { // error case _ => } diff --git a/tests/neg/erased-pathdep-1.scala b/tests/neg/erased-pathdep-1.scala index 027a08e29582..a930ff2f18db 100644 --- a/tests/neg/erased-pathdep-1.scala +++ b/tests/neg/erased-pathdep-1.scala @@ -6,9 +6,9 @@ object Test { fun2(new Bar) fun3(new Bar) - def fun1[F >: Bar <: Foo](erased f: F): f.X = null.asInstanceOf[f.X] // error // error - def fun2[F >: Bar <: Foo](erased f: F)(erased bar: f.B): f.B = null.asInstanceOf[f.B] // error // error // error - def fun3[F >: Bar <: Foo](erased f: F)(erased b: f.B): b.X = null.asInstanceOf[b.X] // error // error // error + def fun1[F >: Bar <: Foo] erased (f: F): f.X = null.asInstanceOf[f.X] // error // error + def fun2[F >: Bar <: Foo] erased (f: F) erased (bar: f.B): f.B = null.asInstanceOf[f.B] // error // error // error + def fun3[F >: Bar <: Foo] erased (f: F) erased (b: f.B): b.X = null.asInstanceOf[b.X] // error // error // error } class Foo { diff --git a/tests/neg/erased-pathdep-2.scala b/tests/neg/erased-pathdep-2.scala index 29dcf216b32e..0c8c5afbaa70 100644 --- a/tests/neg/erased-pathdep-2.scala +++ b/tests/neg/erased-pathdep-2.scala @@ -4,7 +4,7 @@ object Test { type F >: Bar <: Foo - class A(erased val f: F) { + class A erased (val f: F) { type F1 <: f.X // error type F2[Z <: f.X] // error } diff --git a/tests/neg/erased-return.scala b/tests/neg/erased-return.scala index f7cf15a079be..b87394d4a7c8 100644 --- a/tests/neg/erased-return.scala +++ b/tests/neg/erased-return.scala @@ -1,6 +1,6 @@ object Test { var b = true - def foo(erased a: Int): Int = { + def foo erased (a: Int): Int = { if (b) return a // error else diff --git a/tests/neg/erased-try.scala b/tests/neg/erased-try.scala index 3e9aae8ab9a4..7f748a685664 100644 --- a/tests/neg/erased-try.scala +++ b/tests/neg/erased-try.scala @@ -1,12 +1,12 @@ object Test { - def foo(erased a: Int): Int = { + def foo erased (a: Int): Int = { try { a // error } catch { case _ => 42 } } - def foo2(erased a: Int): Int = { + def foo2 erased (a: Int): Int = { try { 42 } catch { diff --git a/tests/neg/erased-val-rhs.scala b/tests/neg/erased-val-rhs.scala index 1b904c671478..afc65789b664 100644 --- a/tests/neg/erased-val-rhs.scala +++ b/tests/neg/erased-val-rhs.scala @@ -1,5 +1,5 @@ object Test { - def f(erased i: Int) = { + def f erased (i: Int) = { val j: Int = i // error () } diff --git a/tests/neg/erased-value-class.scala b/tests/neg/erased-value-class.scala index 65cd3e2f961b..95d707bd34c0 100644 --- a/tests/neg/erased-value-class.scala +++ b/tests/neg/erased-value-class.scala @@ -1,4 +1,4 @@ -class Foo(erased x: Int) extends AnyVal // error +class Foo erased (x: Int) extends AnyVal // error class Bar(x: Int)(y: Int) extends AnyVal // error diff --git a/tests/neg/i4060.scala b/tests/neg/i4060.scala index 3d5c180b5d7b..0e2664e51ec4 100644 --- a/tests/neg/i4060.scala +++ b/tests/neg/i4060.scala @@ -1,12 +1,12 @@ class X { type R } -class T(erased val a: X)(val value: a.R) +class T erased (val a: X)(val value: a.R) object App { def coerce[U, V](u: U): V = { trait X { type R >: U } trait Y { type R = V } - class T[A <: X](erased val a: A)(val value: a.R) // error + class T[A <: X] erased (val a: A)(val value: a.R) // error object O { lazy val x : Y & X = ??? } diff --git a/tests/pos/erased-args-lifted.scala b/tests/pos/erased-args-lifted.scala index faa07cdcb0b5..03b78ec84a1f 100644 --- a/tests/pos/erased-args-lifted.scala +++ b/tests/pos/erased-args-lifted.scala @@ -1,5 +1,5 @@ object Test { - def foo(erased a: Int)(b: Int, c: Int) = 42 + def foo erased (a: Int)(b: Int, c: Int) = 42 def bar(i: Int): Int = { println(1) 42 diff --git a/tests/pos/erased-asInstanceOf.scala b/tests/pos/erased-asInstanceOf.scala index 956e325646d9..57996aab961e 100644 --- a/tests/pos/erased-asInstanceOf.scala +++ b/tests/pos/erased-asInstanceOf.scala @@ -1,6 +1,6 @@ trait Dataset { - def select(erased c: Column): Unit = () + def select erased (c: Column): Unit = () } class Column diff --git a/tests/pos/erased-deep-context.scala b/tests/pos/erased-deep-context.scala index 049bf14c2e4f..93b971456713 100644 --- a/tests/pos/erased-deep-context.scala +++ b/tests/pos/erased-deep-context.scala @@ -1,12 +1,12 @@ object Test { def outer1(): Int = { - def inner(erased a: Int): Int = 0 + def inner erased (a: Int): Int = 0 inner(42) } def outer2(): Int = { - def inner(erased b: Int): Int = { - def inner2(erased a: Int): Int = 0 + def inner erased (b: Int): Int = { + def inner2 erased (a: Int): Int = 0 inner2(b) } inner(42) diff --git a/tests/pos/erased-extension-method.scala b/tests/pos/erased-extension-method.scala index 7ef14d65e4a4..6b56f5ee46dc 100644 --- a/tests/pos/erased-extension-method.scala +++ b/tests/pos/erased-extension-method.scala @@ -1,3 +1,3 @@ class IntDeco(x: Int) extends AnyVal { - def foo(erased y: Int) = x + def foo erased (y: Int) = x } diff --git a/tests/pos/phantom-Eq.scala b/tests/pos/phantom-Eq.scala index 3a500123a754..c3f7f9b8642a 100644 --- a/tests/pos/phantom-Eq.scala +++ b/tests/pos/phantom-Eq.scala @@ -18,7 +18,7 @@ object EqUtil { type PhantomEqEq[T] = PhantomEq[T, T] implicit class EqualsDeco[T](val x: T) extends AnyVal { - def ===[U] (y: U)(implicit erased ce: PhantomEq[T, U]) = x.equals(y) + def ===[U] (y: U) given erased (ce: PhantomEq[T, U]) = x.equals(y) } implicit erased def eqString: PhantomEqEq[String] = ??? @@ -28,5 +28,5 @@ object EqUtil { implicit erased def eqByteNum: PhantomEq[Byte, Number] = ??? implicit erased def eqNumByte: PhantomEq[Number, Byte] = ??? - implicit erased def eqSeq[T, U](implicit erased eq: PhantomEq[T, U]): PhantomEq[Seq[T], Seq[U]] = ??? + implicit erased def eqSeq[T, U] given erased (eq: PhantomEq[T, U]): PhantomEq[Seq[T], Seq[U]] = ??? } diff --git a/tests/pos/phantom-Eq2/Phantom-Eq_1.scala b/tests/pos/phantom-Eq2/Phantom-Eq_1.scala index be61e817eb99..ec5bbe489952 100644 --- a/tests/pos/phantom-Eq2/Phantom-Eq_1.scala +++ b/tests/pos/phantom-Eq2/Phantom-Eq_1.scala @@ -6,7 +6,7 @@ object EqUtil { type PhantomEqEq[T] = PhantomEq[T, T] implicit class EqualsDeco[T](val x: T) extends AnyVal { - def ===[U] (y: U)(implicit erased ce: PhantomEq[T, U]) = x.equals(y) + def ===[U] (y: U) given erased (ce: PhantomEq[T, U]) = x.equals(y) } implicit erased def eqString: PhantomEqEq[String] = new PhantomEq[String, String] @@ -16,6 +16,6 @@ object EqUtil { implicit erased def eqByteNum: PhantomEq[Byte, Number] = new PhantomEq[Byte, Number] implicit erased def eqNumByte: PhantomEq[Number, Byte] = new PhantomEq[Number, Byte] - implicit erased def eqSeq[T, U](implicit erased eq: PhantomEq[T, U]): PhantomEq[Seq[T], Seq[U]] = + implicit erased def eqSeq[T, U] given erased (eq: PhantomEq[T, U]): PhantomEq[Seq[T], Seq[U]] = new PhantomEq[Seq[T], Seq[U]] } diff --git a/tests/pos/phantom-Evidence.scala b/tests/pos/phantom-Evidence.scala index 37ce544dfbcf..f2f9500a0271 100644 --- a/tests/pos/phantom-Evidence.scala +++ b/tests/pos/phantom-Evidence.scala @@ -10,8 +10,8 @@ object WithNormalState { def newInstance(): Instance[Off] = new Instance[Off] } class Instance[S <: State] private { - def getOnInstance(implicit erased ev: S =::= Off): Instance[On] = new Instance[On] // phantom parameter ev is erased - def getOffInstance(implicit erased ev: S =::= On): Instance[Off] = new Instance[Off] // phantom parameter ev is erased + def getOnInstance given erased (ev: S =::= Off): Instance[On] = new Instance[On] // phantom parameter ev is erased + def getOffInstance given erased (ev: S =::= On): Instance[Off] = new Instance[Off] // phantom parameter ev is erased } def run() = { diff --git a/tests/run/erased-1.scala b/tests/run/erased-1.scala index acb8ce68f9bf..f1f62cdd3706 100644 --- a/tests/run/erased-1.scala +++ b/tests/run/erased-1.scala @@ -8,7 +8,7 @@ object Test { println("foo") 42 } - def fun(erased boo: Int): Unit = { + def fun erased (boo: Int): Unit = { println("fun") } } diff --git a/tests/run/erased-10.scala b/tests/run/erased-10.scala index 25c86c0267c8..78a55cc058ef 100644 --- a/tests/run/erased-10.scala +++ b/tests/run/erased-10.scala @@ -4,7 +4,7 @@ object Test { fun2.pacFun4(inky) } - def pacFun4(erased clyde: Int) = { + def pacFun4 erased (clyde: Int) = { println("pacFun4") } diff --git a/tests/run/erased-11.scala b/tests/run/erased-11.scala index 36a8d08f8d7f..1419cd381f08 100644 --- a/tests/run/erased-11.scala +++ b/tests/run/erased-11.scala @@ -8,17 +8,17 @@ object Test { (new Fun2().fun)({ println("z1"); boo })({ println("z2"); boo }) } - def fun(erased x1: Int)(erased x2: Int) = { + def fun erased (x1: Int) erased (x2: Int) = { println("fun") } - class Fun(erased y1: Int)(erased y2: Int) { + class Fun erased (y1: Int) erased (y2: Int) { println("Fun") } class Fun2 { println("Fun2") - def fun(erased z1: Int)(erased z2: Int) = { + def fun erased (z1: Int) erased (z2: Int) = { println("Fun2fun") } } diff --git a/tests/run/erased-12.scala b/tests/run/erased-12.scala index cde677050dd6..202eba7232c2 100644 --- a/tests/run/erased-12.scala +++ b/tests/run/erased-12.scala @@ -12,6 +12,6 @@ object Test { } -case class Foo(a: Int)(erased b: Int) { +case class Foo(a: Int) erased (b: Int) { println("Foo") } diff --git a/tests/run/erased-13.scala b/tests/run/erased-13.scala index 442a3eab4c01..c6687f886ccf 100644 --- a/tests/run/erased-13.scala +++ b/tests/run/erased-13.scala @@ -8,7 +8,7 @@ object Test { foo(x) } - def foo(erased a: Int) = { + def foo erased (a: Int) = { println("foo") } diff --git a/tests/run/erased-15.scala b/tests/run/erased-15.scala index b879ee4c54d8..a850e9b5cc7b 100644 --- a/tests/run/erased-15.scala +++ b/tests/run/erased-15.scala @@ -11,7 +11,7 @@ object Test { } class Foo extends ErasedFunction1[Int, Int] { - def apply(erased x: Int): Int = { + def apply erased (x: Int): Int = { println("Foo.apply") 42 } diff --git a/tests/run/erased-16.scala b/tests/run/erased-16.scala index 879af76765b7..f38f13244dd2 100644 --- a/tests/run/erased-16.scala +++ b/tests/run/erased-16.scala @@ -11,11 +11,11 @@ object Test { } class Foo { - def foo(erased x: Int): Int = 42 + def foo erased (x: Int): Int = 42 } class Bar extends Foo { - override def foo(erased x: Int): Int = { + override def foo erased (x: Int): Int = { println("Bar.foo") 42 } diff --git a/tests/run/erased-2.scala b/tests/run/erased-2.scala index 20d89990b362..b0f550790d14 100644 --- a/tests/run/erased-2.scala +++ b/tests/run/erased-2.scala @@ -12,7 +12,7 @@ object Test { } } - def fun(erased bottom: Nothing): Unit = { + def fun erased (bottom: Nothing): Unit = { println("fun") } } diff --git a/tests/run/erased-22.scala b/tests/run/erased-22.scala index ae6ed279b0ca..94366dc28e50 100644 --- a/tests/run/erased-22.scala +++ b/tests/run/erased-22.scala @@ -10,7 +10,7 @@ object Test { println("foo") 42 } - def fun1(implicit erased boo: Int): Int = { + def fun1 given erased (boo: Int): Int = { println("fun1") 43 } diff --git a/tests/run/erased-25.scala b/tests/run/erased-25.scala index 97a85dd1460d..9bc7e4d08063 100644 --- a/tests/run/erased-25.scala +++ b/tests/run/erased-25.scala @@ -6,5 +6,5 @@ object Test { } class Dataset { - def select[A](erased c: Boolean): String = "abc" + def select[A] erased (c: Boolean): String = "abc" } diff --git a/tests/run/erased-26.scala b/tests/run/erased-26.scala index eed903ac2753..b95ce5036449 100644 --- a/tests/run/erased-26.scala +++ b/tests/run/erased-26.scala @@ -2,5 +2,5 @@ object Test { def main(args: Array[String]): Unit = { col("abc")(true) } - def col[S](s: String)(erased ev: Boolean): Unit = println(s) + def col[S](s: String) erased (ev: Boolean): Unit = println(s) } diff --git a/tests/run/erased-27.scala b/tests/run/erased-27.scala index 68b551520daa..4371190c49e3 100644 --- a/tests/run/erased-27.scala +++ b/tests/run/erased-27.scala @@ -5,7 +5,7 @@ object Test { foo })(x) } - def foo(erased a: Int): Unit = { + def foo erased (a: Int): Unit = { println("foo") } def x: Int = { diff --git a/tests/run/erased-28.scala b/tests/run/erased-28.scala index 8b916b810dff..d8ba2ea19a9a 100644 --- a/tests/run/erased-28.scala +++ b/tests/run/erased-28.scala @@ -5,10 +5,10 @@ object Test { a = false (if (a) foo else bar)(x) } - def foo(erased a: Int): Unit = { + def foo erased (a: Int): Unit = { println("foo") } - def bar(erased a: Int): Unit = { + def bar erased (a: Int): Unit = { println("bar") } def x: Int = { diff --git a/tests/run/erased-3.scala b/tests/run/erased-3.scala index 68d2f8b629c2..10143311a956 100644 --- a/tests/run/erased-3.scala +++ b/tests/run/erased-3.scala @@ -14,7 +14,7 @@ object Test { "abc" } - def fun(erased a: Int)(erased b: String): Unit = { + def fun erased (a: Int) erased (b: String): Unit = { println("fun") } diff --git a/tests/run/erased-4.scala b/tests/run/erased-4.scala index 8725a7ebc00f..c2c5e9c00000 100644 --- a/tests/run/erased-4.scala +++ b/tests/run/erased-4.scala @@ -15,11 +15,11 @@ object Test { "abc" } - def fun(a: Int)(erased b: String): Unit = { + def fun(a: Int) erased (b: String): Unit = { println("fun " + a) } - def fun2(erased a: Int)(b: String): Unit = { + def fun2 erased (a: Int)(b: String): Unit = { println("fun2 " + b) } } diff --git a/tests/run/erased-5.scala b/tests/run/erased-5.scala index 043d1a4781a7..24d26718e8cf 100644 --- a/tests/run/erased-5.scala +++ b/tests/run/erased-5.scala @@ -10,11 +10,11 @@ object Test { i } - def fun(a: Int)(erased b: Int)(c: Int)(erased d: Int): Unit = { + def fun(a: Int) erased (b: Int)(c: Int) erased (d: Int): Unit = { println("fun " + a + " " + c) } - def fun2(erased a2: Int)(b2: Int)(erased c2: Int)(d2: Int): Unit = { + def fun2 erased (a2: Int)(b2: Int) erased (c2: Int)(d2: Int): Unit = { println("fun2 " + b2 + " " + d2) } } diff --git a/tests/run/erased-6.scala b/tests/run/erased-6.scala index ec113fbb426b..40ae3fa28bcd 100644 --- a/tests/run/erased-6.scala +++ b/tests/run/erased-6.scala @@ -11,6 +11,6 @@ object Test { } -class Foo(erased a: Int) { +class Foo erased (a: Int) { println("Foo") } diff --git a/tests/run/erased-7.scala b/tests/run/erased-7.scala index 6027c2e1572c..49a0d9cdf544 100644 --- a/tests/run/erased-7.scala +++ b/tests/run/erased-7.scala @@ -1,7 +1,7 @@ object Test { def main(args: Array[String]): Unit = { - def f(erased i: Int) = { + def f erased (i: Int) = { new Foo(i)(foo) } f(5) @@ -14,6 +14,6 @@ object Test { } -class Foo(erased a: Int)(b: Int) { +class Foo erased (a: Int)(b: Int) { println("Foo") } diff --git a/tests/run/erased-8.scala b/tests/run/erased-8.scala index afa637e709ef..040fadded893 100644 --- a/tests/run/erased-8.scala +++ b/tests/run/erased-8.scala @@ -1,7 +1,7 @@ object Test { def main(args: Array[String]): Unit = { - def f(erased i: Int) = { + def f erased (i: Int) = { new Foo(foo)(i) } f(foo) @@ -14,6 +14,6 @@ object Test { } -class Foo(a: Int)(erased b: Int) { +class Foo(a: Int) erased (b: Int) { println("Foo") } diff --git a/tests/run/erased-9.scala b/tests/run/erased-9.scala index a989bce068a2..81e856437191 100644 --- a/tests/run/erased-9.scala +++ b/tests/run/erased-9.scala @@ -9,7 +9,7 @@ object Test { 42 } - def fun[T](erased x: T): Unit = { + def fun[T] erased (x: T): Unit = { println("fun") } } diff --git a/tests/run/erased-frameless.scala b/tests/run/erased-frameless.scala index 2f6c6ebe3d68..849b50f583fc 100644 --- a/tests/run/erased-frameless.scala +++ b/tests/run/erased-frameless.scala @@ -26,7 +26,7 @@ trait Dataset[T] { // Use c.label to do an untyped select on actual Spark Dataset, and // cast the result to TypedDataset[A] - def col[S <: String, A](s: S)(implicit erased ev: Exists[T, s.type, A]) = + def col[S <: String, A](s: S) given erased (ev: Exists[T, s.type, A]) = new Column[T, A](s) // ev is only here to check than this is safe, it's never used at runtime! def collect(): Vector[T] diff --git a/tests/run/erased-machine-state.scala b/tests/run/erased-machine-state.scala index 241bc9959903..0b759cd84527 100644 --- a/tests/run/erased-machine-state.scala +++ b/tests/run/erased-machine-state.scala @@ -23,11 +23,11 @@ object IsOn { } class Machine[S <: State] private { - def turnedOn(implicit erased s: IsOff[S]): Machine[On] = { + def turnedOn given erased (s: IsOff[S]): Machine[On] = { println("turnedOn") new Machine[On] } - def turnedOff(implicit erased s: IsOn[S]): Machine[Off] = { + def turnedOff given erased (s: IsOn[S]): Machine[Off] = { println("turnedOff") new Machine[Off] } diff --git a/tests/run/erased-poly-ref.scala b/tests/run/erased-poly-ref.scala index 9f0d3c38d417..fb43a72ef2b1 100644 --- a/tests/run/erased-poly-ref.scala +++ b/tests/run/erased-poly-ref.scala @@ -4,9 +4,9 @@ object Test { fun(foo(bar(5))(bar(6))) } - def fun(erased a: Int): Unit = println("fun") + def fun erased (a: Int): Unit = println("fun") - def foo[P](erased x: Int)(erased y: Int): Int = 0 + def foo[P] erased (x: Int) erased (y: Int): Int = 0 def bar(x: Int) = { println(x) diff --git a/tests/run/erased-select-prefix.scala b/tests/run/erased-select-prefix.scala index 718779ccdcfb..985f6c8258f2 100644 --- a/tests/run/erased-select-prefix.scala +++ b/tests/run/erased-select-prefix.scala @@ -25,7 +25,7 @@ object Test { () } - def bar(erased i: Int): Unit = () + def bar erased (i: Int): Unit = () erased def foo0: Int = 0 erased def foo1(): Int = 1 diff --git a/tests/run/erased-value-class.scala b/tests/run/erased-value-class.scala index a87b0e8bf4af..ce07dd1d9a90 100644 --- a/tests/run/erased-value-class.scala +++ b/tests/run/erased-value-class.scala @@ -11,6 +11,6 @@ object Test { } } -class Bar(x: Int)(erased y: Int) extends AnyVal { +class Bar(x: Int) erased (y: Int) extends AnyVal { def foo() = x } diff --git a/tests/run/phantom-OnHList.scala b/tests/run/phantom-OnHList.scala index 5c6e76aac08e..889083ac3353 100644 --- a/tests/run/phantom-OnHList.scala +++ b/tests/run/phantom-OnHList.scala @@ -77,7 +77,7 @@ trait Appender[L1 <: HList, L2 <: HList] { } object Appender { - implicit def lowLevelAppender[L1 <: HList, L2 <: HList, O <: HList](implicit erased p: PhantomAppender.Aux[L1, L2, O]): Appender[L1, L2] { type Out = O } = + implicit def lowLevelAppender[L1 <: HList, L2 <: HList, O <: HList] given erased (p: PhantomAppender.Aux[L1, L2, O]): Appender[L1, L2] { type Out = O } = new Appender[L1, L2] { type Out = O def apply(l1: L1, l2: L2): Out = HListN(Array.concat(l1.underlying, l2.underlying)).asInstanceOf[O] @@ -89,5 +89,5 @@ object Appender { object PhantomAppender { type Aux[L1 <: HList, L2 <: HList, O <: HList] implicit erased def caseHNil[L <: HList]: Aux[HNil, L, L] = ??? - implicit erased def caseHCons[H, T <: HList, L <: HList, O <: HList](implicit erased p: Aux[T, L, O]): Aux[H :: T, L, H :: O] = ??? + implicit erased def caseHCons[H, T <: HList, L <: HList, O <: HList] given erased (p: Aux[T, L, O]): Aux[H :: T, L, H :: O] = ??? } From 9097a3a20c1e613dc549750d9da34494c7fae3f2 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 10 Apr 2019 15:25:04 +0000 Subject: [PATCH 2/4] Fix reflect-printing of `given` and `erased` flags --- .../tools/dotc/tastyreflect/KernelImpl.scala | 2 ++ .../src/scala/tasty/reflect/FlagsOps.scala | 8 ++++- library/src/scala/tasty/reflect/Kernel.scala | 2 ++ .../src/scala/tasty/reflect/Printers.scala | 36 +++++++++++-------- tests/neg/erased-implicit.scala | 2 ++ 5 files changed, 34 insertions(+), 16 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala index a6bc87b6833b..a5ab89fab09b 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala @@ -1647,6 +1647,7 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util. /** Intersection of the two flag sets */ def Flags_and(self: Flags)(that: Flags): Flags = self & that + def Flags_EmptyFlags: Flags = core.Flags.EmptyFlags def Flags_Private: Flags = core.Flags.Private def Flags_Protected: Flags = core.Flags.Protected def Flags_Abstract: Flags = core.Flags.Abstract @@ -1654,6 +1655,7 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util. def Flags_Sealed: Flags = core.Flags.Sealed def Flags_Case: Flags = core.Flags.Case def Flags_Implicit: Flags = core.Flags.Implicit + def Flags_Given: Flags = core.Flags.Given def Flags_Implied: Flags = core.Flags.Implied def Flags_Erased: Flags = core.Flags.Erased def Flags_Lazy: Flags = core.Flags.Lazy diff --git a/library/src/scala/tasty/reflect/FlagsOps.scala b/library/src/scala/tasty/reflect/FlagsOps.scala index 0b52f1a3a416..c0c97fe688d0 100644 --- a/library/src/scala/tasty/reflect/FlagsOps.scala +++ b/library/src/scala/tasty/reflect/FlagsOps.scala @@ -17,6 +17,9 @@ trait FlagsOps extends Core { object Flags { + /** The empty set of flags */ + def EmptyFlags = kernel.Flags_EmptyFlags + /** Is this symbol `private` */ def Private: Flags = kernel.Flags_Private @@ -38,7 +41,10 @@ trait FlagsOps extends Core { /** Is this symbol `implicit` */ def Implicit: Flags = kernel.Flags_Implicit - /** Is this symbol `erased` */ + /** Is this symbol an inferable ("given") parameter */ + def Given: Flags = kernel.Flags_Given + + /** Is this symbol `erased` */ def Erased: Flags = kernel.Flags_Erased /** Is this symbol `lazy` */ diff --git a/library/src/scala/tasty/reflect/Kernel.scala b/library/src/scala/tasty/reflect/Kernel.scala index 07836b68054f..428caecf7fcc 100644 --- a/library/src/scala/tasty/reflect/Kernel.scala +++ b/library/src/scala/tasty/reflect/Kernel.scala @@ -1338,6 +1338,7 @@ trait Kernel { /** Intersection of the two flag sets */ def Flags_and(self: Flags)(that: Flags): Flags + def Flags_EmptyFlags: Flags def Flags_Private: Flags def Flags_Protected: Flags def Flags_Abstract: Flags @@ -1345,6 +1346,7 @@ trait Kernel { def Flags_Sealed: Flags def Flags_Case: Flags def Flags_Implicit: Flags + def Flags_Given: Flags def Flags_Implied: Flags def Flags_Erased: Flags def Flags_Lazy: Flags diff --git a/library/src/scala/tasty/reflect/Printers.scala b/library/src/scala/tasty/reflect/Printers.scala index ead0bffba496..a97a179c3ca1 100644 --- a/library/src/scala/tasty/reflect/Printers.scala +++ b/library/src/scala/tasty/reflect/Printers.scala @@ -1203,24 +1203,30 @@ trait Printers } } - def printArgsDefs(args: List[ValDef])(implicit elideThis: Option[Symbol]): Unit = inParens { - args match { - case Nil => - case arg :: _ => - if (arg.symbol.flags.is(Flags.Erased)) this += "erased " - if (arg.symbol.flags.is(Flags.Implicit)) this += "implicit " + def printArgsDefs(args: List[ValDef])(implicit elideThis: Option[Symbol]): Unit = { + val argFlags = args match { + case Nil => Flags.EmptyFlags + case arg :: _ => arg.symbol.flags } - - def printSeparated(list: List[ValDef]): Unit = list match { - case Nil => - case x :: Nil => printParamDef(x) - case x :: xs => - printParamDef(x) - this += ", " - printSeparated(xs) + if (argFlags.is(Flags.Erased | Flags.Given)) { + if (argFlags.is(Flags.Given)) this += " given" + if (argFlags.is(Flags.Erased)) this += " erased" + this += " " } + inParens { + if (argFlags.is(Flags.Implicit) && !argFlags.is(Flags.Given)) this += "implicit " - printSeparated(args) + def printSeparated(list: List[ValDef]): Unit = list match { + case Nil => + case x :: Nil => printParamDef(x) + case x :: xs => + printParamDef(x) + this += ", " + printSeparated(xs) + } + + printSeparated(args) + } } def printAnnotations(trees: List[Term])(implicit elideThis: Option[Symbol]): Buffer = { diff --git a/tests/neg/erased-implicit.scala b/tests/neg/erased-implicit.scala index ecfdc24a6cdf..0542086bb285 100644 --- a/tests/neg/erased-implicit.scala +++ b/tests/neg/erased-implicit.scala @@ -5,4 +5,6 @@ object Test { def fun(implicit a: Double): Int = 42 erased implicit def doubleImplicit: Double = 42.0 + + def foo erased (implicit a: Double) = 42 // error } From 9fd12cfd56a493ef21a8f82f7f604d2483916cfb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 10 Apr 2019 15:29:58 +0000 Subject: [PATCH 3/4] Drop ERASEDIMPLICITMETHODtype in TastyFormat `erased` parameters cannot be (old style) `implicit` anymore. --- compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala | 6 ++---- compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala | 3 +-- .../src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 2 -- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index e853ded1ad13..cd614e6ca2ff 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -432,7 +432,6 @@ object TastyFormat { final val CONTEXTUALMETHODtype = 182 final val ERASEDCONTEXTUALMETHODtype = 183 final val IMPLICITMETHODtype = 184 - final val ERASEDIMPLICITMETHODtype = 185 final val MATCHtype = 190 final val MATCHtpt = 191 @@ -440,7 +439,7 @@ object TastyFormat { def methodType(isContextual: Boolean, isImplicit: Boolean, isErased: Boolean): Int = { val implicitOffset = if (isContextual) 2 - else if (isImplicit) 4 + else if (isImplicit) { assert(!isErased); 4 } else 0 val erasedOffset = if (isErased) 1 else 0 METHODtype + erasedOffset + implicitOffset @@ -650,7 +649,6 @@ object TastyFormat { case CONTEXTUALMETHODtype => "CONTEXTUALMETHODtype" case ERASEDCONTEXTUALMETHODtype => "ERASEDCONTEXTUALMETHODtype" case IMPLICITMETHODtype => "IMPLICITMETHODtype" - case ERASEDIMPLICITMETHODtype => "ERASEDIMPLICITMETHODtype" case TYPELAMBDAtype => "TYPELAMBDAtype" case LAMBDAtpt => "LAMBDAtpt" case MATCHtype => "MATCHtype" @@ -672,7 +670,7 @@ object TastyFormat { case POLYtype | TYPELAMBDAtype | METHODtype | ERASEDMETHODtype | CONTEXTUALMETHODtype | ERASEDCONTEXTUALMETHODtype | - IMPLICITMETHODtype | ERASEDIMPLICITMETHODtype => -1 + IMPLICITMETHODtype => -1 case _ => 0 } } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala index 1f9bd7f351a5..ff01883ad44e 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala @@ -86,8 +86,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { printNat(); printTrees() case METHODtype | ERASEDMETHODtype | CONTEXTUALMETHODtype | ERASEDCONTEXTUALMETHODtype | - IMPLICITMETHODtype | ERASEDIMPLICITMETHODtype | - POLYtype | TYPELAMBDAtype => + IMPLICITMETHODtype | POLYtype | TYPELAMBDAtype => printTree() until(end) { printName(); printTree() } case PARAMtype => diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index d4e92bcdd973..3cc2389de2ca 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -357,8 +357,6 @@ class TreeUnpickler(reader: TastyReader, readMethodic(ErasedContextualMethodType, _.toTermName) case IMPLICITMETHODtype => readMethodic(ImplicitMethodType, _.toTermName) - case ERASEDIMPLICITMETHODtype => - readMethodic(ErasedImplicitMethodType, _.toTermName) case TYPELAMBDAtype => readMethodic(HKTypeLambda, _.toTypeName) case PARAMtype => From 6687e2c01ed71274f112c5ad3090817e0ebe8e37 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Thu, 11 Apr 2019 09:39:44 +0200 Subject: [PATCH 4/4] Split neg test that emits errors in two phases --- tests/neg/erased-implicit-b.scala | 3 +++ tests/neg/erased-implicit.scala | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 tests/neg/erased-implicit-b.scala diff --git a/tests/neg/erased-implicit-b.scala b/tests/neg/erased-implicit-b.scala new file mode 100644 index 000000000000..32fc8adbcbf6 --- /dev/null +++ b/tests/neg/erased-implicit-b.scala @@ -0,0 +1,3 @@ +object Test { + def foo erased (implicit a: Double) = 42 // error +} diff --git a/tests/neg/erased-implicit.scala b/tests/neg/erased-implicit.scala index 0542086bb285..2df2ad88db4d 100644 --- a/tests/neg/erased-implicit.scala +++ b/tests/neg/erased-implicit.scala @@ -6,5 +6,4 @@ object Test { erased implicit def doubleImplicit: Double = 42.0 - def foo erased (implicit a: Double) = 42 // error }