summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-09-14 12:10:57 -0700
committerPaul Phillips <paulp@improving.org>2012-09-15 08:01:19 -0700
commit3262f7072b4060b1058acb6d772eaa61d4dec1d4 (patch)
tree8a4e0f285145d1f429096ad8dc08b90e846b5c38 /src/compiler/scala/tools/nsc/typechecker
parent930c85d6c96507d798d1847ea078eebf93dc0acb (diff)
parent83c1b1062957e50e5336c1b3409e54e0a5cce275 (diff)
downloadscala-3262f7072b4060b1058acb6d772eaa61d4dec1d4.tar.gz
scala-3262f7072b4060b1058acb6d772eaa61d4dec1d4.tar.bz2
scala-3262f7072b4060b1058acb6d772eaa61d4dec1d4.zip
Merge remote-tracking branch 'origin/2.10.x' into merge-210
* origin/2.10.x: (68 commits) Eliminate breaking relative names in source. "Hot fix" for broken build. Fix SI-4813 - Clone doesn't work on LinkedList. Made 'def clone()' consistent with parens everywhere. accommodates pull request feedback SI-6310 redeploys the starr SI-6310 AbsTypeTag => WeakTypeTag SI-6323 outlaws free types from TypeTag SI-6323 prohibits reflection against free types improvements for reification of free symbols removes build.newFreeExistential SI-6359 Deep prohibition of templates in value class Fixes SI-6259. Unable to use typeOf in super call of top-level object. Fixes binary repo push for new typesafe repo layouts. Better error message for pattern arity errors. Rescued TreeBuilder from the parser. Pending test for SI-3943 Test case for a bug fixed in M7. Fix for SI-6367, exponential time in inference. SI-6306 Remove incorrect eta-expansion optimization in Uncurry ... Conflicts: src/compiler/scala/tools/nsc/transform/AddInterfaces.scala src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala14
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala50
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala33
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Tags.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala64
16 files changed, 172 insertions, 94 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 8218289f93..3526d932d3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc
package typechecker
-import reflect.internal.util.Statistics
+import scala.reflect.internal.util.Statistics
/** The main attribution phase.
*/
@@ -72,7 +72,7 @@ trait Analyzer extends AnyRef
}
object typerFactory extends SubComponent {
- import reflect.internal.TypesStats.typerNanos
+ import scala.reflect.internal.TypesStats.typerNanos
val global: Analyzer.this.global.type = Analyzer.this.global
val phaseName = "typer"
val runsAfter = List[String]()
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 6b69184d0a..f9f61b10a4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -467,9 +467,6 @@ trait ContextErrors {
def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) =
NormalTypeError(tree, "macros application do not support named and/or default arguments")
- def WrongNumberOfArgsError(tree: Tree, fun: Tree) =
- NormalTypeError(tree, "wrong number of arguments for "+ treeSymTypeMsg(fun))
-
def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) =
NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun))
@@ -509,8 +506,8 @@ trait ContextErrors {
def TooManyArgsPatternError(fun: Tree) =
NormalTypeError(fun, "too many arguments for unapply pattern, maximum = "+definitions.MaxTupleArity)
- def WrongNumberArgsPatternError(tree: Tree, fun: Tree) =
- NormalTypeError(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
+ def WrongNumberOfArgsError(tree: Tree, fun: Tree) =
+ NormalTypeError(tree, "wrong number of arguments for "+ treeSymTypeMsg(fun))
def ApplyWithoutArgsError(tree: Tree, fun: Tree) =
NormalTypeError(tree, fun.tpe+" does not take parameters")
@@ -738,7 +735,7 @@ trait ContextErrors {
)
val forgotten = (
if (sym.isTerm) "splice when splicing this variable into a reifee"
- else "c.AbsTypeTag annotation for this type parameter"
+ else "c.WeakTypeTag annotation for this type parameter"
)
macroExpansionError(expandee, template(sym.name.nameKind).format(sym.name + " " + sym.origin, forgotten))
}
@@ -1234,7 +1231,7 @@ trait ContextErrors {
message + suffix
}
- private def abbreviateCoreAliases(s: String): String = List("AbsTypeTag", "Expr").foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x))
+ private def abbreviateCoreAliases(s: String): String = List("WeakTypeTag", "Expr").foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x))
private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = {
var argsPart = (pss map (ps => ps map (_.defString) mkString ("(", ", ", ")"))).mkString
@@ -1313,7 +1310,7 @@ trait ContextErrors {
// aXXX (e.g. aparams) => characteristics of the macro impl ("a" stands for "actual")
// rXXX (e.g. rparams) => characteristics of a reference macro impl signature synthesized from the macro def ("r" stands for "reference")
- def MacroImplNonTagImplicitParameters(params: List[Symbol]) = compatibilityError("macro implementations cannot have implicit parameters other than AbsTypeTag evidences")
+ def MacroImplNonTagImplicitParameters(params: List[Symbol]) = compatibilityError("macro implementations cannot have implicit parameters other than WeakTypeTag evidences")
def MacroImplParamssMismatchError() = compatibilityError("number of parameter sections differ")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 6a908c6c65..dbf769c79f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -8,7 +8,7 @@ package typechecker
import symtab.Flags._
import scala.collection.mutable.{LinkedHashSet, Set}
-import annotation.tailrec
+import scala.annotation.tailrec
/**
* @author Martin Odersky
diff --git a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala
index 5802d36878..6a21639391 100644
--- a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc
package typechecker
-import language.implicitConversions
+import scala.language.implicitConversions
/** A generic means of breaking down types into their subcomponents.
* Types are decomposed top down, and recognizable substructure is
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index 745250e167..2dd0836322 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -29,7 +29,7 @@ abstract class Duplicators extends Analyzer {
* the old class with the new class, and map symbols through the given 'env'. The
* environment is a map from type skolems to concrete types (see SpecializedTypes).
*/
- def retyped(context: Context, tree: Tree, oldThis: Symbol, newThis: Symbol, env: collection.Map[Symbol, Type]): Tree = {
+ def retyped(context: Context, tree: Tree, oldThis: Symbol, newThis: Symbol, env: scala.collection.Map[Symbol, Type]): Tree = {
if (oldThis ne newThis) {
oldClassOwner = oldThis
newClassOwner = newThis
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 6a91922b4c..e3f0756b6c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -11,13 +11,13 @@
package scala.tools.nsc
package typechecker
-import annotation.tailrec
+import scala.annotation.tailrec
import scala.collection.{ mutable, immutable }
import mutable.{ LinkedHashMap, ListBuffer }
import scala.util.matching.Regex
import symtab.Flags._
import scala.reflect.internal.util.Statistics
-import language.implicitConversions
+import scala.language.implicitConversions
/** This trait provides methods to find various kinds of implicits.
*
@@ -1151,7 +1151,7 @@ trait Implicits {
private def TagSymbols = TagMaterializers.keySet
private val TagMaterializers = Map[Symbol, Symbol](
ClassTagClass -> MacroInternal_materializeClassTag,
- AbsTypeTagClass -> MacroInternal_materializeAbsTypeTag,
+ WeakTypeTagClass -> MacroInternal_materializeWeakTypeTag,
TypeTagClass -> MacroInternal_materializeTypeTag
)
@@ -1217,14 +1217,14 @@ trait Implicits {
private val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass)
/** Creates a tree that calls the relevant factory method in object
- * reflect.Manifest for type 'tp'. An EmptyTree is returned if
+ * scala.reflect.Manifest for type 'tp'. An EmptyTree is returned if
* no manifest is found. todo: make this instantiate take type params as well?
*/
private def manifestOfType(tp: Type, flavor: Symbol): SearchResult = {
val full = flavor == FullManifestClass
val opt = flavor == OptManifestClass
- /** Creates a tree that calls the factory method called constructor in object reflect.Manifest */
+ /** Creates a tree that calls the factory method called constructor in object scala.reflect.Manifest */
def manifestFactoryCall(constructor: String, tparg: Type, args: Tree*): Tree =
if (args contains EmptyTree) EmptyTree
else typedPos(tree.pos.focus) {
@@ -1472,7 +1472,7 @@ trait Implicits {
interpolate(msg, Map((typeParamNames zip typeArgs): _*)) // TODO: give access to the name and type of the implicit argument, etc?
def validate: Option[String] = {
- import scala.util.matching.Regex; import collection.breakOut
+ import scala.util.matching.Regex; import scala.collection.breakOut
// is there a shorter way to avoid the intermediate toList?
val refs = """\$\{([^}]+)\}""".r.findAllIn(msg).matchData.map(_ group 1).toSet
val decls = typeParamNames.toSet
@@ -1492,7 +1492,7 @@ trait Implicits {
object ImplicitsStats {
- import reflect.internal.TypesStats._
+ import scala.reflect.internal.TypesStats._
val rawTypeImpl = Statistics.newSubCounter (" of which in implicits", rawTypeCount)
val subtypeImpl = Statistics.newSubCounter(" of which in implicit", subtypeCount)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 96dcbb5b80..12766116d1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -941,10 +941,13 @@ trait Infer {
/** Is sym1 (or its companion class in case it is a module) a subclass of
* sym2 (or its companion class in case it is a module)?
*/
- def isProperSubClassOrObject(sym1: Symbol, sym2: Symbol): Boolean =
- sym1 != sym2 && sym1 != NoSymbol && (sym1 isSubClass sym2) ||
- sym1.isModuleClass && isProperSubClassOrObject(sym1.linkedClassOfClass, sym2) ||
- sym2.isModuleClass && isProperSubClassOrObject(sym1, sym2.linkedClassOfClass)
+ def isProperSubClassOrObject(sym1: Symbol, sym2: Symbol): Boolean = (
+ (sym1 != sym2) && (sym1 != NoSymbol) && (
+ (sym1 isSubClass sym2)
+ || (sym1.isModuleClass && isProperSubClassOrObject(sym1.linkedClassOfClass, sym2))
+ || (sym2.isModuleClass && isProperSubClassOrObject(sym1, sym2.linkedClassOfClass))
+ )
+ )
/** is symbol `sym1` defined in a proper subclass of symbol `sym2`?
*/
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 01e773e528..7e9b288853 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -7,7 +7,7 @@ import scala.tools.nsc.util.ClassPath._
import scala.reflect.runtime.ReflectionUtils
import scala.collection.mutable.ListBuffer
import scala.compat.Platform.EOL
-import reflect.internal.util.Statistics
+import scala.reflect.internal.util.Statistics
import scala.reflect.macros.util._
import java.lang.{Class => jClass}
import java.lang.reflect.{Array => jArray, Method => jMethod}
@@ -26,7 +26,7 @@ import scala.reflect.macros.runtime.AbortMacroException
*
* Then fooBar needs to point to a static method of the following form:
*
- * def fooBar[T: c.AbsTypeTag] // type tag annotation is optional
+ * def fooBar[T: c.WeakTypeTag] // type tag annotation is optional
* (c: scala.reflect.macros.Context)
* (xs: c.Expr[List[T]])
* : c.Expr[T] = {
@@ -84,7 +84,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
val methName: String,
// flattens the macro impl's parameter lists having symbols replaced with metadata
// currently metadata is an index of the type parameter corresponding to that type tag (if applicable)
- // f.ex. for: def impl[T: AbsTypeTag, U: AbsTypeTag, V](c: Context)(x: c.Expr[T]): (U, V) = ???
+ // f.ex. for: def impl[T: WeakTypeTag, U: WeakTypeTag, V](c: Context)(x: c.Expr[T]): (U, V) = ???
// `signature` will be equal to List(-1, -1, 0, 1)
val signature: List[Int],
// type arguments part of a macro impl ref (the right-hand side of a macro definition)
@@ -216,7 +216,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
/** Transforms parameters lists of a macro impl.
- * The `transform` function is invoked only for AbsTypeTag evidence parameters.
+ * The `transform` function is invoked only for WeakTypeTag evidence parameters.
*
* The transformer takes two arguments: a value parameter from the parameter list
* and a type parameter that is witnesses by the value parameter.
@@ -232,7 +232,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
if (paramss.isEmpty || paramss.last.isEmpty) return paramss // no implicit parameters in the signature => nothing to do
if (paramss.head.isEmpty || !(paramss.head.head.tpe <:< MacroContextClass.tpe)) return paramss // no context parameter in the signature => nothing to do
def transformTag(param: Symbol): Symbol = param.tpe.dealias match {
- case TypeRef(SingleType(SingleType(NoPrefix, c), universe), AbsTypeTagClass, targ :: Nil)
+ case TypeRef(SingleType(SingleType(NoPrefix, c), universe), WeakTypeTagClass, targ :: Nil)
if c == paramss.head.head && universe == MacroContextUniverse =>
transform(param, targ.typeSymbol)
case _ =>
@@ -336,7 +336,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
RepeatedParamClass.typeConstructor,
List(implType(isType, sigma(origTpe.typeArgs.head))))
else {
- val tsym = getMember(MacroContextClass, if (isType) tpnme.AbsTypeTag else tpnme.Expr)
+ val tsym = getMember(MacroContextClass, if (isType) tpnme.WeakTypeTag else tpnme.Expr)
typeRef(singleType(NoPrefix, ctxParam), tsym, List(sigma(origTpe)))
}
val paramCache = collection.mutable.Map[Symbol, Symbol]()
@@ -630,7 +630,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
macroDef.owner)
} else
targ.tpe
- if (tpe.isConcrete) context.TypeTag(tpe) else context.AbsTypeTag(tpe)
+ context.WeakTypeTag(tpe)
})
macroTraceVerbose("tags: ")(tags)
@@ -832,7 +832,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
var hasPendingMacroExpansions = false
private val delayed = perRunCaches.newWeakMap[Tree, collection.mutable.Set[Int]]
private def isDelayed(expandee: Tree) = delayed contains expandee
- private def calculateUndetparams(expandee: Tree): collection.mutable.Set[Int] =
+ private def calculateUndetparams(expandee: Tree): scala.collection.mutable.Set[Int] =
delayed.get(expandee).getOrElse {
val calculated = collection.mutable.Set[Symbol]()
expandee foreach (sub => {
@@ -872,13 +872,13 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
new Transformer {
override def transform(tree: Tree) = super.transform(tree match {
// todo. expansion should work from the inside out
- case wannabe if (delayed contains wannabe) && calculateUndetparams(wannabe).isEmpty =>
- val context = wannabe.attachments.get[MacroRuntimeAttachment].get.typerContext
- delayed -= wannabe
+ case tree if (delayed contains tree) && calculateUndetparams(tree).isEmpty =>
+ val context = tree.attachments.get[MacroRuntimeAttachment].get.typerContext
+ delayed -= tree
context.implicitsEnabled = typer.context.implicitsEnabled
context.enrichmentEnabled = typer.context.enrichmentEnabled
context.macrosEnabled = typer.context.macrosEnabled
- macroExpand(newTyper(context), wannabe, EXPRmode, WildcardType)
+ macroExpand(newTyper(context), tree, EXPRmode, WildcardType)
case _ =>
tree
})
@@ -886,7 +886,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
}
object MacrosStats {
- import reflect.internal.TypesStats.typerNanos
+ import scala.reflect.internal.TypesStats.typerNanos
val macroExpandCount = Statistics.newCounter ("#macro expansions", "typer")
val macroExpandNanos = Statistics.newSubTimer("time spent in macroExpand", typerNanos)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index 4f597f97c9..91dcd90962 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -10,7 +10,7 @@ import scala.collection.{ mutable, immutable }
import scala.reflect.internal.util.StringOps.{ ojoin }
import scala.reflect.ClassTag
import scala.reflect.runtime.{ universe => ru }
-import language.higherKinds
+import scala.language.higherKinds
/** Logic related to method synthesis which involves cooperation between
* Namer and Typer.
@@ -369,7 +369,7 @@ trait MethodSynthesis {
}
/** A synthetic method which performs the implicit conversion implied by
- * the declaration of an implicit class. Yet to be written.
+ * the declaration of an implicit class.
*/
case class ImplicitClassWrapper(tree: ClassDef) extends DerivedFromClassDef {
def completer(sym: Symbol): Type = ??? // not needed
@@ -377,7 +377,7 @@ trait MethodSynthesis {
def derivedSym: Symbol = {
// Only methods will do! Don't want to pick up any stray
// companion objects of the same name.
- val result = enclClass.info decl name suchThat (_.isMethod)
+ val result = enclClass.info decl name suchThat (x => x.isMethod && x.isSynthetic)
assert(result != NoSymbol, "not found: "+name+" in "+enclClass+" "+enclClass.info.decls)
result
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 18b3fe5f4c..7f14216e76 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -359,10 +359,39 @@ trait Namers extends MethodSynthesis {
}
}
+ /** Given a ClassDef or ModuleDef, verifies there isn't a companion which
+ * has been defined in a separate file.
+ */
+ private def validateCompanionDefs(tree: ImplDef) {
+ val sym = tree.symbol
+ if (sym eq NoSymbol) return
+
+ val ctx = if (context.owner.isPackageObjectClass) context.outer else context
+ val module = if (sym.isModule) sym else ctx.scope lookup tree.name.toTermName
+ val clazz = if (sym.isClass) sym else ctx.scope lookup tree.name.toTypeName
+ val fails = (
+ module.isModule
+ && clazz.isClass
+ && !module.isSynthetic
+ && !clazz.isSynthetic
+ && (clazz.sourceFile ne null)
+ && (module.sourceFile ne null)
+ && !(module isCoDefinedWith clazz)
+ )
+ if (fails) {
+ context.unit.error(tree.pos, (
+ s"Companions '$clazz' and '$module' must be defined in same file:\n"
+ + s" Found in ${clazz.sourceFile.canonicalPath} and ${module.sourceFile.canonicalPath}")
+ )
+ }
+ }
+
def enterModuleDef(tree: ModuleDef) = {
val sym = enterModuleSymbol(tree)
sym.moduleClass setInfo namerOf(sym).moduleClassTypeCompleter(tree)
sym setInfo completerOf(tree)
+ validateCompanionDefs(tree)
+ sym
}
/** Enter a module symbol. The tree parameter can be either
@@ -467,7 +496,6 @@ trait Namers extends MethodSynthesis {
// for Java code importing Scala objects
if (!nme.isModuleName(from) || isValid(nme.stripModuleSuffix(from))) {
typer.TyperErrorGen.NotAMemberError(tree, expr, from)
- typer.infer.setError(tree)
}
}
// Setting the position at the import means that if there is
@@ -635,6 +663,7 @@ trait Namers extends MethodSynthesis {
}
else context.unit.error(tree.pos, "implicit classes must accept exactly one primary constructor parameter")
}
+ validateCompanionDefs(tree)
}
// this logic is needed in case typer was interrupted half
@@ -699,7 +728,7 @@ trait Namers extends MethodSynthesis {
// }
}
- def moduleClassTypeCompleter(tree: Tree) = {
+ def moduleClassTypeCompleter(tree: ModuleDef) = {
mkTypeCompleter(tree) { sym =>
val moduleSymbol = tree.symbol
assert(moduleSymbol.moduleClass == sym, moduleSymbol.moduleClass)
@@ -1545,18 +1574,11 @@ trait Namers extends MethodSynthesis {
* call this method?
*/
def companionSymbolOf(original: Symbol, ctx: Context): Symbol = {
- try {
- original.companionSymbol orElse {
- ctx.lookup(original.name.companionName, original.owner).suchThat(sym =>
- (original.isTerm || sym.hasModuleFlag) &&
- (sym isCoDefinedWith original)
- )
- }
- }
- catch {
- case e: InvalidCompanions =>
- ctx.unit.error(original.pos, e.getMessage)
- NoSymbol
+ original.companionSymbol orElse {
+ ctx.lookup(original.name.companionName, original.owner).suchThat(sym =>
+ (original.isTerm || sym.hasModuleFlag) &&
+ (sym isCoDefinedWith original)
+ )
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index 14c9aca078..7a035bb33b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -9,12 +9,12 @@ package typechecker
import symtab._
import Flags.{MUTABLE, METHOD, LABEL, SYNTHETIC, ARTIFACT}
-import language.postfixOps
+import scala.language.postfixOps
import scala.tools.nsc.transform.TypingTransformers
import scala.tools.nsc.transform.Transform
import scala.collection.mutable.HashSet
import scala.collection.mutable.HashMap
-import reflect.internal.util.Statistics
+import scala.reflect.internal.util.Statistics
import scala.reflect.internal.Types
/** Translate pattern matching.
@@ -2941,7 +2941,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
// node in the tree that describes how to construct a counter-example
- case class VariableAssignment(variable: Var, equalTo: List[Const], notEqualTo: List[Const], fields: collection.mutable.Map[Symbol, VariableAssignment]) {
+ case class VariableAssignment(variable: Var, equalTo: List[Const], notEqualTo: List[Const], fields: scala.collection.mutable.Map[Symbol, VariableAssignment]) {
// need to prune since the model now incorporates all super types of a constant (needed for reachability)
private lazy val uniqueEqualTo = equalTo filterNot (subsumed => equalTo.exists(better => (better ne subsumed) && instanceOfTpImplies(better.tp, subsumed.tp)))
private lazy val prunedEqualTo = uniqueEqualTo filterNot (subsumed => variable.staticTpCheckable <:< subsumed.tp)
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 93a8dfc9cb..2335a9e3b6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -7,10 +7,10 @@ package scala.tools.nsc
package typechecker
import symtab.Flags._
-import collection.{ mutable, immutable }
+import scala.collection.{ mutable, immutable }
import transform.InfoTransform
import scala.collection.mutable.ListBuffer
-import language.postfixOps
+import scala.language.postfixOps
/** <p>
* Post-attribution checking and transformation.
@@ -38,7 +38,7 @@ import language.postfixOps
*
* @todo Check whether we always check type parameter bounds.
*/
-abstract class RefChecks extends InfoTransform with reflect.internal.transform.RefChecks {
+abstract class RefChecks extends InfoTransform with scala.reflect.internal.transform.RefChecks {
val global: Global // need to repeat here because otherwise last mixin defines global as
// SymbolTable. If we had DOT this would not be an issue
@@ -430,6 +430,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
overrideError("cannot override a macro")
} else {
checkOverrideTypes()
+ checkOverrideDeprecated()
if (settings.warnNullaryOverride.value) {
if (other.paramss.isEmpty && !member.paramss.isEmpty) {
unit.warning(member.pos, "non-nullary method overrides nullary method")
@@ -508,6 +509,14 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
}
}
+
+ def checkOverrideDeprecated() {
+ if (other.hasDeprecatedOverridingAnnotation) {
+ val suffix = other.deprecatedOverridingMessage map (": " + _) getOrElse ""
+ val msg = s"overriding ${other.fullLocationString} is deprecated$suffix"
+ unit.deprecationWarning(member.pos, msg)
+ }
+ }
}
val opc = new overridingPairs.Cursor(clazz)
@@ -1199,6 +1208,23 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case _ =>
}
+ // SI-6276 warn for `def foo = foo` or `val bar: X = bar`, which come up more frequently than you might think.
+ def checkInfiniteLoop(valOrDef: ValOrDefDef) {
+ def callsSelf = valOrDef.rhs match {
+ case t @ (Ident(_) | Select(This(_), _)) =>
+ t hasSymbolWhich (_.accessedOrSelf == valOrDef.symbol)
+ case _ => false
+ }
+ val trivialInifiniteLoop = (
+ !valOrDef.isErroneous
+ && !valOrDef.symbol.isValueParameter
+ && valOrDef.symbol.paramss.isEmpty
+ && callsSelf
+ )
+ if (trivialInifiniteLoop)
+ unit.warning(valOrDef.rhs.pos, s"${valOrDef.symbol.fullLocationString} does nothing other than call itself recursively")
+ }
+
// Transformation ------------------------------------------------------------
/* Convert a reference to a case factory of type `tpe` to a new of the class it produces. */
@@ -1642,6 +1668,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case ValDef(_, _, _, _) | DefDef(_, _, _, _, _, _) =>
checkDeprecatedOvers(tree)
+ checkInfiniteLoop(tree.asInstanceOf[ValOrDefDef])
if (settings.warnNullaryUnit.value)
checkNullaryMethodReturnType(sym)
if (settings.warnInaccessible.value) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 0c9ed29182..2fe8925c95 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -63,7 +63,7 @@ trait SyntheticMethods extends ast.TreeDSL {
// in the original order.
def accessors = clazz.caseFieldAccessors sortBy { acc =>
originalAccessors indexWhere { orig =>
- (acc.name == orig.name) || (acc.name startsWith (orig.name append "$").asInstanceOf[Name]) // [Eugene] why do we need this cast?
+ (acc.name == orig.name) || (acc.name startsWith (orig.name append "$"))
}
}
val arity = accessors.size
@@ -87,7 +87,7 @@ trait SyntheticMethods extends ast.TreeDSL {
)
def forwardToRuntime(method: Symbol): Tree =
- forwardMethod(method, getMember(ScalaRunTimeModule, (method.name prepend "_").asInstanceOf[Name]))(mkThis :: _) // [Eugene] why do we need this cast?
+ forwardMethod(method, getMember(ScalaRunTimeModule, (method.name prepend "_")))(mkThis :: _)
def callStaticsMethod(name: String)(args: Tree*): Tree = {
val method = termMember(RuntimeStaticsModule, name)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala
index d4e4100dfa..44fa9a5d7a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala
@@ -26,7 +26,7 @@ trait Tags {
/** Finds in scope or materializes a ClassTag.
* Should be used instead of ClassManifest every time compiler needs to persist an erasure.
*
- * Once upon a time, we had an `ErasureTag` which was to `ClassTag` the same that `AbsTypeTag` is for `TypeTag`.
+ * Once upon a time, we had an `ErasureTag` which was to `ClassTag` the same that `WeakTypeTag` is for `TypeTag`.
* However we found out that we don't really need this concept, so it got removed.
*
* @param pos Position for error reporting. Please, provide meaningful value.
@@ -43,7 +43,7 @@ trait Tags {
resolveTag(pos, taggedTp, allowMaterialization)
}
- /** Finds in scope or materializes an AbsTypeTag (if `concrete` is false) or a TypeTag (if `concrete` is true).
+ /** Finds in scope or materializes an WeakTypeTag (if `concrete` is false) or a TypeTag (if `concrete` is true).
*
* @param pos Position for error reporting. Please, provide meaningful value.
* @param pre Prefix that represents a universe this type tag will be bound to.
@@ -60,7 +60,7 @@ trait Tags {
* EmptyTree if `allowMaterialization` is false, and there is no array tag in scope.
*/
def resolveTypeTag(pos: Position, pre: Type, tp: Type, concrete: Boolean, allowMaterialization: Boolean = true): Tree = {
- val tagSym = if (concrete) TypeTagClass else AbsTypeTagClass
+ val tagSym = if (concrete) TypeTagClass else WeakTypeTagClass
val tagTp = if (pre == NoType) TypeRef(BaseUniverseClass.toTypeConstructor, tagSym, List(tp)) else singleType(pre, pre member tagSym.name)
val taggedTp = appliedType(tagTp, List(tp))
resolveTag(pos, taggedTp, allowMaterialization)
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index f8a5c401df..e5c0f5767c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -59,6 +59,19 @@ trait TypeDiagnostics {
* the map, the addendum should also be printed.
*/
private var addendums = perRunCaches.newMap[Position, () => String]()
+ private var isTyperInPattern = false
+
+ /** Devising new ways of communicating error info out of
+ * desperation to work on error messages. This is used
+ * by typedPattern to wrap its business so we can generate
+ * a sensible error message when things go south.
+ */
+ def typingInPattern[T](body: => T): T = {
+ val saved = isTyperInPattern
+ isTyperInPattern = true
+ try body
+ finally isTyperInPattern = saved
+ }
def setAddendum(pos: Position, msg: () => String) =
if (pos != NoPosition)
@@ -138,13 +151,17 @@ trait TypeDiagnostics {
def hasParams = tree.tpe.paramSectionCount > 0
def preResultString = if (hasParams) ": " else " of type "
- def nullMessage = "expression of type " + tree.tpe
- def overloadedMessage = "overloaded method " + sym + " with alternatives:\n" + alternativesString(tree)
+ def patternMessage = "pattern " + tree.tpe.finalResultType + valueParamsString(tree.tpe)
+ def exprMessage = "expression of type " + tree.tpe
+ def overloadedMessage = s"overloaded method $sym with alternatives:\n" + alternativesString(tree)
def moduleMessage = "" + sym
def defaultMessage = moduleMessage + preResultString + tree.tpe
def applyMessage = defaultMessage + tree.symbol.locationString
- if (sym == null) nullMessage
+ if ((sym eq null) || (sym eq NoSymbol)) {
+ if (isTyperInPattern) patternMessage
+ else exprMessage
+ }
else if (sym.isOverloaded) overloadedMessage
else if (sym.isModule) moduleMessage
else if (sym.name == nme.apply) applyMessage
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 87937519fc..a58d73bd69 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -13,10 +13,9 @@ package scala.tools.nsc
package typechecker
import scala.collection.mutable
-import scala.reflect.internal.util.BatchSourceFile
+import scala.reflect.internal.util.{ BatchSourceFile, Statistics }
import mutable.ListBuffer
import symtab.Flags._
-import reflect.internal.util.Statistics
// Suggestion check whether we can do without priming scopes with symbols of outer scopes,
// like the IDE does.
@@ -779,7 +778,7 @@ trait Typers extends Modes with Adaptations with Tags {
var raw = featureDesc + " " + req + " be enabled\n" +
"by making the implicit value language." + featureName + " visible."
if (!(currentRun.reportedFeature contains featureTrait))
- raw += "\nThis can be achieved by adding the import clause 'import language." + featureName + "'\n" +
+ raw += "\nThis can be achieved by adding the import clause 'import scala.language." + featureName + "'\n" +
"or by setting the compiler option -language:" + featureName + ".\n" +
"See the Scala docs for value scala.language." + featureName + " for a discussion\n" +
"why the feature " + req + " be explicitly enabled."
@@ -1405,14 +1404,15 @@ trait Typers extends Modes with Adaptations with Tags {
unit.error(clazz.pos, "value class needs to have exactly one public val parameter")
}
}
- body foreach {
- case md: ModuleDef =>
- unit.error(md.pos, "value class may not have nested module definitions")
- case cd: ClassDef =>
- unit.error(cd.pos, "value class may not have nested class definitions")
- case md: DefDef if md.symbol.isConstructor && !md.symbol.isPrimaryConstructor =>
- unit.error(md.pos, "value class may not have secondary constructors")
- case _ =>
+
+ def valueClassMayNotHave(at: Tree, what: String) = unit.error(at.pos, s"value class may not have $what")
+ body.foreach {
+ case dd: DefDef if dd.symbol.isAuxiliaryConstructor => valueClassMayNotHave(dd, "secondary constructors")
+ case t => t.foreach {
+ case md: ModuleDef => valueClassMayNotHave(md, "nested module definitions")
+ case cd: ClassDef => valueClassMayNotHave(cd, "nested class definitions")
+ case _ =>
+ }
}
for (tparam <- clazz.typeParams)
if (tparam hasAnnotation definitions.SpecializedClass)
@@ -1577,6 +1577,12 @@ trait Typers extends Modes with Adaptations with Tags {
if (psym.isFinal)
pending += ParentFinalInheritanceError(parent, psym)
+ if (psym.hasDeprecatedInheritanceAnnotation) {
+ val suffix = psym.deprecatedInheritanceMessage map (": " + _) getOrElse ""
+ val msg = s"inheritance from ${psym.fullLocationString} is deprecated$suffix"
+ unit.deprecationWarning(parent.pos, msg)
+ }
+
if (psym.isSealed && !phase.erasedTypes)
if (context.unit.source.file == psym.sourceFile)
psym addChild context.owner
@@ -1868,7 +1874,7 @@ trait Typers extends Modes with Adaptations with Tags {
* @param rhs ...
*/
def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) {
- log("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug
+ debuglog(s"computing param aliases for $clazz:${clazz.primaryConstructor.tpe}:$rhs")
def decompose(call: Tree): (Tree, List[Tree]) = call match {
case Apply(fn, args) =>
val (superConstr, args1) = decompose(fn)
@@ -2392,7 +2398,7 @@ trait Typers extends Modes with Adaptations with Tags {
else targs.init
def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) =
- if (formals.isEmpty) { MissingParameterTypeAnonMatchError(tree, pt); Nil }
+ if (formals.isEmpty || !formals.forall(isFullyDefined)) { MissingParameterTypeAnonMatchError(tree, pt); Nil }
else methodSym newSyntheticValueParams formals
def mkSel(params: List[Symbol]) =
@@ -3227,7 +3233,7 @@ trait Typers extends Modes with Adaptations with Tags {
val nbSubPats = args.length
val (formals, formalsExpanded) = extractorFormalTypes(resTp, nbSubPats, fun1.symbol)
- if (formals == null) duplErrorTree(WrongNumberArgsPatternError(tree, fun))
+ if (formals == null) duplErrorTree(WrongNumberOfArgsError(tree, fun))
else {
val args1 = typedArgs(args, mode, formals, formalsExpanded)
// This used to be the following (failing) assert:
@@ -3434,7 +3440,7 @@ trait Typers extends Modes with Adaptations with Tags {
}
if (hasError) annotationError
- else AnnotationInfo(annType, List(), nvPairs map {p => (p._1.asInstanceOf[Name], p._2.get)}).setOriginal(Apply(typedFun, args).setPos(ann.pos)) // [Eugene] why do we need this cast?
+ else AnnotationInfo(annType, List(), nvPairs map {p => (p._1, p._2.get)}).setOriginal(Apply(typedFun, args).setPos(ann.pos))
}
} else if (requireJava) {
reportAnnotationError(NestedAnnotationError(ann, annType))
@@ -3813,18 +3819,23 @@ trait Typers extends Modes with Adaptations with Tags {
* - simplest solution: have two method calls
*
*/
- def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] =
+ def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] = {
+ debuglog(s"mkInvoke($cxTree, $tree, $qual, $name)")
acceptsApplyDynamicWithType(qual, name) map { tp =>
// tp eq NoType => can call xxxDynamic, but not passing any type args (unless specified explicitly by the user)
// in scala-virtualized, when not NoType, tp is passed as type argument (for selection on a staged Struct)
- // strip off type application -- we're not doing much with outer, so don't bother preserving cxTree's attributes etc
- val (outer, explicitTargs) = cxTree match {
- case TypeApply(fun, targs) => (fun, targs)
- case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs)
- case t => (t, Nil)
+ // strip off type application -- we're not doing much with outer,
+ // so don't bother preserving cxTree's attributes etc
+ val cxTree1 = cxTree match {
+ case t: ValOrDefDef => t.rhs
+ case t => t
+ }
+ val (outer, explicitTargs) = cxTree1 match {
+ case TypeApply(fun, targs) => (fun, targs)
+ case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs)
+ case t => (t, Nil)
}
-
@inline def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty
// note: context.tree includes at most one Apply node
@@ -3849,6 +3860,7 @@ trait Typers extends Modes with Adaptations with Tags {
atPos(qual.pos)(Apply(tappSel, List(Literal(Constant(name.decode)))))
}
+ }
}
@inline final def deindentTyping() = context.typingIndentLevel -= 2
@@ -4069,7 +4081,7 @@ trait Typers extends Modes with Adaptations with Tags {
if ( !settings.XoldPatmat.value && !isPastTyper
&& thenp1.tpe.annotations.isEmpty && elsep1.tpe.annotations.isEmpty // annotated types need to be lubbed regardless (at least, continations break if you by pass them like this)
&& thenTp =:= elseTp
- ) (thenp1.tpe, false) // use unpacked type
+ ) (thenp1.tpe.deconst, false) // use unpacked type. Important to deconst, as is done in ptOrLub, otherwise `if (???) 0 else 0` evaluates to 0 (SI-6331)
// TODO: skolemize (lub of packed types) when that no longer crashes on files/pos/t4070b.scala
else ptOrLub(thenp1.tpe :: elsep1.tpe :: Nil, pt)
@@ -5454,7 +5466,7 @@ trait Typers extends Modes with Adaptations with Tags {
// as a compromise, context.enrichmentEnabled tells adaptToMember to go ahead and enrich,
// but arbitrary conversions (in adapt) are disabled
// TODO: can we achieve the pattern matching bit of the string interpolation SIP without this?
- context.withImplicitsDisabledAllowEnrichment(typed(tree, PATTERNmode, pt))
+ typingInPattern(context.withImplicitsDisabledAllowEnrichment(typed(tree, PATTERNmode, pt)))
}
/** Types a (fully parameterized) type tree */
@@ -5559,8 +5571,8 @@ trait Typers extends Modes with Adaptations with Tags {
}
object TypersStats {
- import reflect.internal.TypesStats._
- import reflect.internal.BaseTypeSeqsStats._
+ import scala.reflect.internal.TypesStats._
+ import scala.reflect.internal.BaseTypeSeqsStats._
val typedIdentCount = Statistics.newCounter("#typechecked identifiers")
val typedSelectCount = Statistics.newCounter("#typechecked selections")
val typedApplyCount = Statistics.newCounter("#typechecked applications")