diff options
19 files changed, 168 insertions, 54 deletions
@@ -10,6 +10,7 @@ Aleksandar Prokopec <aleksandar.prokopec@epfl.ch> <aleksandar@lampmac14.epfl.ch> Aleksandar Prokopec <aleksandar.prokopec@epfl.ch> <axel22@gmail.com> Alex Cruise <alex@cluonflux.com> Alex Cruise <alex@cluonflux.com> <alex@metaforsoftware.com> +A. P. Marki <som.snytt@gmail.com> Antonio Cunei <antonio.cunei@typesafe.com> Antonio Cunei <antonio.cunei@typesafe.com> <antonio.cunei@epfl.ch> Buraq Emir <buraq@epfl.ch> @@ -71,5 +72,6 @@ Unknown Committer <lost.soul@typesafe.com> <USER@epfl.ch> Unknown Committer <lost.soul@typesafe.com> <noreply@epfl.ch> Viktor Klang <viktor.klang@gmail.com> Vincent Cremet <cremet@epfl.ch> +Vladimir Nikolaev <vladimir.nikolaev9@gmail.com> Vojin Jovanovic <vojin.jovanovic@epfl.ch> Vojin Jovanovic <vojin.jovanovic@epfl.ch> <gvojin@gmail.com> diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 23a2e0b37f..e3d2bf14a0 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1225,7 +1225,7 @@ self => // Like Swiss cheese, with holes def stringCheese: Tree = atPos(in.offset) { val start = in.offset - val interpolator = in.name + val interpolator = in.name.encoded // ident() for INTERPOLATIONID val partsBuf = new ListBuffer[Tree] val exprBuf = new ListBuffer[Tree] diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 90c15bca61..55f45257dc 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -55,23 +55,26 @@ abstract class Pickler extends SubComponent { case _ => } } - // If there are any erroneous types in the tree, then we will crash - // when we pickle it: so let's report an error instead. We know next - // to nothing about what happened, but our supposition is a lot better - // than "bad type: <error>" in terms of explanatory power. - for (t <- unit.body) { - if (t.isErroneous) { - unit.error(t.pos, "erroneous or inaccessible type") - return - } - if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) { - unit.error(t.pos, "macro has not been expanded") - return - } + try { + pickle(unit.body) + } catch { + case e: FatalError => + for (t <- unit.body) { + // If there are any erroneous types in the tree, then we will crash + // when we pickle it: so let's report an error instead. We know next + // to nothing about what happened, but our supposition is a lot better + // than "bad type: <error>" in terms of explanatory power. + // + // OPT: do this only as a recovery after fatal error. Checking in advance was expensive. + if (t.isErroneous) { + if (settings.debug) e.printStackTrace() + unit.error(t.pos, "erroneous or inaccessible type") + return + } + } + throw e } - - pickle(unit.body) } } diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 3791af1629..c59b726076 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -306,6 +306,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { /** Return the specialized name of 'sym' in the given environment. It * guarantees the same result regardless of the map order by sorting * type variables alphabetically. + * + * !!! Is this safe in the face of the following? + * scala> trait T { def foo[A] = 0}; object O extends T { override def foo[B] = 0 } */ private def specializedName(sym: Symbol, env: TypeEnv): TermName = { val tvars = ( @@ -391,13 +394,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * enclosing member with the annotation. */ private def needsSpecialization(env: TypeEnv, sym: Symbol): Boolean = ( - !sym.ownerChain.exists(_ hasAnnotation UnspecializedClass) && ( + !hasUnspecializableAnnotation(sym) && ( specializedTypeVars(sym).intersect(env.keySet).diff(wasSpecializedForTypeVars(sym)).nonEmpty || sym.isClassConstructor && (sym.enclClass.typeParams exists (_.isSpecialized)) || isNormalizedMember(sym) && info(sym).typeBoundsIn(env) ) ) + private def hasUnspecializableAnnotation(sym: Symbol): Boolean = + sym.ownerChain.exists(_ hasAnnotation UnspecializedClass) + def isNormalizedMember(m: Symbol) = m.isSpecialized && (info get m exists { case NormalizedMember(_) => true case _ => false @@ -433,10 +439,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { else specializedTypeVars(sym.typeParams zip args collect { case (tp, arg) if tp.isSpecialized => arg }) - case PolyType(tparams, resTpe) => specializedTypeVars(resTpe :: tparams.map(_.info)) + case PolyType(tparams, resTpe) => specializedTypeVars(resTpe :: mapList(tparams)(symInfo)) // OPT // since this method may be run at phase typer (before uncurry, where NMTs are eliminated) case NullaryMethodType(resTpe) => specializedTypeVars(resTpe) - case MethodType(argSyms, resTpe) => specializedTypeVars(resTpe :: argSyms.map(_.tpe)) + case MethodType(argSyms, resTpe) => specializedTypeVars(resTpe :: mapList(argSyms)(symTpe)) // OPT case ExistentialType(_, res) => specializedTypeVars(res) case AnnotatedType(_, tp) => specializedTypeVars(tp) case TypeBounds(lo, hi) => specializedTypeVars(lo :: hi :: Nil) @@ -907,16 +913,20 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } if (sym.isMethod) { - val stvars = specializedTypeVars(sym) - if (stvars.nonEmpty) - debuglog("specialized %s on %s".format(sym.fullLocationString, stvars.map(_.name).mkString(", "))) + if (hasUnspecializableAnnotation(sym)) { + List() + } else { + val stvars = specializedTypeVars(sym) + if (stvars.nonEmpty) + debuglog("specialized %s on %s".format(sym.fullLocationString, stvars.map(_.name).mkString(", "))) - val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps - val tps2 = tps1 filter stvars - if (!sym.isDeferred) - addConcreteSpecMethod(sym) + val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps + val tps2 = tps1 filter stvars + if (!sym.isDeferred) + addConcreteSpecMethod(sym) - specializeOn(tps2) + specializeOn(tps2) + } } else Nil } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 598b12b00d..e5907e1a0f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -1303,7 +1303,7 @@ trait Contexts { self: Analyzer => var renamed = false var selectors = tree.selectors def current = selectors.head - while (selectors.nonEmpty && result == NoSymbol) { + while ((selectors ne Nil) && result == NoSymbol) { if (current.rename == name.toTermName) result = qual.tpe.nonLocalMember( // new to address #2733: consider only non-local members for imports if (name.isTypeName) current.name.toTypeName else current.name) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 68d724b6fc..f7684b93af 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1596,6 +1596,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } } + private def checkUnexpandedMacro(t: Tree) = + if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) + unit.error(t.pos, "macro has not been expanded") + override def transform(tree: Tree): Tree = { val savedLocalTyper = localTyper val savedCurrentApplication = currentApplication @@ -1755,6 +1759,9 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans varianceValidator.traverse(tt.original) // See SI-7872 case _ => } + + checkUnexpandedMacro(result) + result } catch { case ex: TypeError => diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 37ab6f03fa..101e1526fe 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3412,7 +3412,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case: // val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo) // precise(foo) : foo.type => foo.type - val restpe = mt.resultType(args1 map (arg => gen stableTypeFor arg orElse arg.tpe)) + val restpe = mt.resultType(mapList(args1)(arg => gen stableTypeFor arg orElse arg.tpe)) def ifPatternSkipFormals(tp: Type) = tp match { case MethodType(_, rtp) if (mode.inPatternMode) => rtp case _ => tp @@ -3832,7 +3832,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // lifted out of typed1 because it's needed in typedImplicit0 protected def typedTypeApply(tree: Tree, mode: Mode, fun: Tree, args: List[Tree]): Tree = fun.tpe match { case OverloadedType(pre, alts) => - inferPolyAlternatives(fun, args map (_.tpe)) + inferPolyAlternatives(fun, mapList(args)(treeTpe)) val tparams = fun.symbol.typeParams //@M TODO: fun.symbol.info.typeParams ? (as in typedAppliedTypeTree) val args1 = if (sameLength(args, tparams)) { //@M: in case TypeApply we can't check the kind-arities of the type arguments, @@ -3852,7 +3852,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper typedTypeApply(tree, mode, fun setType fun.tpe.widen, args) case PolyType(tparams, restpe) if tparams.nonEmpty => if (sameLength(tparams, args)) { - val targs = args map (_.tpe) + val targs = mapList(args)(treeTpe) checkBounds(tree, NoPrefix, NoSymbol, tparams, targs, "") if (isPredefClassOf(fun.symbol)) typedClassOf(tree, args.head, noGen = true) @@ -4872,7 +4872,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper typedHigherKindedType(arg, mode, pt) } - val argtypes = args1 map (_.tpe) + val argtypes = mapList(args1)(treeTpe) foreach2(args, tparams) { (arg, tparam) => // note: can't use args1 in selector, because Binds got replaced diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index 49c3b4c3cd..60de147477 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -1108,11 +1108,15 @@ object Stream extends SeqFactory[Stream] { override def isEmpty = false override def head = hd @volatile private[this] var tlVal: Stream[A] = _ - def tailDefined: Boolean = tlVal ne null + @volatile private[this] var tlGen = tl _ + def tailDefined: Boolean = tlGen eq null override def tail: Stream[A] = { if (!tailDefined) synchronized { - if (!tailDefined) tlVal = tl + if (!tailDefined) { + tlVal = tlGen() + tlGen = null + } } tlVal diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 4fde57ed02..d634034fe9 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -48,7 +48,7 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => /** Tests for, get, or remove an annotation */ def hasAnnotation(cls: Symbol): Boolean = //OPT inlined from exists to save on #closures; was: annotations exists (_ matches cls) - dropOtherAnnotations(annotations, cls).nonEmpty + dropOtherAnnotations(annotations, cls) ne Nil def getAnnotation(cls: Symbol): Option[AnnotationInfo] = //OPT inlined from exists to save on #closures; was: annotations find (_ matches cls) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index f49ddaf6ca..26914fecc1 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -3404,8 +3404,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => * @return the new list of info-adjusted symbols */ def deriveSymbols(syms: List[Symbol], symFn: Symbol => Symbol): List[Symbol] = { - val syms1 = syms map symFn - syms1 map (_ substInfo (syms, syms1)) + val syms1 = mapList(syms)(symFn) + mapList(syms1)(_ substInfo (syms, syms1)) } /** Derives a new Type by first deriving new symbols as in deriveSymbols, @@ -3445,9 +3445,9 @@ trait Symbols extends api.Symbols { self: SymbolTable => * @return the newly created, info-adjusted symbols */ def cloneSymbolsAndModify(syms: List[Symbol], infoFn: Type => Type): List[Symbol] = - cloneSymbols(syms) map (_ modifyInfo infoFn) + mapList(cloneSymbols(syms))(_ modifyInfo infoFn) def cloneSymbolsAtOwnerAndModify(syms: List[Symbol], owner: Symbol, infoFn: Type => Type): List[Symbol] = - cloneSymbolsAtOwner(syms, owner) map (_ modifyInfo infoFn) + mapList(cloneSymbolsAtOwner(syms, owner))(_ modifyInfo infoFn) /** Functions which perform the standard clone/substituting on the given symbols and type, * then call the creator function with the new symbols and type as arguments. diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index e602a12175..145b4a3f1f 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -49,10 +49,10 @@ abstract class TreeGen extends macros.TreeBuilder { mkMethodCall(Select(receiver, method), targs, args) def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree = - Apply(mkTypeApply(target, targs map TypeTree), args) + Apply(mkTypeApply(target, mapList(targs)(TypeTree)), args) def mkNullaryCall(method: Symbol, targs: List[Type]): Tree = - mkTypeApply(mkAttributedRef(method), targs map TypeTree) + mkTypeApply(mkAttributedRef(method), mapList(targs)(TypeTree)) /** Builds a reference to value whose type is given stable prefix. * The type must be suitable for this. For example, it diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 9ddaea4c62..2acf901d0e 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1977,7 +1977,7 @@ trait Types def pendingVolatiles = _pendingVolatiles class ArgsTypeRef(pre0: Type, sym0: Symbol, args0: List[Type]) extends TypeRef(pre0, sym0, args0) { - require(args0.nonEmpty, this) + require(args0 ne Nil, this) /** No unapplied type params size it has (should have) equally as many args. */ override def isHigherKinded = false @@ -2035,7 +2035,7 @@ trait Types // to a java or scala symbol, but it does matter whether it occurs in java or scala code. // TypeRefs w/o type params that occur in java signatures/code are considered raw types, and are // represented as existential types. - override def isHigherKinded = typeParams.nonEmpty + override def isHigherKinded = (typeParams ne Nil) override def typeParams = if (isDefinitionsInitialized) sym.typeParams else sym.unsafeTypeParams private def isRaw = !phase.erasedTypes && isRawIfWithoutArgs(sym) @@ -2221,7 +2221,7 @@ trait Types //OPT specialize hashCode override final def computeHashCode = { import scala.util.hashing.MurmurHash3._ - val hasArgs = args.nonEmpty + val hasArgs = args ne Nil var h = productSeed h = mix(h, pre.hashCode) h = mix(h, sym.hashCode) @@ -2412,7 +2412,7 @@ trait Types object TypeRef extends TypeRefExtractor { def apply(pre: Type, sym: Symbol, args: List[Type]): Type = unique({ - if (args.nonEmpty) { + if (args ne Nil) { if (sym.isAliasType) new AliasArgsTypeRef(pre, sym, args) else if (sym.isAbstractType) new AbstractArgsTypeRef(pre, sym, args) else new ClassArgsTypeRef(pre, sym, args) @@ -2485,7 +2485,7 @@ trait Types true } - def isImplicit = params.nonEmpty && params.head.isImplicit + def isImplicit = (params ne Nil) && params.head.isImplicit def isJava = false // can we do something like for implicits? I.e. do Java methods without parameters need to be recognized? //assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG @@ -2493,7 +2493,7 @@ trait Types override def paramss: List[List[Symbol]] = params :: resultType.paramss - override def paramTypes = params map (_.tpe) + override def paramTypes = mapList(params)(symTpe) // OPT use mapList rather than .map override def boundSyms = resultType.boundSyms ++ params @@ -4120,7 +4120,7 @@ trait Types && (variance.isCovariant || isSubType(t2, t1, depth)) ) - corresponds3(tps1, tps2, tparams map (_.variance))(isSubArg) + corresponds3(tps1, tps2, mapList(tparams)(_.variance))(isSubArg) } def specializesSym(tp: Type, sym: Symbol, depth: Depth): Boolean = { @@ -4304,7 +4304,7 @@ trait Types } def instantiatedBounds(pre: Type, owner: Symbol, tparams: List[Symbol], targs: List[Type]): List[TypeBounds] = - tparams map (_.info.asSeenFrom(pre, owner).instantiateTypeParams(tparams, targs).bounds) + mapList(tparams)(_.info.asSeenFrom(pre, owner).instantiateTypeParams(tparams, targs).bounds) def elimAnonymousClass(t: Type) = t match { case TypeRef(pre, clazz, Nil) if clazz.isAnonymousClass => @@ -4553,7 +4553,10 @@ trait Types private[scala] val typeIsExistentiallyBound = (tp: Type) => tp.typeSymbol.isExistentiallyBound private[scala] val typeIsErroneous = (tp: Type) => tp.isErroneous private[scala] val symTypeIsError = (sym: Symbol) => sym.tpe.isError - private[scala] val typeHasAnnotations = (tp: Type) => tp.annotations.nonEmpty + private[scala] val treeTpe = (t: Tree) => t.tpe + private[scala] val symTpe = (sym: Symbol) => sym.tpe + private[scala] val symInfo = (sym: Symbol) => sym.info + private[scala] val typeHasAnnotations = (tp: Type) => tp.annotations ne Nil private[scala] val boundsContainType = (bounds: TypeBounds, tp: Type) => bounds containsType tp private[scala] val typeListIsEmpty = (ts: List[Type]) => ts.isEmpty private[scala] val typeIsSubTypeOfSerializable = (tp: Type) => tp <:< SerializableTpe diff --git a/src/reflect/scala/reflect/internal/util/Collections.scala b/src/reflect/scala/reflect/internal/util/Collections.scala index 7cc2952c96..d128521be8 100644 --- a/src/reflect/scala/reflect/internal/util/Collections.scala +++ b/src/reflect/scala/reflect/internal/util/Collections.scala @@ -47,6 +47,30 @@ trait Collections { final def mforeach[A](xss: List[List[A]])(f: A => Unit) = xss foreach (_ foreach f) final def mforeach[A](xss: Traversable[Traversable[A]])(f: A => Unit) = xss foreach (_ foreach f) + /** A version of List#map, specialized for List, and optimized to avoid allocation if `as` is empty */ + final def mapList[A, B](as: List[A])(f: A => B): List[B] = if (as eq Nil) Nil else { + val head = new ::[B](f(as.head), Nil) + var tail: ::[B] = head + var rest = as.tail + while (rest ne Nil) { + val next = new ::(f(rest.head), Nil) + tail.tl = next + tail = next + rest = rest.tail + } + head + } + + final def collectFirst[A, B](as: List[A])(pf: PartialFunction[A, B]): Option[B] = { + @tailrec + def loop(rest: List[A]): Option[B] = rest match { + case Nil => None + case a :: as if pf.isDefinedAt(a) => Some(pf(a)) + case a :: as => loop(as) + } + loop(as) + } + final def map2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => C): List[C] = { val lb = new ListBuffer[C] var ys1 = xs1 @@ -99,15 +123,19 @@ trait Collections { else f(xs1.head, xs2.head, xs3.head) :: map3(xs1.tail, xs2.tail, xs3.tail)(f) } final def flatMap2[A, B, C](xs1: List[A], xs2: List[B])(f: (A, B) => List[C]): List[C] = { - val lb = new ListBuffer[C] + var lb: ListBuffer[C] = null var ys1 = xs1 var ys2 = xs2 while (!ys1.isEmpty && !ys2.isEmpty) { - lb ++= f(ys1.head, ys2.head) + val cs = f(ys1.head, ys2.head) + if (cs ne Nil) { + if (lb eq null) lb = new ListBuffer[C] + lb ++= cs + } ys1 = ys1.tail ys2 = ys2.tail } - lb.toList + if (lb eq null) Nil else lb.result } final def flatCollect[A, B](elems: List[A])(pf: PartialFunction[A, Traversable[B]]): List[B] = { diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala index 8f217e087c..ef84ac42ba 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala @@ -10,6 +10,7 @@ import diagram._ import scala.collection._ import scala.util.matching.Regex +import scala.reflect.macros.internal.macroImpl import symtab.Flags import io._ @@ -80,7 +81,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def inTemplate: TemplateImpl = inTpl def toRoot: List[EntityImpl] = this :: inTpl.toRoot def qualifiedName = name - def annotations = sym.annotations.map(makeAnnotation) + def annotations = sym.annotations.filterNot(_.tpe =:= typeOf[macroImpl]).map(makeAnnotation) def inPackageObject: Boolean = sym.owner.isModuleClass && sym.owner.sourceModule.isPackageObject def isType = sym.name.isTypeName } @@ -145,6 +146,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { * any abstract terms, otherwise it would fail compilation. So we reset the DEFERRED flag. */ if (!sym.isTrait && (sym hasFlag Flags.DEFERRED) && (!isImplicitlyInherited)) fgs += Paragraph(Text("abstract")) if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final")) + if (sym.isMacro) fgs += Paragraph(Text("macro")) fgs.toList } def deprecation = diff --git a/test/files/pos/t7322.scala b/test/files/pos/t7322.scala new file mode 100644 index 0000000000..006bf89e9f --- /dev/null +++ b/test/files/pos/t7322.scala @@ -0,0 +1,11 @@ + +package object t7322 { + implicit class X(sc: StringContext) { + def x_?(args: Any*) = "hi there" + } +} +package t7322 { + trait Y { + x_?"junk" // assume that if it compiles, it works + } +} diff --git a/test/files/run/t7700.check b/test/files/run/t7700.check new file mode 100644 index 0000000000..ca8e686984 --- /dev/null +++ b/test/files/run/t7700.check @@ -0,0 +1,2 @@ +public abstract java.lang.Object C.bar(java.lang.Object) +public abstract java.lang.Object C.foo(java.lang.Object) diff --git a/test/files/run/t7700.scala b/test/files/run/t7700.scala new file mode 100644 index 0000000000..76d16b808c --- /dev/null +++ b/test/files/run/t7700.scala @@ -0,0 +1,17 @@ +import scala.annotation._ + +trait C[@specialized U] { + @unspecialized + def foo(u: U): U + @unspecialized + def bar[A](u: U) = u +} + +object Test extends App { + val declared = classOf[C[_]].getDeclaredMethods.sortBy(_.getName) + println(declared.mkString("\n")) + object CInt extends C[Int] { def foo(i: Int) = i } + object CAny extends C[Any] { def foo(a: Any) = a } + assert(CInt.foo(1) == 1) + assert(CAny.foo("") == "") +} diff --git a/test/scaladoc/run/t7124.check b/test/scaladoc/run/t7124.check new file mode 100644 index 0000000000..96b627a322 --- /dev/null +++ b/test/scaladoc/run/t7124.check @@ -0,0 +1,3 @@ +List() +List(Paragraph(Text(macro))) +Done. diff --git a/test/scaladoc/run/t7124.scala b/test/scaladoc/run/t7124.scala new file mode 100644 index 0000000000..e8272000d2 --- /dev/null +++ b/test/scaladoc/run/t7124.scala @@ -0,0 +1,22 @@ +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest + +object Test extends ScaladocModelTest { + + override def code = """ + import scala.language.experimental.macros + class Test { + def print(): Unit = macro ??? + } + """ + + def scaladocSettings = "" + + def testModel(root: Package) = { + import access._ + val p = root._class("Test")._method("print") + + println(p.annotations) // no annotations + println(p.flags) // a 'macro' flag + } +} |