diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index f6f949cf6e32..70685e75e375 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -548,8 +548,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`, `transparent`, or `erased` */ + final val EffectivelyFinal = Private | Final | Transparent | Erased /** A private method */ final val PrivateMethod = allOf(Private, Method) @@ -563,6 +563,9 @@ object Flags { /** A transparent parameter */ final val TransparentParam = allOf(Transparent, Param) + /** A transparent erased method */ + final val TransparentErasedMethod = allOf(Transparent, Erased, Method) + /** An enum case */ final val EnumCase = allOf(Enum, Case) diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index af13b3f22ed5..565f94ec387f 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -276,6 +276,10 @@ trait TypeOps { this: Context => // TODO: Make standalone object. /** Are we in a transparent method body? */ def inTransparentMethod = owner.ownersIterator.exists(_.isTransparentMethod) + /** Are we in a transparent method body? */ + def inErasedTransparentMethod = owner.ownersIterator.exists(sym => + sym.isTransparentMethod && sym.is(Erased)) + /** Is `feature` enabled in class `owner`? * This is the case if one of the following two alternatives holds: * diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java index 8233e3305d2a..2ac008a64683 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -131,6 +131,7 @@ public enum ErrorMessageID { MatchCaseOnlyNullWarningID, ImportRenamedTwiceID, TypeTestAlwaysSucceedsID, + SpliceOutsideQuotesID, ; public int errorNumber() { diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index ef0e416ae1a2..9e382963c426 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -2105,4 +2105,12 @@ object messages { } val explanation = "" } + + case class SpliceOutsideQuotes() extends Message(SpliceOutsideQuotesID) { + val kind = "Syntax" + val msg = "splice outside quotes" + val explanation = + """A splice may only appear inside quotes '{ ... }, + |or else it must be the whole right hand side of a transparent method.""".stripMargin + } } diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index a5b78a2c0ebf..4b19e4a85775 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -156,25 +156,10 @@ 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 - * as a macro. - * - * 2. If selection is a quote or splice node, record that fact in the current compilation unit. + /** If selection is a quote or splice node, record that fact in the current compilation unit. */ - private def handleMeta(sym: Symbol)(implicit ctx: Context): Unit = { - - def markAsMacro(c: Context): Unit = - if (c.owner eq c.outer.owner) markAsMacro(c.outer) - else if (c.owner.isTransparentMethod) { - c.owner.setFlag(Macro) - } - else if (!c.outer.owner.is(Package)) markAsMacro(c.outer) - - if (sym.isSplice || sym.isQuote) { - markAsMacro(ctx) - ctx.compilationUnit.containsQuotesOrSplices = true - } - } + private def reportMeta(sym: Symbol)(implicit ctx: Context): Unit = + if (sym.isSplice || sym.isQuote) ctx.compilationUnit.containsQuotesOrSplices = true private object dropInlines extends TreeMap { override def transform(tree: Tree)(implicit ctx: Context): Tree = tree match { @@ -186,13 +171,13 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase override def transform(tree: Tree)(implicit ctx: Context): Tree = try tree match { case tree: Ident if !tree.isType => - handleMeta(tree.symbol) + reportMeta(tree.symbol) tree.tpe match { case tpe: ThisType => This(tpe.cls).withPos(tree.pos) case _ => tree } case tree @ Select(qual, name) => - handleMeta(tree.symbol) + reportMeta(tree.symbol) if (name.isTypeName) { Checking.checkRealizable(qual.tpe, qual.pos.focus) super.transform(tree)(ctx.addMode(Mode.Type)) diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index b30b65f45001..0d0b2807b304 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -11,7 +11,7 @@ import SymUtils._ import NameKinds._ import dotty.tools.dotc.ast.tpd.Tree import typer.Implicits.SearchFailureType - +import reporting.diagnostic.messages._ import scala.collection.mutable import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.core.quoted._ @@ -242,6 +242,10 @@ class ReifyQuotes extends MacroTransformWithImplicits { !sym.is(Param) || levelOK(sym.owner) } + /** Issue a "splice outside quote" error unless we are in the body of a transparent method */ + def spliceOutsideQuotes(pos: Position)(implicit ctx: Context): Unit = + ctx.error(SpliceOutsideQuotes(), pos) + /** Try to heal phase-inconsistent reference to type `T` using a local type definition. * @return None if successful * @return Some(msg) if unsuccessful where `msg` is a potentially empty error message @@ -300,7 +304,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { outer.checkType(pos).foldOver(acc, tp) } else { - if (tp.isTerm) ctx.error(i"splice outside quotes", pos) + if (tp.isTerm) spliceOutsideQuotes(pos) tp } case tp: NamedType => @@ -431,7 +435,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { 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) + spliceOutsideQuotes(splice.pos) splice } else if (Splicer.canBeSpliced(splice.qualifier)) { // level 0 inside a transparent definition diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index 516ded001526..6ac1d38642dc 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -58,8 +58,12 @@ object Inliner { /** Should call with method `meth` be inlined in this context? */ def isInlineable(meth: Symbol)(implicit ctx: Context): Boolean = { + /** Suppress inlining of + * - non-erased methods inside a transparent method, + * - all methods inside an erased transparent method + */ def suppressInline = - ctx.inTransparentMethod || + ctx.inTransparentMethod && (!meth.is(Erased) || ctx.inErasedTransparentMethod) || ctx.settings.YnoInline.value || ctx.isAfterTyper || ctx.reporter.hasErrors diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 2933c3dc92a5..f79aeb4fec52 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -1195,15 +1195,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/PrepareTransparent.scala index 927ce6f4f053..8aa695336720 100644 --- a/compiler/src/dotty/tools/dotc/typer/PrepareTransparent.scala +++ b/compiler/src/dotty/tools/dotc/typer/PrepareTransparent.scala @@ -20,6 +20,7 @@ import ProtoTypes.selectionProto import SymDenotations.SymDenotation import Annotations._ import transform.{ExplicitOuter, AccessProxies} +import transform.SymUtils._ import Inferencing.fullyDefinedType import config.Printers.inlining import ErrorReporting.errorTree @@ -250,6 +251,15 @@ object PrepareTransparent { inlined.updateAnnotation(LazyBodyAnnotation { _ => implicit val ctx = inlineCtx val rawBody = treeExpr(ctx) + + def markAsMacro(body: Tree): Unit = body match { + case _: Select if body.symbol.isSplice => inlined.setFlag(Erased | Macro) + case Block(Nil, expr) => markAsMacro(expr) + case Block(expr :: Nil, Literal(Constant(()))) => markAsMacro(expr) + case _ => + } + markAsMacro(rawBody) + val typedBody = if (ctx.reporter.hasErrors) rawBody else ctx.compilationUnit.inlineAccessors.makeInlineable(rawBody) diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index f3d16eb4fe0a..906584025dfa 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -143,16 +143,14 @@ 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 definition, it must override at least one concrete member * 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. * 4. Check that every member with an `override` modifier * overrides some other member. * TODO check that classes are not overridden - * TODO This still needs to be cleaned up; the current version is a staright port of what was there + * TODO This still needs to be cleaned up; the current version is a straight port of what was there * before, but it looks too complicated and method bodies are far too large. */ private def checkAllOverrides(clazz: Symbol)(implicit ctx: Context): Unit = { @@ -376,14 +374,8 @@ 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(Deferred) && member.extendedOverriddenSymbols.forall(_.is(Deferred))) { // (1.9) + overrideError("is erased, cannot override only abstract methods") } 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 3310fb6dd8fc..549288a556a9 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -974,8 +974,11 @@ 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) + if (tree.getAttachment(PrepareTransparent.TopLevelMatch).isDefined) + ctx.owner.setFlag(Erased) + else ctx.error(em"implicit match cannot be used here; it must occur as a toplevel match of a transparent method", tree.pos) + val sel1 = id.withType(defn.ImplicitScrutineeTypeRef) typedMatchFinish(tree, sel1, sel1.tpe, pt) case _ => @@ -2351,7 +2354,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(TransparentErasedMethod) && !ctx.mode.is(Mode.Pattern) && !(isSyntheticApply(tree) && !isExpandableApply)) simplify(typed(etaExpand(tree, wtp, arity), pt), pt, locked) diff --git a/docs/docs/typelevel.md b/docs/docs/typelevel.md index 8e09d9971e09..c156e2fa4b0d 100644 --- a/docs/docs/typelevel.md +++ b/docs/docs/typelevel.md @@ -229,34 +229,17 @@ 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 +## Restrictions for Transparent and Erased Functions Transparent methods are effectively final; they may not be overwritten. -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: +Transparent methods with a toplevel implicit match or macro splice are classified `erased` - an `erased` modifier can be given for them, but it is redundant. Erased transparent methods must be always fully applied. In addition, the restrictions on normal erased methods apply, including: - 1. They must be always fully applied. - 2. They may override other methods only if one of the overridden methods is concrete. + 1. They may not override other methods. + 2. They may not be referred to from a non-erased context. -The right hand side of a typelevel 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 = ... -} -val xs: Iterable[T] = ... -val ys: List[T] = ... -val zs: Iterable[T] = ys -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). +**Question:** We currently set `erased` automatically for macros, i.e. methods with a +right-hand side of the form `~...`. But we require it to be written explicitly for methods that have an implicit match as RHS. Should these situations be treated in the same instead? If yes, which of the two is preferable? ## Matching on Types @@ -415,7 +398,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 { +erased transparent def setFor[T]: Set[T] = implicit match { case ord: Ordering[T] => new TreeSet[T] case _ => new HashSet[T] } @@ -426,8 +409,8 @@ 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. +Implicit matches can only occur as toplevel match expressions of a `transparent` method. +If a transpatent method contains implicit matches, it is classified as `erased` - an `erased` modifier can be given for it, but it is redundant. This ensures that all implicit searches are done at compile-time. ## Transparent Values diff --git a/tests/neg/implicitMatch-syntax.scala b/tests/neg/implicitMatch-syntax.scala index 97a47f20f66b..9a0ea94489fd 100644 --- a/tests/neg/implicitMatch-syntax.scala +++ b/tests/neg/implicitMatch-syntax.scala @@ -27,7 +27,7 @@ object Test { case _ => new HashSet[T] }} - def f6[T] = implicit match { // error: implicit match cannot be used here + erased def f6[T] = implicit match { // error: implicit match cannot be used here case _ => new HashSet[T] } } \ No newline at end of file diff --git a/tests/neg/quote-macro-splice.scala b/tests/neg/quote-macro-splice.scala index 52c7042c32d0..d97d5212a995 100644 --- a/tests/neg/quote-macro-splice.scala +++ b/tests/neg/quote-macro-splice.scala @@ -2,23 +2,23 @@ import scala.quoted._ object Test { - transparent def foo1: Int = { // error + transparent def foo1: Int = { println() - ~impl(1.toExpr) + ~impl(1.toExpr) // error: splice outside quotes } - transparent def foo2: Int = { // error - ~impl(1.toExpr) - ~impl(2.toExpr) + transparent def foo2: Int = { + ~impl(1.toExpr) // error: splice outside quotes + ~impl(2.toExpr) // error: splice outside quotes } - transparent def foo3: Int = { // error + transparent def foo3: Int = { val a = 1 - ~impl('(a)) + ~impl('(a)) // error: splice outside quotes } - transparent def foo4: Int = { // error - ~impl('(1)) + transparent def foo4: Int = { + ~impl('(1)) // error: splice outside quotes 1 } diff --git a/tests/neg/transparent-override/B_2.scala b/tests/neg/transparent-override/B_2.scala index c4613f91e9e8..e350479d13cd 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 + erased transparent def f(x: Int): Int = x match { // error case 0 => 1 case _ => x } diff --git a/tests/neg/typelevel-noeta.scala b/tests/neg/typelevel-noeta.scala index c25cd6971b6b..86c10ceebf22 100644 --- a/tests/neg/typelevel-noeta.scala +++ b/tests/neg/typelevel-noeta.scala @@ -2,7 +2,7 @@ object Test { def anyValue[T]: T = ??? - transparent def test(x: Int) = x match { + erased transparent def test(x: Int) = x match { case _: Byte => case _: Char => } diff --git a/tests/pos/i4773.scala b/tests/pos/i4773.scala index 9ed2e098682b..26a5e1a9073c 100644 --- a/tests/pos/i4773.scala +++ b/tests/pos/i4773.scala @@ -3,5 +3,5 @@ import scala.quoted._ object Foo { transparent def foo2(): Unit = ~foo2Impl() def foo2Impl(): Expr[Unit] = '() - transparent def foo(): Unit = foo2() + erased transparent def foo(): Unit = foo2() } diff --git a/tests/neg/inline-i1773.scala b/tests/pos/inline-i1773.scala similarity index 76% rename from tests/neg/inline-i1773.scala rename to tests/pos/inline-i1773.scala index 9e377b23213f..adf601f3d69e 100644 --- a/tests/neg/inline-i1773.scala +++ b/tests/pos/inline-i1773.scala @@ -7,7 +7,7 @@ object Test { } def main(args: Array[String]): Unit = { - val q"class $name extends $parent" = new Object // error: method unapply is used + val q"class $name extends $parent" = new Object println(name) println(parent) } diff --git a/tests/pos/typelevel-vector1.scala b/tests/pos/typelevel-vector1.scala index d48dadd12331..b9d0e2c6992e 100644 --- a/tests/pos/typelevel-vector1.scala +++ b/tests/pos/typelevel-vector1.scala @@ -23,8 +23,13 @@ object Test { 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, _] = { - val length = Typed(add(erasedValue[N1], erasedValue[N2])) + erased val length = Typed(add(erasedValue[N1], erasedValue[N2])) Vec[T, length.Type](xs.elems ++ ys.elems) } + + val xs = Vec[Int, S[S[Z]]](List(1, 2)) + val ys = Vec[Int, S[Z]](List(3)) + val zs = concat(xs, ys) + val zsc: Vec[Int, S[S[S[Z]]]] = zs } diff --git a/tests/pos/typelevel-vector2.scala b/tests/pos/typelevel-vector2.scala new file mode 100644 index 000000000000..d40479924131 --- /dev/null +++ b/tests/pos/typelevel-vector2.scala @@ -0,0 +1,45 @@ +object typelevel { + case class Typed[T](value: T) { type Type = T } + erased def erasedValue[T]: T = ??? +} + +sealed trait Nat +case object Z extends Nat +case class S[N <: Nat](n: N) extends Nat + +object Nat { + type Z = Z.type + transparent def fromInt(n: Int): Nat = n match { + case 0 => Z + case n1 => S(fromInt(n - 1)) + } +} + +import Nat.Z + +sealed trait Vec[+A] { type Len <: Nat } +case object VNil extends Vec[Nothing] { type Len = Z } +case class VCons[+A, TL <: Vec[A]](hd: A, tl: TL) extends Vec[A] { type Len = S[tl.Len]} + +object Vec { + type VNil = VNil.type +} + +import Vec.VNil + +object Concat { + transparent def concat[A](xs: Vec[A], ys: Vec[A]): Vec[A] = + xs match { + case VNil => ys + case VCons(hd, tl) => VCons(hd, concat(tl, ys)) + } +} + +import Concat.concat + +object Test { + val v1 = VCons(1, VCons(2, VNil)) + val v2 = VCons(3, VCons(4, VCons(5, VNil))) + val v3 = concat(v1, v2) + val v3l: v3.Len = Nat.fromInt(5) +} \ No newline at end of file diff --git a/tests/run/i4735/App_2.scala b/tests/run/i4735/App_2.scala index 3f374a321031..547f210ac07b 100644 --- a/tests/run/i4735/App_2.scala +++ b/tests/run/i4735/App_2.scala @@ -7,8 +7,9 @@ object Test { System.out.println(2*x) } } + } class Unrolled(arr: Array[Int]) extends AnyVal { - transparent def foreach(f: => Int => Unit): Unit = Macro.unrolledForeach(3, arr, f) + erased transparent def foreach(f: => Int => Unit): Unit = Macro.unrolledForeach(3, arr, f) } diff --git a/tests/run/implicitMatch.scala b/tests/run/implicitMatch.scala index c11888e8897b..54e2016b5391 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 { + erased transparent 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 { + erased transparent def g = implicit match { case _: A => println("A") case _: B => println("B") } diff --git a/tests/run/typelevel-defaultValue.scala b/tests/run/typelevel-defaultValue.scala index c31b363f3b18..2baf4cbcd206 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 { + erased transparent def defaultValue[T]: Option[Any] = 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-overrides.scala b/tests/run/typelevel-overrides.scala index 67a9512048f5..10f44b380f3c 100644 --- a/tests/run/typelevel-overrides.scala +++ b/tests/run/typelevel-overrides.scala @@ -25,5 +25,5 @@ object Test extends App { val b: B = new B assert(b.f(0) == 0) val c: A = new C - assert(c.f(0) == 1, c.f(0)) + assert(c.f(0) == 0, c.f(0)) } \ No newline at end of file