summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala8
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala67
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala2
6 files changed, 84 insertions, 13 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index e1740b621e..0fa2762c0f 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -386,10 +386,10 @@ trait Definitions extends reflect.api.StandardDefinitions {
def isCastSymbol(sym: Symbol) = sym == Any_asInstanceOf || sym == Object_asInstanceOf
def isJavaVarArgsMethod(m: Symbol) = m.isMethod && isJavaVarArgs(m.info.params)
- def isJavaVarArgs(params: List[Symbol]) = params.nonEmpty && isJavaRepeatedParamType(params.last.tpe)
- def isScalaVarArgs(params: List[Symbol]) = params.nonEmpty && isScalaRepeatedParamType(params.last.tpe)
- def isVarArgsList(params: List[Symbol]) = params.nonEmpty && isRepeatedParamType(params.last.tpe)
- def isVarArgTypes(formals: List[Type]) = formals.nonEmpty && isRepeatedParamType(formals.last)
+ def isJavaVarArgs(params: Seq[Symbol]) = params.nonEmpty && isJavaRepeatedParamType(params.last.tpe)
+ def isScalaVarArgs(params: Seq[Symbol]) = params.nonEmpty && isScalaRepeatedParamType(params.last.tpe)
+ def isVarArgsList(params: Seq[Symbol]) = params.nonEmpty && isRepeatedParamType(params.last.tpe)
+ def isVarArgTypes(formals: Seq[Type]) = formals.nonEmpty && isRepeatedParamType(formals.last)
def hasRepeatedParam(tp: Type): Boolean = tp match {
case MethodType(formals, restpe) => isScalaVarArgs(formals) || hasRepeatedParam(restpe)
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index e8fb33dafb..6666a49491 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -76,6 +76,73 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def setInternalFlags(flag: Long): this.type = { setFlag(flag); this }
def setTypeSignature(tpe: Type): this.type = { setInfo(tpe); this }
def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this }
+
+ private def lastElemType(ts: Seq[Type]): Type = ts.last.normalize.typeArgs.head
+
+ private def formalTypes(formals: List[Type], nargs: Int): List[Type] = {
+ val formals1 = formals mapConserve {
+ case TypeRef(_, ByNameParamClass, List(arg)) => arg
+ case formal => formal
+ }
+ if (isVarArgTypes(formals1)) {
+ val ft = lastElemType(formals)
+ formals1.init ::: List.fill(nargs - (formals1.length - 1))(ft)
+ } else formals1
+ }
+
+ def resolveOverloaded(pre: Type, targs: Seq[Type], actuals: Seq[Type]): Symbol = {
+ def firstParams(tpe: Type): (List[Symbol], List[Type]) = tpe match {
+ case PolyType(tparams, restpe) =>
+ val (Nil, formals) = firstParams(restpe)
+ (tparams, formals)
+ case MethodType(params, _) =>
+ (Nil, params map (_.tpe))
+ case _ =>
+ (Nil, Nil)
+ }
+ def isApplicable(alt: Symbol, targs: List[Type], actuals: Seq[Type]) = {
+ def isApplicableType(tparams: List[Symbol], tpe: Type): Boolean = {
+ val (tparams, formals) = firstParams(pre memberType alt)
+ val formals1 = formalTypes(formals, actuals.length)
+ val actuals1 =
+ if (isVarArgTypes(actuals)) {
+ if (!isVarArgTypes(formals)) return false
+ actuals.init :+ lastElemType(actuals)
+ } else actuals
+ if (formals1.length != actuals1.length) return false
+
+ if (tparams.isEmpty) return (actuals1 corresponds formals1)(_ <:< _)
+
+ if (targs.length == tparams.length)
+ isApplicableType(List(), tpe.instantiateTypeParams(tparams, targs))
+ else if (targs.nonEmpty)
+ false
+ else {
+ val tvars = tparams map (TypeVar(_))
+ (actuals1 corresponds formals1) { (actual, formal) =>
+ val tp1 = actual.deconst.instantiateTypeParams(tparams, tvars)
+ val pt1 = actual.instantiateTypeParams(tparams, tvars)
+ tp1 <:< pt1
+ } &&
+ solve(tvars, tparams, List.fill(tparams.length)(COVARIANT), upper = false)
+ }
+ }
+ isApplicableType(List(), pre.memberType(alt))
+ }
+ def isAsGood(alt1: Symbol, alt2: Symbol): Boolean = {
+ alt1 == alt2 ||
+ alt2 == NoSymbol || {
+ val (tparams, formals) = firstParams(pre memberType alt1)
+ isApplicable(alt2, tparams map (_.tpe), formals)
+ }
+ }
+ assert(isOverloaded)
+ val applicables = alternatives filter (isApplicable(_, targs.toList, actuals))
+ def winner(alts: List[Symbol]) =
+ ((NoSymbol: Symbol) /: alts)((best, alt) => if (isAsGood(alt, best)) alt else best)
+ val best = winner(applicables)
+ if (best == winner(applicables.reverse)) best else NoSymbol
+ }
}
/** The class for all symbols */
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 5104518dd9..3515c1d521 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -68,7 +68,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
private def normalize(stpe: Type, clazz: Symbol): Type = stpe match {
case PolyType(tparams, restpe) =>
- GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe, clazz))
+ GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe.substSym(tparams takeRight clazz.typeParams.length, clazz.typeParams), clazz))
case MethodType(tparams, restpe) =>
restpe
case _ =>
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index f06e7c3820..6d4dab57a3 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -136,7 +136,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
sym = member.matchingSymbol(bcs.head, base.thisType).suchThat(sym => !sym.hasFlag(DEFERRED | BRIDGE))
bcs = bcs.tail
}
- assert(sym != NoSymbol, member)
sym
}
@@ -339,8 +338,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else if (mixinMember.isSuperAccessor) { // mixin super accessors
val superAccessor = addMember(clazz, mixinMember.cloneSymbol(clazz)) setPos clazz.pos
assert(superAccessor.alias != NoSymbol, superAccessor)
- val alias1 = rebindSuper(clazz, mixinMember.alias, mixinClass)
- superAccessor.asInstanceOf[TermSymbol] setAlias alias1
+
+ rebindSuper(clazz, mixinMember.alias, mixinClass) match {
+ case NoSymbol =>
+ unit.error(clazz.pos, "Member %s of mixin %s is missing a concrete super implementation.".format(
+ mixinMember.alias, mixinClass))
+ case alias1 =>
+ superAccessor.asInstanceOf[TermSymbol] setAlias alias1
+ }
}
else if (mixinMember.isMethod && mixinMember.isModule && mixinMember.hasNoFlags(LIFTED | BRIDGE)) {
// mixin objects: todo what happens with abstract objects?
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 5a7c015f09..68a722aab4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -662,7 +662,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
// Check the remainder for invalid absoverride.
- for (member <- rest ; if ((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz))) {
+ for (member <- rest ; if (member.isAbstractOverride && member.isIncompleteIn(clazz))) {
val other = member.superSymbol(clazz)
val explanation =
if (other != NoSymbol) " and overrides incomplete superclass member " + infoString(other)
@@ -756,11 +756,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
// 4. Check that every defined member with an `override` modifier overrides some other member.
for (member <- clazz.info.decls)
- if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) &&
- !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) {
+ if (member.isAnyOverride && !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) {
// for (bc <- clazz.info.baseClasses.tail) Console.println("" + bc + " has " + bc.info.decl(member.name) + ":" + bc.info.decl(member.name).tpe);//DEBUG
unit.error(member.pos, member.toString() + " overrides nothing");
- member resetFlag OVERRIDE
+ member resetFlag (OVERRIDE | ABSOVERRIDE) // Any Override
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 94733369a8..43cbea83ff 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -121,7 +121,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
if (sym.isDeferred) {
val member = sym.overridingSymbol(clazz);
if (mix != tpnme.EMPTY || member == NoSymbol ||
- !((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz)))
+ !(member.isAbstractOverride && member.isIncompleteIn(clazz)))
unit.error(sel.pos, ""+sym.fullLocationString+" is accessed from super. It may not be abstract "+
"unless it is overridden by a member declared `abstract' and `override'");
}