diff options
28 files changed, 310 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala index 5be5abd895..dd2d63ad17 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeTypes.scala @@ -835,6 +835,7 @@ abstract class BCodeTypes extends BCodeIdiomatic { if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0, if (sym.isArtifact) ACC_SYNTHETIC else 0, if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, + if (sym.hasEnumFlag) ACC_ENUM else 0, if (sym.isVarargsMethod) ACC_VARARGS else 0, if (sym.hasFlag(symtab.Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0 ) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index e92f8c2541..7e1a82a155 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -244,6 +244,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0, if (sym.isArtifact) ACC_SYNTHETIC else 0, if (sym.isClass && !sym.isInterface) ACC_SUPER else 0, + if (sym.hasEnumFlag) ACC_ENUM else 0, if (sym.isVarargsMethod) ACC_VARARGS else 0, if (sym.hasFlag(Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0 ) diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 7932dd3459..9875d27047 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -792,7 +792,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val superclazz = AppliedTypeTree(javaLangDot(tpnme.Enum), List(enumType)) addCompanionObject(consts ::: statics ::: predefs, atPos(pos) { - ClassDef(mods, name, List(), + ClassDef(mods | Flags.ENUM, name, List(), makeTemplate(superclazz :: interfaces, body)) }) } @@ -811,10 +811,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { skipAhead() accept(RBRACE) } - // The STABLE flag is to signal to namer that this was read from a - // java enum, and so should be given a Constant type (thereby making - // it usable in annotations.) - ValDef(Modifiers(Flags.STABLE | Flags.JAVA | Flags.STATIC), name.toTermName, enumType, blankExpr) + ValDef(Modifiers(Flags.ENUM | Flags.STABLE | Flags.JAVA | Flags.STATIC), name.toTermName, enumType, blankExpr) } } diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala index 183752d4a2..7837f9a11a 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala @@ -126,10 +126,11 @@ object Plugin { } /** Load all plugins specified by the arguments. - * Each of `jars` must be a valid plugin archive or exploded archive. + * Each location of `paths` must be a valid plugin archive or exploded archive. + * Each of `paths` must define one plugin. * Each of `dirs` may be a directory containing arbitrary plugin archives. * Skips all plugins named in `ignoring`. - * A single classloader is created and used to load all of them. + * A classloader is created to load each plugin. */ def loadAllFrom( paths: List[List[Path]], diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 1f9987c83b..6ec364bcb6 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -94,11 +94,11 @@ trait ScalaSettings extends AbsScalaSettings val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.") val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.") val Xverify = BooleanSetting ("-Xverify", "Verify generic signatures in generated bytecode (asm backend only.)") - val plugin = MultiStringSetting("-Xplugin", "file", "Load one or more plugins from files.") - val disable = MultiStringSetting("-Xplugin-disable", "plugin", "Disable the given plugin(s).") + val plugin = MultiStringSetting("-Xplugin", "paths", "Load a plugin from each classpath.") + val disable = MultiStringSetting("-Xplugin-disable", "plugin", "Disable plugins by name.") val showPlugins = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins.") - val require = MultiStringSetting("-Xplugin-require", "plugin", "Abort unless the given plugin(s) are available.") - val pluginsDir = StringSetting ("-Xpluginsdir", "path", "Path to search compiler plugins.", Defaults.scalaPluginPath) + val require = MultiStringSetting("-Xplugin-require", "plugin", "Abort if a named plugin is not loaded.") + val pluginsDir = StringSetting ("-Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath) val Xprint = PhasesSetting ("-Xprint", "Print out program after") val writeICode = PhasesSetting ("-Xprint-icode", "Log internal icode to *.icode files after", "icode") val Xprintpos = BooleanSetting ("-Xprint-pos", "Print tree positions, as offsets.") diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 2b96961291..664645e53e 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -515,7 +515,7 @@ abstract class ClassfileParser { val info = readType() val sym = ownerForFlags(jflags).newValue(name.toTermName, NoPosition, sflags) - // Note: the info may be overrwritten later with a generic signature + // Note: the info may be overwritten later with a generic signature // parsed from SignatureATTR sym setInfo { if (jflags.isEnum) ConstantType(Constant(sym)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 14695f5939..27e8698676 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -122,10 +122,31 @@ trait Namers extends MethodSynthesis { || (vd.mods.isPrivateLocal && !vd.mods.isCaseAccessor) || (vd.name startsWith nme.OUTER) || (context.unit.isJava) + || isEnumConstant(vd) ) + def noFinishGetterSetter(vd: ValDef) = ( (vd.mods.isPrivateLocal && !vd.mods.isLazy) // all lazy vals need accessors, even private[this] - || vd.symbol.isModuleVar) + || vd.symbol.isModuleVar + || isEnumConstant(vd)) + + /** Determines whether this field holds an enum constant. + * To qualify, the following conditions must be met: + * - The field's class has the ENUM flag set + * - The field's class extends java.lang.Enum + * - The field has the ENUM flag set + * - The field is static + * - The field is stable + */ + def isEnumConstant(vd: ValDef) = { + val ownerHasEnumFlag = + // Necessary to check because scalac puts Java's static members into the companion object + // while Scala's enum constants live directly in the class. + // We don't check for clazz.superClass == JavaEnumClass, because this causes a illegal + // cyclic reference error. See the commit message for details. + if (context.unit.isJava) owner.companionClass.hasEnumFlag else owner.hasEnumFlag + vd.mods.hasAllFlags(ENUM | STABLE | STATIC) && ownerHasEnumFlag + } def setPrivateWithin[T <: Symbol](tree: Tree, sym: T, mods: Modifiers): T = if (sym.isPrivateLocal || !mods.hasAccessBoundary) sym @@ -620,11 +641,7 @@ trait Namers extends MethodSynthesis { else enterGetterSetter(tree) - // When java enums are read from bytecode, they are known to have - // constant types by the jvm flag and assigned accordingly. When - // they are read from source, the java parser marks them with the - // STABLE flag, and now we receive that signal. - if (tree.symbol hasAllFlags STABLE | JAVA) + if (isEnumConstant(tree)) tree.symbol setInfo ConstantType(Constant(tree.symbol)) } diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index 3d5a213f2f..54b65166d8 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -169,6 +169,14 @@ trait FlagSets { self: Universe => /** Flag indicating that tree was generated by the compiler */ val SYNTHETIC: FlagSet + + /** Flag indicating that tree represents an enum. + * + * It can only appear at + * - the enum's class + * - enum constants + **/ + val ENUM: FlagSet } /** The empty set of flags diff --git a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala index 19c67879f5..0ca8611719 100644 --- a/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala +++ b/src/reflect/scala/reflect/internal/BaseTypeSeqs.scala @@ -166,9 +166,10 @@ trait BaseTypeSeqs { val index = new Array[Int](nparents) var i = 0 for (p <- parents) { + val parentBts = p.dealias.baseTypeSeq // dealias need for SI-8046. pbtss(i) = - if (p.baseTypeSeq eq undetBaseTypeSeq) AnyClass.info.baseTypeSeq - else p.baseTypeSeq + if (parentBts eq undetBaseTypeSeq) AnyClass.info.baseTypeSeq + else parentBts index(i) = 0 i += 1 } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 38be6fcf56..dde3f1e9f7 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -363,6 +363,7 @@ trait Definitions extends api.StandardDefinitions { lazy val ComparableClass = requiredClass[java.lang.Comparable[_]] modifyInfo fixupAsAnyTrait lazy val JavaCloneableClass = requiredClass[java.lang.Cloneable] lazy val JavaNumberClass = requiredClass[java.lang.Number] + lazy val JavaEnumClass = requiredClass[java.lang.Enum[_]] lazy val RemoteInterfaceClass = requiredClass[java.rmi.Remote] lazy val RemoteExceptionClass = requiredClass[java.rmi.RemoteException] diff --git a/src/reflect/scala/reflect/internal/FlagSets.scala b/src/reflect/scala/reflect/internal/FlagSets.scala index 84825ff2da..799f85054a 100644 --- a/src/reflect/scala/reflect/internal/FlagSets.scala +++ b/src/reflect/scala/reflect/internal/FlagSets.scala @@ -43,5 +43,6 @@ trait FlagSets extends api.FlagSets { self: SymbolTable => val PRESUPER : FlagSet = Flags.PRESUPER val DEFAULTINIT : FlagSet = Flags.DEFAULTINIT val SYNTHETIC : FlagSet = Flags.SYNTHETIC + val ENUM : FlagSet = Flags.ENUM } } diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala index dcdf6728ce..11c1d66190 100644 --- a/src/reflect/scala/reflect/internal/Flags.scala +++ b/src/reflect/scala/reflect/internal/Flags.scala @@ -63,7 +63,7 @@ import scala.collection.{ mutable, immutable } // 45: SYNCHRONIZED/M // 46: ARTIFACT // 47: DEFAULTMETHOD/M -// 48: +// 48: ENUM // 49: // 50: // 51: lateDEFERRED @@ -119,6 +119,7 @@ class ModifierFlags { final val DEFAULTINIT = 1L << 41 // symbol is initialized to the default value: used by -Xcheckinit final val ARTIFACT = 1L << 46 // symbol should be ignored when typechecking; will be marked ACC_SYNTHETIC in bytecode final val DEFAULTMETHOD = 1L << 47 // symbol is a java default method + final val ENUM = 1L << 48 // symbol is an enum /** Symbols which are marked ARTIFACT. (Expand this list?) * @@ -142,7 +143,7 @@ class ModifierFlags { } object ModifierFlags extends ModifierFlags -/** All flags and associated operatins */ +/** All flags and associated operations */ class Flags extends ModifierFlags { final val METHOD = 1 << 6 // a method final val MODULE = 1 << 8 // symbol is module or class implementing a module @@ -446,7 +447,7 @@ class Flags extends ModifierFlags { case SYNCHRONIZED => "<synchronized>" // (1L << 45) case ARTIFACT => "<artifact>" // (1L << 46) case DEFAULTMETHOD => "<defaultmethod>" // (1L << 47) - case 0x1000000000000L => "" // (1L << 48) + case ENUM => "<enum>" // (1L << 48) case 0x2000000000000L => "" // (1L << 49) case 0x4000000000000L => "" // (1L << 50) case `lateDEFERRED` => "<latedeferred>" // (1L << 51) diff --git a/src/reflect/scala/reflect/internal/HasFlags.scala b/src/reflect/scala/reflect/internal/HasFlags.scala index ecbf839bab..1131c94da0 100644 --- a/src/reflect/scala/reflect/internal/HasFlags.scala +++ b/src/reflect/scala/reflect/internal/HasFlags.scala @@ -82,6 +82,7 @@ trait HasFlags { def hasAbstractFlag = hasFlag(ABSTRACT) def hasAccessorFlag = hasFlag(ACCESSOR) def hasDefault = hasFlag(DEFAULTPARAM) && hasFlag(METHOD | PARAM) // Second condition disambiguates with TRAIT + def hasEnumFlag = hasFlag(ENUM) def hasLocalFlag = hasFlag(LOCAL) def hasModuleFlag = hasFlag(MODULE) def hasPackageFlag = hasFlag(PACKAGE) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index d8bbd981b9..e9230aceee 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1998,7 +1998,9 @@ trait Types if (sym.typeParams.size != args.size) devWarning(s"$this.transform($tp), but tparams.isEmpty and args=$args") - asSeenFromOwner(tp).instantiateTypeParams(sym.typeParams, args) + val GenPolyType(tparams, result) = asSeenFromOwner(tp) + assert((tparams eq Nil) || tparams == sym.typeParams, (tparams, sym.typeParams)) + result.instantiateTypeParams(sym.typeParams, args) } // note: does not go through typeRef. There's no need to because @@ -2308,7 +2310,14 @@ trait Types } thisInfo.decls } - protected[Types] def baseTypeSeqImpl: BaseTypeSeq = sym.info.baseTypeSeq map transform + protected[Types] def baseTypeSeqImpl: BaseTypeSeq = + if (sym.info.baseTypeSeq exists (_.typeSymbolDirect.isAbstractType)) + // SI-8046 base type sequence might have more elements in a subclass, we can't map it element wise. + transform(sym.info).baseTypeSeq + else + // Optimization: no abstract types, we can compute the BTS of this TypeRef as an element-wise map + // of the BTS of the referenced symbol. + sym.info.baseTypeSeq map transform override def baseTypeSeq: BaseTypeSeq = { val cache = baseTypeSeqCache diff --git a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala index b60fecd66e..2623a47be6 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeComparers.scala @@ -170,11 +170,20 @@ trait TypeComparers { // corresponds does not check length of two sequences before checking the predicate, // but SubstMap assumes it has been checked (SI-2956) ( sameLength(tparams1, tparams2) - && (tparams1 corresponds tparams2)((p1, p2) => p1.info =:= subst(p2.info)) + && (tparams1 corresponds tparams2)((p1, p2) => methodHigherOrderTypeParamsSameVariance(p1, p2) && p1.info =:= subst(p2.info)) && (res1 =:= subst(res2)) ) } + // SI-2066 This prevents overrides with incompatible variance in higher order type parameters. + private def methodHigherOrderTypeParamsSameVariance(sym1: Symbol, sym2: Symbol) = { + def ignoreVariance(sym: Symbol) = !(sym.isHigherOrderTypeParameter && sym.logicallyEnclosingMember.isMethod) + ignoreVariance(sym1) || ignoreVariance(sym2) || sym1.variance == sym2.variance + } + + private def methodHigherOrderTypeParamsSubVariance(low: Symbol, high: Symbol) = + methodHigherOrderTypeParamsSameVariance(low, high) || low.variance.isInvariant + def isSameType2(tp1: Type, tp2: Type): Boolean = { def retry(lhs: Type, rhs: Type) = ((lhs ne tp1) || (rhs ne tp2)) && isSameType(lhs, rhs) @@ -327,7 +336,10 @@ trait TypeComparers { val substitutes = if (isMethod) tparams1 else cloneSymbols(tparams1) def sub1(tp: Type) = if (isMethod) tp else tp.substSym(tparams1, substitutes) def sub2(tp: Type) = tp.substSym(tparams2, substitutes) - def cmp(p1: Symbol, p2: Symbol) = sub2(p2.info) <:< sub1(p1.info) + def cmp(p1: Symbol, p2: Symbol) = ( + methodHigherOrderTypeParamsSubVariance(p2, p1) + && sub2(p2.info) <:< sub1(p1.info) + ) (tparams1 corresponds tparams2)(cmp) && (sub1(res1) <:< sub2(res2)) } diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index c87995275f..effb97b96d 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -273,6 +273,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => definitions.ComparableClass definitions.JavaCloneableClass definitions.JavaNumberClass + definitions.JavaEnumClass definitions.RemoteInterfaceClass definitions.RemoteExceptionClass definitions.ByNameParamClass diff --git a/test/files/neg/t2066.check b/test/files/neg/t2066.check new file mode 100644 index 0000000000..efade87e26 --- /dev/null +++ b/test/files/neg/t2066.check @@ -0,0 +1,21 @@ +t2066.scala:6: error: overriding method f in trait A1 of type [T[_]]=> Unit; + method f has incompatible type + override def f[T[+_]] = () + ^ +t2066.scala:10: error: overriding method f in trait A1 of type [T[_]]=> Unit; + method f has incompatible type + override def f[T[-_]] = () + ^ +t2066.scala:23: error: overriding method f in trait A2 of type [T[+_]]=> Unit; + method f has incompatible type + override def f[T[-_]] = () + ^ +t2066.scala:45: error: overriding method f in trait A4 of type [T[X[+_]]]=> Unit; + method f has incompatible type + override def f[T[X[_]]] = () + ^ +t2066.scala:53: error: overriding method f in trait A5 of type [T[X[-_]]]=> Unit; + method f has incompatible type + override def f[T[X[_]]] = () + ^ +5 errors found diff --git a/test/files/neg/t2066.scala b/test/files/neg/t2066.scala new file mode 100644 index 0000000000..7f15d39c67 --- /dev/null +++ b/test/files/neg/t2066.scala @@ -0,0 +1,70 @@ +trait A1 { + def f[T[_]] = () +} + +trait B1 extends A1 { + override def f[T[+_]] = () +} + +trait C1 extends A1 { + override def f[T[-_]] = () +} + + +trait A2 { + def f[T[+_]] = () +} + +trait B2 extends A2 { + override def f[T[_]] = () // okay +} + +trait C2 extends A2 { + override def f[T[-_]] = () +} + + +trait A3 { + def f[T[-_]] = () +} + +trait B3 extends A3 { + override def f[T[_]] = () // okay +} + +trait C3 extends A3 { + override def f[T[-_]] = () +} + + +trait A4 { + def f[T[X[+_]]] = () +} + +trait B4 extends A4 { + override def f[T[X[_]]] = () +} + +trait A5 { + def f[T[X[-_]]] = () +} + +trait B5 extends A5 { + override def f[T[X[_]]] = () +} + + + +trait A6 { + def f[T[X[_]]] = () +} + +trait B6 extends A6 { + override def f[T[X[+_]]] = () // okay +} +trait C6 extends A6 { + override def f[T[X[_]]] = () // okay +} +trait D6 extends A6 { + override def f[T[X[-_]]] = () +} diff --git a/test/files/neg/t2066b.check b/test/files/neg/t2066b.check new file mode 100644 index 0000000000..097c44fef3 --- /dev/null +++ b/test/files/neg/t2066b.check @@ -0,0 +1,5 @@ +t2066b.scala:7: error: overriding method f in trait A of type [T[_]](x: T[Int])T[Any]; + method f has incompatible type + def f[T[+_]](x : T[Int]) : T[Any] = x + ^ +one error found diff --git a/test/pending/neg/t2066.scala b/test/files/neg/t2066b.scala index 46177b19f7..46177b19f7 100644 --- a/test/pending/neg/t2066.scala +++ b/test/files/neg/t2066b.scala diff --git a/test/files/pos/t2066.scala b/test/files/pos/t2066.scala new file mode 100644 index 0000000000..30cb99d45c --- /dev/null +++ b/test/files/pos/t2066.scala @@ -0,0 +1,25 @@ +trait A1 { + def f[T[+_]] = () +} + +trait B1 extends A1 { + override def f[T[_]] = () +} + + +trait A2 { + def f[T[-_]] = () +} + +trait B2 extends A2 { + override def f[T[_]] = () +} + + +trait A3 { + def f[T[X[_]]] = () +} + +trait B3 extends A3 { + override def f[T[X[+_]]] = () +} diff --git a/test/files/pos/t8046.scala b/test/files/pos/t8046.scala new file mode 100644 index 0000000000..304d70b6b8 --- /dev/null +++ b/test/files/pos/t8046.scala @@ -0,0 +1,20 @@ +trait One { + type Op[A] + type Alias[A] = Op[A] +} + +trait Two extends One { + trait Op[A] extends (A => A) + + // This compiles + class View1 extends Op[Int] { def apply(xs: Int) = xs } + + // ??? base class View2 not found in basetypes of class View2 + // ./a.scala:9: error: class View2 needs to be abstract, since \ + // method apply in trait Function1 of type (v1: T1)R is not defined + // (Note that T1 does not match Int) + // class View2 extends Alias[Int] { def apply(xs: Int) = xs } + // ^ + // one error found + class View2 extends Alias[Int] { def apply(xs: Int) = xs } +} diff --git a/test/files/pos/t8046b.scala b/test/files/pos/t8046b.scala new file mode 100644 index 0000000000..45b99fd7e0 --- /dev/null +++ b/test/files/pos/t8046b.scala @@ -0,0 +1,16 @@ +trait One { + type Op[A] + type Alias = Op[Int] +} + +trait Two extends One { + trait Op[A] extends M[A] + //(a: Alias) => a.value.toChar // okay + // (=> A).asSeenFrom(a.type, trait M): => Int + class View2 extends Alias { value.toChar } // toChar is not a member of type parameter A + // (=> A).asSeenFrom(View2.this.type, trait M): => A + + // override type Alias = Op[Int] // works with this +} + +trait M[A] { def value: A = sys.error("") } diff --git a/test/files/pos/t8046c.scala b/test/files/pos/t8046c.scala new file mode 100644 index 0000000000..f05b4c15b5 --- /dev/null +++ b/test/files/pos/t8046c.scala @@ -0,0 +1,19 @@ +trait One { + type Op[A] + type Alias[A] = Op[A] +} + +trait Three extends One { + trait Op[A] extends (A => A) + + def f1(f: Op[Int]) = f(5) + def f2(f: Alias[Int]) = f(5) + def f3[T <: Op[Int]](f: T) = f(5) + def f4[T <: Alias[Int]](f: T) = f(5) + // ./a.scala:12: error: type mismatch; + // found : Int(5) + // required: T1 + // def f4[T <: Alias[Int]](f: T) = f(5) + // ^ +} + diff --git a/test/files/run/t8046.check b/test/files/run/t8046.check new file mode 100644 index 0000000000..905b0b35ca --- /dev/null +++ b/test/files/run/t8046.check @@ -0,0 +1,2 @@ +List(trait Op, trait Function1, class Object, class Any) +BTS(T,Three.this.Op[Int],Int => Int,Object,Any) diff --git a/test/files/run/t8046/Test.scala b/test/files/run/t8046/Test.scala new file mode 100644 index 0000000000..f6b525d1b5 --- /dev/null +++ b/test/files/run/t8046/Test.scala @@ -0,0 +1,18 @@ +import scala.tools.partest._ + +object Test extends DirectTest { + override def code = "" + override def extraSettings: String = "-usejavacp" + + override def show() { + val c = newCompiler() + new c.Run + import c._ + + val f4 = typeOf[Three].member(newTermName("f4")) + val f4ParamInfo = f4.paramss.head.head.info + println(f4ParamInfo.baseClasses) + println(f4ParamInfo.baseTypeSeq) + } +} + diff --git a/test/files/run/t8046/t8046c.scala b/test/files/run/t8046/t8046c.scala new file mode 100644 index 0000000000..0b484da530 --- /dev/null +++ b/test/files/run/t8046/t8046c.scala @@ -0,0 +1,13 @@ +import language._ + +trait One { + type Op[A] + type Alias[A] = Op[A] +} + +trait Three extends One { + trait Op[A] extends (A => A) + + def f4[T <: Alias[Int]](f: T) = 0 +} + diff --git a/test/pending/pos/t6161.scala b/test/pending/pos/t6161.scala new file mode 100644 index 0000000000..5783cc85f2 --- /dev/null +++ b/test/pending/pos/t6161.scala @@ -0,0 +1,22 @@ +object t6161 { + trait N { + type Name + } + + trait N1 extends N { + class Name { + type ThisNameType <: Name + def encode: ThisNameType = ??? + } + } + + trait S { + self: N => // change to N1 and it compiles + type NameType <: Name + } + + object g extends S with N1 + + val n1: g.NameType = ??? + val n2: g.Name = n1.encode +} |