diff options
Diffstat (limited to 'src/compiler')
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'"); } |