diff options
Diffstat (limited to 'src')
12 files changed, 222 insertions, 123 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 6ef6751720..dc8f59b0af 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -905,7 +905,9 @@ trait Definitions extends reflect.api.StandardDefinitions { lazy val GetterTargetClass = getMetaAnnotation("getter") lazy val ParamTargetClass = getMetaAnnotation("param") lazy val SetterTargetClass = getMetaAnnotation("setter") - // TODO: module, moduleClass? package, packageObject? + lazy val ClassTargetClass = getMetaAnnotation("companionClass") + lazy val ObjectTargetClass = getMetaAnnotation("companionObject") + lazy val MethodTargetClass = getMetaAnnotation("companionMethod") // TODO: module, moduleClass? package, packageObject? private def getMetaAnnotation(name: String) = getRequiredClass("scala.annotation.meta." + name) def isMetaAnnotation(sym: Symbol): Boolean = metaAnnotations(sym) || ( diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index ff0bdf7580..4a05b28867 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -832,7 +832,7 @@ trait ContextErrors { implicit val context0 = context object SymValidateErrors extends Enumeration { - val ImplicitConstr, ImplicitNotTerm, ImplicitTopObject, + val ImplicitConstr, ImplicitNotTermOrClass, ImplicitAtToplevel, OverrideClass, SealedNonClass, AbstractNonClass, OverrideConstr, AbstractOverride, LazyAndEarlyInit, ByNameParameter, AbstractVar = Value @@ -898,10 +898,10 @@ trait ContextErrors { case ImplicitConstr => "`implicit' modifier not allowed for constructors" - case ImplicitNotTerm => - "`implicit' modifier can be used only for values, variables and methods" + case ImplicitNotTermOrClass => + "`implicit' modifier can be used only for values, variables, methods and classes" - case ImplicitTopObject => + case ImplicitAtToplevel => "`implicit' modifier cannot be used for top-level objects" case OverrideClass => diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 3d8c2ea564..875c83969e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -65,7 +65,24 @@ trait MethodSynthesis { MethodType(params, symbols.last.typeConstructor) } - } + + /** The annotations amongst those found on the original symbol which + * should be propagated to this kind of accessor. + */ + def deriveAnnotations(initial: List[AnnotationInfo], category: Symbol, keepClean: Boolean): List[AnnotationInfo] = { + initial filter { ann => + // There are no meta-annotation arguments attached to `ann` + if (ann.metaAnnotations.isEmpty) { + // A meta-annotation matching `annotKind` exists on `ann`'s definition. + (ann.defaultTargets contains category) || + // `ann`'s definition has no meta-annotations, and `keepClean` is true. + (ann.defaultTargets.isEmpty && keepClean) + } + // There are meta-annotation arguments, and one of them matches `annotKind` + else ann.metaAnnotations exists (_ matches category) + } + } + } import synthesisUtil._ class ClassMethodSynthesis(val clazz: Symbol, localTyper: Typer) { @@ -155,28 +172,23 @@ trait MethodSynthesis { /** There are two key methods in here. * - * 1) enterGetterSetter is called from Namer with a ValDef which - * may need accessors. Some setup is performed. In general this - * creates symbols and enters them into the scope of the owner. + * 1) Enter methods such as enterGetterSetterare called + * from Namer with a tree which may generate further trees such as accessors or + * implicit wrappers. Some setup is performed. In general this creates symbols + * and enters them into the scope of the owner. * - * 2) finishGetterSetter is called from Typer when a Template is typed. + * 2) addDerivedTrees is called from Typer when a Template is typed. * It completes the job, returning a list of trees with their symbols - * set to those created in enterGetterSetter. Those trees then become + * set to those created in the enter methods. Those trees then become * part of the typed template. */ trait MethodSynth { self: Namer => import NamerErrorGen._ - - /** TODO - synthesize method. - */ - def enterImplicitClass(tree: ClassDef) { - /** e.g. - val ClassDef(mods, name, tparams, impl) = tree - val converter = ImplicitClassConverter(tree).createAndEnterSymbol() - ... - */ + + def enterImplicitWrapper(tree: ClassDef) { + ImplicitClassWrapper(tree).createAndEnterSymbol() } def enterGetterSetter(tree: ValDef) { @@ -203,7 +215,8 @@ trait MethodSynthesis { enterBeans(tree) } - def finishGetterSetter(typer: Typer, stat: Tree): List[Tree] = stat match { + + def addDerivedTrees(typer: Typer, stat: Tree): List[Tree] = stat match { case vd @ ValDef(mods, name, tpt, rhs) if !noFinishGetterSetter(vd) && !vd.symbol.isLazy => // If we don't save the annotations, they seem to wander off. val annotations = stat.symbol.initialize.annotations @@ -211,9 +224,19 @@ trait MethodSynthesis { map (acc => atPos(vd.pos.focus)(acc derive annotations)) filterNot (_ eq EmptyTree) ) + case cd @ ClassDef(mods, _, _, _) if mods.isImplicit => + val annotations = stat.symbol.initialize.annotations + // TODO: need to shuffle annotations between wrapper and class. + val wrapper = ImplicitClassWrapper(cd) + val meth = wrapper.derivedSym + val mdef = context.unit.synthetics(meth) + context.unit.synthetics -= meth + meth setAnnotations deriveAnnotations(annotations, MethodTargetClass, false) + cd.symbol setAnnotations deriveAnnotations(annotations, ClassTargetClass, true) + List(cd, mdef) case _ => List(stat) - } + } def standardAccessors(vd: ValDef): List[DerivedFromValDef] = ( if (vd.mods.isMutable && !vd.mods.isLazy) List(Getter(vd), Setter(vd)) @@ -234,35 +257,59 @@ trait MethodSynthesis { field ::: standardAccessors(vd) ::: beanAccessors(vd) } + /** This trait assembles what's needed for synthesizing derived methods. + * Important: Typically, instances of this trait are created TWICE for each derived + * symbol; once form Namers in an enter method, and once from Typers in addDerivedTrees. + * So it's important that creating an instance of Derived does not have a side effect, + * or if it has a side effect, control that it is done only once. + */ trait Derived { - /** The tree from which we are deriving a synthetic member. */ + + /** The tree from which we are deriving a synthetic member. Typically, that's + * given as an argument of the instance. */ def tree: Tree + + /** The name of the method */ def name: TermName + + /** The flags that are retained from the original symbol */ + def flagsMask: Long + + /** The flags that the derived symbol has in addition to those retained from + * the original symbol*/ def flagsExtra: Long - - /** The tree, symbol, and type completer for the synthetic member. */ + + /** type completer for the synthetic member. + */ def completer(sym: Symbol): Type + + /** The derived symbol. It is assumed that this symbol already exists and has been + * entered in the parent scope when derivedSym is called */ def derivedSym: Symbol + + /** The definition tree of the derived symbol. */ def derivedTree: Tree } - + trait DerivedFromMemberDef extends Derived { def tree: MemberDef - + def enclClass: Symbol + // Final methods to make the rest easier to reason about. final def mods = tree.mods final def basisSym = tree.symbol - final def enclClass = basisSym.enclClass final def derivedFlags: Long = basisSym.flags & flagsMask | flagsExtra } - + trait DerivedFromClassDef extends DerivedFromMemberDef { def tree: ClassDef + final def enclClass = basisSym.owner.enclClass } trait DerivedFromValDef extends DerivedFromMemberDef { def tree: ValDef + final def enclClass = basisSym.enclClass /** Which meta-annotation is associated with this kind of entity. * Presently one of: field, getter, setter, beanGetter, beanSetter, param. @@ -286,22 +333,6 @@ trait MethodSynthesis { enterInScope(sym) sym setInfo completer(sym) } - /** The annotations amongst those found on the original symbol which - * should be propagated to this kind of accessor. - */ - private def deriveAnnotations(initial: List[AnnotationInfo]): List[AnnotationInfo] = { - initial filter { ann => - // There are no meta-annotation arguments attached to `ann` - if (ann.metaAnnotations.isEmpty) { - // A meta-annotation matching `annotKind` exists on `ann`'s definition. - (ann.defaultTargets contains category) || - // `ann`'s definition has no meta-annotations, and `keepClean` is true. - (ann.defaultTargets.isEmpty && keepClean) - } - // There are meta-annotation arguments, and one of them matches `annotKind` - else ann.metaAnnotations exists (_ matches category) - } - } private def logDerived(result: Tree): Tree = { debuglog("[+derived] " + ojoin(mods.flagString, basisSym.accurateKindString, basisSym.getterName.decode) + " (" + derivedSym + ")\n " + result) @@ -310,7 +341,7 @@ trait MethodSynthesis { } final def derive(initial: List[AnnotationInfo]): Tree = { validate() - derivedSym setAnnotations deriveAnnotations(initial) + derivedSym setAnnotations deriveAnnotations(initial, category, keepClean) logDerived(derivedTree) } } @@ -334,15 +365,21 @@ trait MethodSynthesis { /** A synthetic method which performs the implicit conversion implied by * the declaration of an implicit class. Yet to be written. */ - case class ImplicitClassConverter(tree: ClassDef) extends DerivedFromClassDef { - def completer(sym: Symbol): Type = ??? - def derivedSym: Symbol = ??? - def derivedTree: DefDef = ??? - def flagsExtra: Long = ??? - def flagsMask: Long = ??? - def name: TermName = ??? - } - + case class ImplicitClassWrapper(tree: ClassDef) extends DerivedFromClassDef { + def completer(sym: Symbol): Type = ??? // not needed + def createAndEnterSymbol(): Symbol = enterSyntheticSym(derivedTree) + def derivedSym: Symbol = { + val result = enclClass.info decl name + assert(result != NoSymbol, "not found: "+name+" in "+enclClass+" "+enclClass.info.decls) + result + } + def derivedTree: DefDef = + factoryMeth(mods & flagsMask | flagsExtra, name, tree, symbolic = false) + def flagsExtra: Long = METHOD | IMPLICIT + def flagsMask: Long = AccessFlags + def name: TermName = tree.name.toTermName + } + case class Getter(tree: ValDef) extends DerivedGetter { def name = tree.name def category = GetterTargetClass diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 2539091966..129a1c7520 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -99,7 +99,7 @@ trait Namers extends MethodSynthesis { owner.unsafeTypeParams foreach (paramContext.scope enter _) newNamer(paramContext) } - + def enclosingNamerWithScope(scope: Scope) = { var cx = context while (cx != NoContext && cx.scope != scope) cx = cx.outer @@ -666,10 +666,12 @@ trait Namers extends MethodSynthesis { "If possible, define " + tree.symbol + " in " + owner.skipPackageObject + " instead." ) } - + // Suggested location only. - if (mods.isImplicit) - enterImplicitClass(tree) + if (mods.isImplicit) { + log("enter implicit wrapper "+tree+", owner = "+owner) + enterImplicitWrapper(tree) + } } // this logic is needed in case typer was interrupted half @@ -684,7 +686,7 @@ trait Namers extends MethodSynthesis { val acc = sym.lazyAccessor if (acc != NoSymbol) enterIfNotThere(acc) } - defaultParametersOfMethod(sym) foreach enterIfNotThere + defaultParametersOfMethod(sym) foreach { symRef => enterIfNotThere(symRef()) } } this.context } @@ -1161,7 +1163,7 @@ trait Namers extends MethodSynthesis { // if compiling the same local block several times (which can happen in interactive mode) // we might otherwise not find the default symbol, because the second time it the // method symbol will be re-entered in the scope but the default parameter will not. - defaultParametersOfMethod(meth) += default + defaultParametersOfMethod(meth) += new WeakReference(default) } } else if (baseHasDefault) { // the parameter does not have a default itself, but the @@ -1404,10 +1406,10 @@ trait Namers extends MethodSynthesis { if (sym.isImplicit) { if (sym.isConstructor) fail(ImplicitConstr) - if (!sym.isTerm) - fail(ImplicitNotTerm) + if (!(sym.isTerm || (sym.isClass && !sym.isTrait))) + fail(ImplicitNotTermOrClass) if (sym.owner.isPackageClass) - fail(ImplicitTopObject) + fail(ImplicitAtToplevel) } if (sym.isClass) { if (sym.isAnyOverride && !sym.hasFlag(TRAIT)) diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 2573678f8c..4d84bf4af2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -8,6 +8,7 @@ package typechecker import symtab.Flags._ import scala.collection.mutable +import scala.ref.WeakReference /** * @author Lukas Rytz @@ -20,7 +21,7 @@ trait NamesDefaults { self: Analyzer => import NamesDefaultsErrorsGen._ val defaultParametersOfMethod = - perRunCaches.newWeakMap[Symbol, Set[Symbol]]() withDefaultValue Set() + perRunCaches.newWeakMap[Symbol, Set[WeakReference[Symbol]]]() withDefaultValue Set() case class NamedApplyInfo( qual: Option[Tree], diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f558e0afc7..5c342a83e2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1653,7 +1653,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val body = if (isPastTyper || reporter.hasErrors) templ.body - else templ.body flatMap rewrappingWrapperTrees(namer.finishGetterSetter(Typer.this, _)) + else templ.body flatMap rewrappingWrapperTrees(namer.addDerivedTrees(Typer.this, _)) val body1 = typedStats(body, templ.symbol) @@ -2202,7 +2202,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { vparams map {p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe} } - def mkParams(methodSym: Symbol, formals: List[Type]/* = deriveFormals*/) = { + def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) = { selOverride match { case None if targs.isEmpty => MissingParameterTypeAnonMatchError(tree, pt); (Nil, EmptyTree) case None => @@ -2228,7 +2228,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { // rig the show so we can get started typing the method body -- later we'll correct the infos... anonClass setInfo ClassInfoType(List(ObjectClass.tpe, pt, SerializableClass.tpe), newScope, anonClass) val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL) - val (paramSyms, selector) = mkParams(methodSym, deriveFormals) + val (paramSyms, selector) = mkParams(methodSym) if (selector eq EmptyTree) EmptyTree else { @@ -2292,7 +2292,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { def isDefinedAtMethod = { val methodSym = anonClass.newMethod(nme.isDefinedAt, tree.pos, FINAL) - val (paramSyms, selector) = mkParams(methodSym, deriveFormals) + val (paramSyms, selector) = mkParams(methodSym) if (selector eq EmptyTree) EmptyTree else { val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it) @@ -2474,54 +2474,53 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { || (looker.hasAccessorFlag && !accessed.hasAccessorFlag && accessed.isPrivate) ) - def checkNoDoubleDefsAndAddSynthetics(stats: List[Tree]): List[Tree] = { + def checkNoDoubleDefs(stats: List[Tree]): Unit = { val scope = if (inBlock) context.scope else context.owner.info.decls - var newStats = new ListBuffer[Tree] - var needsCheck = true - var moreToAdd = true - while (moreToAdd) { - val initSize = scope.size - var e = scope.elems - while ((e ne null) && e.owner == scope) { - - // check no double def - if (needsCheck) { - var e1 = scope.lookupNextEntry(e) - while ((e1 ne null) && e1.owner == scope) { - if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) && - (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe) || e.sym.isMacro && e1.sym.isMacro)) - // default getters are defined twice when multiple overloads have defaults. an - // error for this is issued in RefChecks.checkDefaultsInOverloaded - if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefault && - !e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) { - log("Double definition detected:\n " + - ((e.sym.getClass, e.sym.info, e.sym.ownerChain)) + "\n " + - ((e1.sym.getClass, e1.sym.info, e1.sym.ownerChain))) - - DefDefinedTwiceError(e.sym, e1.sym) - scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779 - } - e1 = scope.lookupNextEntry(e1) + var e = scope.elems + while ((e ne null) && e.owner == scope) { + var e1 = scope.lookupNextEntry(e) + while ((e1 ne null) && e1.owner == scope) { + if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) && + (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe))) + // default getters are defined twice when multiple overloads have defaults. an + // error for this is issued in RefChecks.checkDefaultsInOverloaded + if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag && + !e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) { + log("Double definition detected:\n " + + ((e.sym.getClass, e.sym.info, e.sym.ownerChain)) + "\n " + + ((e1.sym.getClass, e1.sym.info, e1.sym.ownerChain))) + + DefDefinedTwiceError(e.sym, e1.sym) + scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779 } - } - - // add synthetics - context.unit.synthetics get e.sym foreach { tree => - newStats += typedStat(tree) // might add even more synthetics to the scope - context.unit.synthetics -= e.sym + e1 = scope.lookupNextEntry(e1) } - e = e.next } - needsCheck = false - // the type completer of a synthetic might add more synthetics. example: if the - // factory method of a case class (i.e. the constructor) has a default. - moreToAdd = initSize != scope.size + } + + def addSynthetics(stats: List[Tree]): List[Tree] = { + val scope = if (inBlock) context.scope else context.owner.info.decls + var newStats = new ListBuffer[Tree] + var moreToAdd = true + while (moreToAdd) { + val initElems = scope.elems + for (sym <- scope) + for (tree <- context.unit.synthetics get sym) { + newStats += typedStat(tree) // might add even more synthetics to the scope + context.unit.synthetics -= sym + } + // the type completer of a synthetic might add more synthetics. example: if the + // factory method of a case class (i.e. the constructor) has a default. + moreToAdd = scope.elems ne initElems } if (newStats.isEmpty) stats else { // put default getters next to the method they belong to, // same for companion objects. fixes #2489 and #4036. + // [Martin] This is pretty ugly. I think we could avoid + // this code by associating defaults and companion objects + // with the original tree instead of the new symbol. def matches(stat: Tree, synt: Tree) = (stat, synt) match { case (DefDef(_, statName, _, _, _, _), DefDef(mods, syntName, _, _, _, _)) => mods.hasDefaultFlag && syntName.toString.startsWith(statName.toString) @@ -2551,7 +2550,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } context.updateBuffer(statsErrors) if (phase.erasedTypes) stats1 - else checkNoDoubleDefsAndAddSynthetics(stats1) + else { + checkNoDoubleDefs(stats1) + addSynthetics(stats1) + } } def typedArg(arg: Tree, mode: Int, newmode: Int, pt: Type): Tree = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala index 4f5b6868ae..1f79d8212d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala @@ -112,8 +112,8 @@ trait Unapplies extends ast.TreeDSL private def toIdent(x: DefTree) = Ident(x.name) setPos x.pos.focus - private def classType(cdef: ClassDef, tparams: List[TypeDef]): Tree = { - val tycon = REF(cdef.symbol) + private def classType(cdef: ClassDef, tparams: List[TypeDef], symbolic: Boolean = true): Tree = { + val tycon = if (symbolic) REF(cdef.symbol) else Ident(cdef.name) if (tparams.isEmpty) tycon else AppliedTypeTree(tycon, tparams map toIdent) } @@ -166,15 +166,20 @@ trait Unapplies extends ast.TreeDSL /** The apply method corresponding to a case class */ - def caseModuleApplyMeth(cdef: ClassDef): DefDef = { + def factoryMeth(mods: Modifiers, name: TermName, cdef: ClassDef, symbolic: Boolean): DefDef = { val tparams = cdef.tparams map copyUntypedInvariant val cparamss = constrParamss(cdef) + def classtpe = classType(cdef, tparams, symbolic) atPos(cdef.pos.focus)( - DefDef(caseMods, nme.apply, tparams, cparamss, classType(cdef, tparams), - New(classType(cdef, tparams), mmap(cparamss)(gen.paramToArg))) + DefDef(mods, name, tparams, cparamss, classtpe, + New(classtpe, mmap(cparamss)(gen.paramToArg))) ) } + /** The apply method corresponding to a case class + */ + def caseModuleApplyMeth(cdef: ClassDef): DefDef = factoryMeth(caseMods, nme.apply, cdef, symbolic = true) + /** The unapply method corresponding to a case class */ def caseModuleUnapplyMeth(cdef: ClassDef): DefDef = { diff --git a/src/library/scala/Dynamic.scala b/src/library/scala/Dynamic.scala index 32b57ee88f..dcf7599742 100644 --- a/src/library/scala/Dynamic.scala +++ b/src/library/scala/Dynamic.scala @@ -11,7 +11,7 @@ package scala /** A marker trait that enables dynamic invocations. Instances `x` of this * trait allow calls `x.meth(args)` for arbitrary method names `meth` and * argument lists `args`. If a call is not natively supported by `x`, it - * is rewritten to `x.applyDynamic("meth", args)`. + * is rewritten to `x.applyDynamic("meth")(args)`. * * As of scala 2.9, `scalac` must receive the `-Xexperimental` option for * `Dynamic` to receive this treatment. diff --git a/src/library/scala/annotation/meta/companionClass.scala b/src/library/scala/annotation/meta/companionClass.scala new file mode 100644 index 0000000000..8e53f6caf9 --- /dev/null +++ b/src/library/scala/annotation/meta/companionClass.scala @@ -0,0 +1,17 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.annotation.meta + +/** + * When defining an implicit class, the Scala compiler creates an implicit + * conversion method for it. Annotations `@companionClass` and `@companionMethod` + * control where an annotation on the implicit class will go. By default, annotations + * on an implicit class end up only on the class. + * + */ +final class companionClass extends annotation.StaticAnnotation diff --git a/src/library/scala/annotation/meta/companionMethod.scala b/src/library/scala/annotation/meta/companionMethod.scala new file mode 100644 index 0000000000..379c4f3385 --- /dev/null +++ b/src/library/scala/annotation/meta/companionMethod.scala @@ -0,0 +1,17 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.annotation.meta + +/** + * When defining an implicit class, the Scala compiler creates an implicit + * conversion method for it. Annotations `@companionClass` and `@companionMethod` + * control where an annotation on the implicit class will go. By default, annotations + * on an implicit class end up only on the class. + * + */ +final class companionMethod extends annotation.StaticAnnotation diff --git a/src/library/scala/annotation/meta/companionObject.scala b/src/library/scala/annotation/meta/companionObject.scala new file mode 100644 index 0000000000..d329df5c42 --- /dev/null +++ b/src/library/scala/annotation/meta/companionObject.scala @@ -0,0 +1,14 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ +package scala.annotation.meta + +/** + * Currently unused; intended as an annotation target for classes such as case classes + * that automatically generate a companion object + */ +final class companionObject extends annotation.StaticAnnotation diff --git a/src/library/scala/util/Random.scala b/src/library/scala/util/Random.scala index 791582c9ec..62cba1fc5b 100644 --- a/src/library/scala/util/Random.scala +++ b/src/library/scala/util/Random.scala @@ -120,15 +120,6 @@ class Random(val self: java.util.Random) { bf(xs) ++= buf result } -} - -/** The object `Random` offers a default implementation - * of scala.util.Random and random-related convenience methods. - * - * @since 2.8 - */ -object Random extends Random { - /** Returns a Stream of pseudorandomly chosen alphanumeric characters, * equally chosen from A-Z, a-z, and 0-9. * @@ -141,3 +132,14 @@ object Random extends Random { } } + +/** The object `Random` offers a default implementation + * of scala.util.Random and random-related convenience methods. + * + * @since 2.8 + */ +object Random extends Random { + + implicit def javaRandomToRandom(r: java.util.Random): Random = new Random(r) + +} |