diff options
Diffstat (limited to 'src/reflect/scala')
18 files changed, 81 insertions, 42 deletions
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index a6e584424b..8ba3e62ac2 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -316,8 +316,9 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => /** Check whether any of the arguments mention a symbol */ def refsSymbol(sym: Symbol) = hasArgWhich(_.symbol == sym) - def stringArg(index: Int) = constantAtIndex(index) map (_.stringValue) - def intArg(index: Int) = constantAtIndex(index) map (_.intValue) + def stringArg(index: Int) = constantAtIndex(index) map (_.stringValue) + def intArg(index: Int) = constantAtIndex(index) map (_.intValue) + def booleanArg(index: Int) = constantAtIndex(index) map (_.booleanValue) def symbolArg(index: Int) = argAtIndex(index) collect { case Apply(fun, Literal(str) :: Nil) if fun.symbol == definitions.Symbol_apply => newTermName(str.stringValue) diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 19460af27f..78a75c63d6 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -975,10 +975,10 @@ trait Definitions extends api.StandardDefinitions { } /** Given a class symbol C with type parameters T1, T2, ... Tn - * which have upper/lower bounds LB1/UB1, LB1/UB2, ..., LBn/UBn, + * which have upper/lower bounds LB1/UB1, LB2/UB2, ..., LBn/UBn, * returns an existential type of the form * - * C[E1, ..., En] forSome { E1 >: LB1 <: UB1 ... en >: LBn <: UBn }. + * C[E1, ..., En] forSome { E1 >: LB1 <: UB1 ... En >: LBn <: UBn }. */ // TODO Review the way this is used. I see two potential problems: // 1. `existentialAbstraction` here doesn't create fresh existential type symbols, it just @@ -1421,6 +1421,8 @@ trait Definitions extends api.StandardDefinitions { case _ => false } + lazy val ShowAsInfixAnnotationClass = rootMirror.getClassIfDefined("scala.annotation.showAsInfix") + // todo: reconcile with javaSignature!!! def signature(tp: Type): String = { def erasure(tp: Type): Type = tp match { diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala index 95b3b7fb14..1a1aa2e721 100644 --- a/src/reflect/scala/reflect/internal/Positions.scala +++ b/src/reflect/scala/reflect/internal/Positions.scala @@ -255,7 +255,7 @@ trait Positions extends api.Positions { self: SymbolTable => val annTrees = mdef.mods.annotations match { case Nil if mdef.symbol != null => // After typechecking, annotations are moved from the modifiers - // to the annotation on the symbol of the anotatee. + // to the annotation on the symbol of the annotatee. mdef.symbol.annotations.map(_.original) case anns => anns } diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 9602a2859b..bb352e9d31 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -775,7 +775,7 @@ trait Printers extends api.Printers { self: SymbolTable => } // constructor's params processing (don't print single empty constructor param list) vparamss match { - case Nil | List(Nil) if (!mods.isCase && !ctorMods.hasFlag(AccessFlags)) => + case Nil | List(Nil) if !mods.isCase && !ctorMods.hasFlag(AccessFlags) => case _ => vparamss foreach printConstrParams } parents diff --git a/src/reflect/scala/reflect/internal/ReificationSupport.scala b/src/reflect/scala/reflect/internal/ReificationSupport.scala index 026438e421..1b2be64654 100644 --- a/src/reflect/scala/reflect/internal/ReificationSupport.scala +++ b/src/reflect/scala/reflect/internal/ReificationSupport.scala @@ -266,7 +266,7 @@ trait ReificationSupport { self: SymbolTable => } // undo gen.mkTemplate - protected object UnMkTemplate { + protected class UnMkTemplate(isCaseClass: Boolean) { def unapply(templ: Template): Option[(List[Tree], ValDef, Modifiers, List[List[ValDef]], List[Tree], List[Tree])] = { val Template(parents, selfType, _) = templ val tbody = treeInfo.untypecheckedTemplBody(templ) @@ -296,8 +296,9 @@ trait ReificationSupport { self: SymbolTable => result(ctorMods, Nil, edefs, body) else { // undo conversion from (implicit ... ) to ()(implicit ... ) when it's the only parameter section + // except that case classes require the explicit leading empty parameter list val vparamssRestoredImplicits = ctorVparamss match { - case Nil :: (tail @ ((head :: _) :: _)) if head.mods.isImplicit => tail + case Nil :: (tail @ ((head :: _) :: _)) if head.mods.isImplicit && !isCaseClass => tail case other => other } // undo flag modifications by merging flag info from constructor args and fieldDefs @@ -314,7 +315,9 @@ trait ReificationSupport { self: SymbolTable => } } } + def asCase = new UnMkTemplate(isCaseClass = true) } + protected object UnMkTemplate extends UnMkTemplate(isCaseClass = false) protected def mkSelfType(tree: Tree) = tree match { case vd: ValDef => @@ -346,9 +349,11 @@ trait ReificationSupport { self: SymbolTable => def unapply(tree: Tree): Option[(Modifiers, TypeName, List[TypeDef], Modifiers, List[List[ValDef]], List[Tree], List[Tree], ValDef, List[Tree])] = tree match { - case ClassDef(mods, name, tparams, UnMkTemplate(parents, selfType, ctorMods, vparamss, earlyDefs, body)) - if !ctorMods.isTrait && !ctorMods.hasFlag(JAVA) => - Some((mods, name, tparams, ctorMods, vparamss, earlyDefs, parents, selfType, body)) + case ClassDef(mods, name, tparams, impl) => + val X = if (mods.isCase) UnMkTemplate.asCase else UnMkTemplate + val X(parents, selfType, ctorMods, vparamss, earlyDefs, body) = impl + if (ctorMods.isTrait || ctorMods.hasFlag(JAVA)) None + else Some((mods, name, tparams, ctorMods, vparamss, earlyDefs, parents, selfType, body)) case _ => None } diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index 19804fc5f3..51fb31d36d 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -298,7 +298,7 @@ trait Scopes extends api.Scopes { self: SymbolTable => var e = lookupEntry(original.name.companionName) while (e != null) { // 1) Must be owned by the same Scope, to ensure that in - // `{ class C; { ...; object C } }`, the class is not seen as a comaniopn of the object. + // `{ class C; { ...; object C } }`, the class is not seen as a companion of the object. // 2) Must be a class and module symbol, so that `{ class C; def C }` or `{ type T; object T }` are not companions. def isClassAndModule(sym1: Symbol, sym2: Symbol) = sym1.isClass && sym2.isModule if ((e.owner eq entry.owner) && (isClassAndModule(original, e.sym) || isClassAndModule(e.sym, original))) { diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index ad7e3ffe8f..2a0fb5298b 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -309,6 +309,9 @@ trait Types /** Is this type completed (i.e. not a lazy type)? */ def isComplete: Boolean = true + /** Should this be printed as an infix type (@showAsInfix class &&[T, U])? */ + def isShowAsInfixType: Boolean = false + /** If this is a lazy type, assign a new type to `sym`. */ def complete(sym: Symbol) {} @@ -2102,6 +2105,15 @@ trait Types trivial = fromBoolean(!sym.isTypeParameter && pre.isTrivial && areTrivialTypes(args)) toBoolean(trivial) } + + /* It only makes sense to show 2-ary type constructors infix. + * By default we do only if it's a symbolic name. */ + override def isShowAsInfixType: Boolean = + hasLength(args, 2) && + sym.getAnnotation(ShowAsInfixAnnotationClass) + .map(_ booleanArg 0 getOrElse true) + .getOrElse(!Character.isUnicodeIdentifierStart(sym.decodedName.head)) + private[Types] def invalidateTypeRefCaches(): Unit = { parentsCache = null parentsPeriod = NoPeriod @@ -2327,6 +2339,22 @@ trait Types case arg :: Nil => s"($arg,)" case _ => args.mkString("(", ", ", ")") } + private def infixTypeString: String = { + /* SLS 3.2.8: all infix types have the same precedence. + * In A op B op' C, op and op' need the same associativity. + * Therefore, if op is left associative, anything on its right + * needs to be parenthesized if it's an infix type, and vice versa. */ + // we should only get here after `isShowInfixType` says we have 2 args + val l :: r :: Nil = args + + val isRightAssoc = typeSymbol.decodedName endsWith ":" + + val lstr = if (isRightAssoc && l.isShowAsInfixType) s"($l)" else l.toString + + val rstr = if (!isRightAssoc && r.isShowAsInfixType) s"($r)" else r.toString + + s"$lstr ${sym.decodedName} $rstr" + } private def customToString = sym match { case RepeatedParamClass | JavaRepeatedParamClass => args.head + "*" case ByNameParamClass => "=> " + args.head @@ -2350,6 +2378,8 @@ trait Types xs.init.mkString("(", ", ", ")") + " => " + xs.last } } + else if (isShowAsInfixType) + infixTypeString else if (isTupleTypeDirect(this)) tupleTypeString else if (sym.isAliasType && prefixChain.exists(_.termSymbol.isSynthetic) && (this ne dealias)) @@ -4152,7 +4182,7 @@ trait Types * The specification-enumerated non-value types are method types, polymorphic * method types, and type constructors. Supplements to the specified set of * non-value types include: types which wrap non-value symbols (packages - * abd statics), overloaded types. Varargs and by-name types T* and (=>T) are + * and statics), overloaded types. Varargs and by-name types T* and (=>T) are * not designated non-value types because there is code which depends on using * them as type arguments, but their precise status is unclear. */ @@ -4251,7 +4281,7 @@ trait Types case mt1 @ MethodType(params1, res1) => tp2 match { case mt2 @ MethodType(params2, res2) => - // sameLength(params1, params2) was used directly as pre-screening optimization (now done by matchesQuantified -- is that ok, performancewise?) + // sameLength(params1, params2) was used directly as pre-screening optimization (now done by matchesQuantified -- is that ok, performance-wise?) mt1.isImplicit == mt2.isImplicit && matchingParams(params1, params2, mt1.isJava, mt2.isJava) && matchesQuantified(params1, params2, res1, res2) @@ -4696,7 +4726,7 @@ trait Types case _ => Depth(1) } - //OPT replaced with tailrecursive function to save on #closures + //OPT replaced with tail recursive function to save on #closures // was: // var d = 0 // for (tp <- tps) d = d max by(tp) //!!!OPT!!! diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index fe1de91662..08ccac8069 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -385,7 +385,7 @@ abstract class UnPickler { // We're stuck with the order types are pickled in, but with judicious use // of named parameters we can recapture a declarative flavor in a few cases. - // But it's still a rat's nest of adhockery. + // But it's still a rat's nest of ad-hockery. (tag: @switch) match { case NOtpe => NoType case NOPREFIXtpe => NoPrefix diff --git a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala index 108ce45cca..6d9a9d6649 100644 --- a/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala +++ b/src/reflect/scala/reflect/internal/tpe/GlbLubs.scala @@ -136,7 +136,7 @@ private[internal] trait GlbLubs { mergePrefixAndArgs(ts1, Covariant, depth) match { case NoType => loop(pretypes, tails) case tp if strictInference && willViolateRecursiveBounds(tp, ts0, ts1) => - log(s"Breaking recursion in lublist, advancing frontier and discaring merged prefix/args from $tp") + log(s"Breaking recursion in lublist, advancing frontier and discarding merged prefix/args from $tp") loop(pretypes, tails) case tp => loop(tp :: pretypes, tails) diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala index cf274f24bb..990092b749 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala @@ -404,7 +404,7 @@ trait TypeComparers { sym2.isClass && { val base = tr1 baseType sym2 // During bootstrap, `base eq NoType` occurs about 2.5 times as often as `base ne NoType`. - // The extra check seems like a worthwhile optimization (about 2.5M useless calls to isSubtype saved during that run). + // The extra check seems like a worthwhile optimization (about 2.5M useless calls to isSubType saved during that run). (base ne tr1) && (base ne NoType) && isSubType(base, tr2, depth) } || diff --git a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala index e321a07f51..2697824fd5 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala @@ -25,7 +25,7 @@ private[internal] trait TypeConstraints { // register with the auto-clearing cache manager perRunCaches.recordCache(this) - /** Undo all changes to constraints to type variables upto `limit`. */ + /** Undo all changes to constraints to type variables up to `limit`. */ //OPT this method is public so we can do `manual inlining` def undoTo(limit: UndoPairs) { assertCorrectThread() diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index de065d0b5d..0601067d26 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -312,7 +312,7 @@ private[internal] trait TypeMaps { * the corresponding class file might still not be read, so we do not * know what the type parameters of the type are. Therefore * the conversion of raw types to existential types might not have taken place - * in ClassFileparser.sigToType (where it is usually done). + * in ClassFileParser.sigToType (where it is usually done). */ def rawToExistential = new TypeMap { private var expanded = immutable.Set[Symbol]() @@ -404,7 +404,7 @@ private[internal] trait TypeMaps { case _ => super.mapOver(tp) } - // Do not discard the types of existential ident's. The + // Do not discard the types of existential idents. The // symbol of the Ident itself cannot be listed in the // existential's parameters, so the resulting existential // type would be ill-formed. @@ -504,7 +504,7 @@ private[internal] trait TypeMaps { && isBaseClassOfEnclosingClass(sym.owner) ) - private var capturedThisIds= 0 + private var capturedThisIds = 0 private def nextCapturedThisId() = { capturedThisIds += 1; capturedThisIds } /** Creates an existential representing a type parameter which appears * in the prefix of a ThisType. diff --git a/src/reflect/scala/reflect/internal/transform/Erasure.scala b/src/reflect/scala/reflect/internal/transform/Erasure.scala index e2f1e74740..24f8aa88e6 100644 --- a/src/reflect/scala/reflect/internal/transform/Erasure.scala +++ b/src/reflect/scala/reflect/internal/transform/Erasure.scala @@ -19,7 +19,7 @@ trait Erasure { /* A Java Array<T> is erased to Array[Object] (T can only be a reference type), where as a Scala Array[T] is * erased to Object. However, there is only symbol for the Array class. So to make the distinction between * a Java and a Scala array, we check if the owner of T comes from a Java class. - * This however caused issue SI-5654. The additional test for EXSITENTIAL fixes it, see the ticket comments. + * This however caused issue SI-5654. The additional test for EXISTENTIAL fixes it, see the ticket comments. * In short, members of an existential type (e.g. `T` in `forSome { type T }`) can have pretty arbitrary * owners (e.g. when computing lubs, <root> is used). All packageClass symbols have `isJavaDefined == true`. */ diff --git a/src/reflect/scala/reflect/internal/util/Statistics.scala b/src/reflect/scala/reflect/internal/util/Statistics.scala index 905f1bf26e..2d623f3367 100644 --- a/src/reflect/scala/reflect/internal/util/Statistics.scala +++ b/src/reflect/scala/reflect/internal/util/Statistics.scala @@ -78,7 +78,7 @@ object Statistics { /** Create a new stackable that shows as `prefix` and is active * in the same phases as its base timer. Stackable timers are subtimers - * that can be stacked ina timerstack, and that print aggregate, as well as specific + * that can be stacked in a timerstack, and that print aggregate, as well as specific * durations. */ def newStackableTimer(prefix: String, timer: Timer): StackableTimer = new StackableTimer(prefix, timer) diff --git a/src/reflect/scala/reflect/internal/util/StringOps.scala b/src/reflect/scala/reflect/internal/util/StringOps.scala index 79195e6eab..2fee6b0f82 100644 --- a/src/reflect/scala/reflect/internal/util/StringOps.scala +++ b/src/reflect/scala/reflect/internal/util/StringOps.scala @@ -11,7 +11,7 @@ package reflect package internal package util -import scala.compat.Platform.EOL +import java.lang.System.{lineSeparator => EOL} /** This object provides utility methods to extract elements * from Strings. @@ -45,7 +45,7 @@ trait StringOps { else s.substring(0, end) } /** Breaks the string into lines and strips each line before reassembling. */ - def trimAllTrailingSpace(s: String): String = s.lines map trimTrailingSpace mkString EOL + def trimAllTrailingSpace(s: String): String = s.lines.map(trimTrailingSpace).mkString(EOL) def decompose(str: String, sep: Char): List[String] = { def ws(start: Int): List[String] = @@ -69,18 +69,17 @@ trait StringOps { else Some((str take idx, str drop (if (doDropIndex) idx + 1 else idx))) /** Returns a string meaning "n elements". + * Don't try an element such as "index" with irregular plural. */ - def countElementsAsString(n: Int, elements: String): String = + def countElementsAsString(n: Int, element: String): String = n match { - case 0 => s"no ${elements}s" - case 1 => "one " + elements - case 2 => "two " + elements + "s" - case 3 => "three " + elements + "s" - case 4 => "four " + elements + "s" - case _ => s"$n ${elements}s" + case 0 => s"no ${element}s" + case 1 => s"one ${element}" + case _ => s"${countAsString(n)} ${element}s" } /** Turns a count into a friendly English description if n<=4. + * Otherwise, a scary math representation. */ def countAsString(n: Int): String = n match { @@ -89,8 +88,8 @@ trait StringOps { case 2 => "two" case 3 => "three" case 4 => "four" - case _ => "" + n + case _ => n.toString } } -object StringOps extends StringOps { } +object StringOps extends StringOps diff --git a/src/reflect/scala/reflect/io/Path.scala b/src/reflect/scala/reflect/io/Path.scala index 5f93506015..c5b5ae24ba 100644 --- a/src/reflect/scala/reflect/io/Path.scala +++ b/src/reflect/scala/reflect/io/Path.scala @@ -107,19 +107,20 @@ class Path private[io] (val jfile: JFile) { def /(child: Directory): Directory = /(child: Path).toDirectory def /(child: File): File = /(child: Path).toFile - /** If this path is a container, recursively iterate over its contents. + /** If this path is a directory, recursively iterate over its contents. * The supplied condition is a filter which is applied to each element, - * with that branch of the tree being closed off if it is true. So for - * example if the condition is true for some subdirectory, nothing - * under that directory will be in the Iterator; but otherwise each - * file and subdirectory underneath it will appear. + * with that branch of the tree being closed off if it is false. + * So for example if the condition is false for some subdirectory, nothing + * under that directory will be in the Iterator. If it's true, all files for + * which the condition holds and are directly in that subdirectory are in the + * Iterator, and all sub-subdirectories are recursively evaluated */ def walkFilter(cond: Path => Boolean): Iterator[Path] = if (isFile) toFile walkFilter cond else if (isDirectory) toDirectory walkFilter cond else Iterator.empty - /** Equivalent to walkFilter(_ => false). + /** Equivalent to walkFilter(_ => true). */ def walk: Iterator[Path] = walkFilter(_ => true) diff --git a/src/reflect/scala/reflect/macros/blackbox/Context.scala b/src/reflect/scala/reflect/macros/blackbox/Context.scala index ce28b5911e..205e3ad1c3 100644 --- a/src/reflect/scala/reflect/macros/blackbox/Context.scala +++ b/src/reflect/scala/reflect/macros/blackbox/Context.scala @@ -26,7 +26,7 @@ package blackbox * Refer to the documentation of top-level traits in this package to learn the details. * * If a macro def refers to a macro impl that uses `blackbox.Context`, then this macro def becomes a blackbox macro, - * which means that its expansion will be upcast to its return type, enforcing faithfullness of that macro to its + * which means that its expansion will be upcast to its return type, enforcing faithfulness of that macro to its * type signature. Whitebox macros, i.e. the ones defined with `whitebox.Context`, aren't bound by this restriction, * which enables a number of important use cases, but they are also going to enjoy less support than blackbox macros, * so choose wisely. See the [[http://docs.scala-lang.org/overviews/macros/overview.html Macros Guide]] for more information. diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 95d6662d14..9138ed3f02 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -429,6 +429,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.hijackedCoreClasses definitions.symbolsNotPresentInBytecode definitions.isPossibleSyntheticParent + definitions.ShowAsInfixAnnotationClass definitions.abbrvTag definitions.numericWeight definitions.boxedModule |