diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 30 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 121 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 24 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 9 | ||||
-rw-r--r-- | test/files/neg/bug409.check | 2 | ||||
-rw-r--r-- | test/files/neg/bug877.check | 2 |
8 files changed, 94 insertions, 106 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 690a1643fb..f17c660918 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1937,7 +1937,7 @@ trait Parsers requires SyntaxAnalyzer { in.nextToken() AliasTypeDef(mods, name, tparams, typ()) case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE => - typeBounds(mods | Flags.DEFERRED, name, tparams) // @M: last arg is new + typeBounds(mods | Flags.DEFERRED, name, tparams) case _ => syntaxErrorOrIncomplete("`=', `>:', or `<:' expected", true) EmptyTree @@ -2048,14 +2048,14 @@ trait Parsers requires SyntaxAnalyzer { } in.nextToken() val (parents, argss) = templateParents(isTrait) - val (self1, body1) = templateBodyOpt() + val (self1, body1) = templateBodyOpt(isTrait) (parents, argss, self1, vdefs ::: body1) } else { (List(), List(List()), self, body) } } else { val (parents, argss) = templateParents(isTrait) - val (self, body) = templateBodyOpt() + val (self, body) = templateBodyOpt(isTrait) (parents, argss, self, body) } } @@ -2064,22 +2064,14 @@ trait Parsers requires SyntaxAnalyzer { * TraitTemplateOpt ::= [extends TraitTemplate | TemplateBody] */ def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): (ValDef, Template) = { - val pos = in.currentPos - def acceptEmptyTemplateBody(msg: String) { - if (in.token == LPAREN && settings.migrate.value) - syntaxErrorMigrate("traits may not have parameters") - if (!(isStatSep || in.token == COMMA || in.token == RBRACE || in.token == EOF)) - syntaxError(msg, true) - } + val pos = in.currentPos; val (parents0, argss, self, body) = if (in.token == EXTENDS) { in.nextToken() template(mods hasFlag Flags.TRAIT) } else { newLineOptWhenFollowedBy(LBRACE) - val (self, body) = - if (in.token == LBRACE) templateBody() - else { acceptEmptyTemplateBody("`extends' or `{' expected"); (emptyValDef, List()) } + val (self, body) = templateBodyOpt(mods hasFlag Flags.TRAIT) (List(), List(List()), self, body) } var parents = parents0 @@ -2099,10 +2091,16 @@ trait Parsers requires SyntaxAnalyzer { if (stats.isEmpty) (self, List(EmptyTree)) else result } - def templateBodyOpt(): (ValDef, List[Tree]) = { + def templateBodyOpt(isTrait: boolean): (ValDef, List[Tree]) = { newLineOptWhenFollowedBy(LBRACE) - if (in.token == LBRACE) templateBody() - else (emptyValDef, List()) + if (in.token == LBRACE) { + templateBody() + } else { + if (in.token == LPAREN) + syntaxError((if (isTrait) "parents of traits" else "mixins")+ + " may not have parameters", true) + (emptyValDef, List()) + } } /** Refinement ::= [nl] `{' RefineStat {semi RefineStat} `}' diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index f7f7a7869d..c27cf02811 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1080,7 +1080,7 @@ trait Types requires SymbolTable { cl1 } - override def symbol = if(normalize ne this) normalize.symbol else sym + override def symbol = if (sym.isAliasType) normalize.symbol else sym override def bounds: TypeBounds = if (sym.isAbstractType) transform(thisInfo.bounds).asInstanceOf[TypeBounds] @@ -1102,10 +1102,7 @@ trait Types requires SymbolTable { override def narrow = if (sym.isModuleClass) transform(sym.thisType) else super.narrow - override def prefix: Type = if(normalize ne this) normalize.resultType.prefix else pre -// @M: .resultType because normalisation may eta-expand to a poly type, we want the resultType's prefix, not the surrounding polytype's -// @M: should PolyType override prefix to return resultType.prefix? - + override def prefix: Type = if (sym.isAliasType) normalize.prefix else pre override def typeArgs: List[Type] = args @@ -1114,10 +1111,10 @@ trait Types requires SymbolTable { // @MAT was symbol.unsafeTypeParams, but symbol normalizes now override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]): Type = - if(isHigherKinded) { + if (isHigherKinded) { val substTps = formals.intersect(typeParams) - if(substTps.length == typeParams.length) + if (substTps.length == typeParams.length) typeRef(pre, sym, actuals) else // partial application (needed in infer when bunching type arguments from classes and methods together) typeRef(pre, sym, higherKindedArgs).subst(formals, actuals) @@ -1128,12 +1125,12 @@ trait Types requires SymbolTable { override def isHigherKinded = !typeParams.isEmpty //@M args.isEmpty is checked in typeParams private def higherKindedArgs = typeParams map (.typeConstructor) //@M must be .typeConstructor - private def argsMaybeDummy = if(isHigherKinded) higherKindedArgs else args + private def argsMaybeDummy = if (isHigherKinded) higherKindedArgs else args override def normalize = if (sym.isAliasType) { - if(sym.info.typeParams.length == args.length) // beta-reduce - transform(sym.info.resultType).normalize // cycles have been checked in typeRef -- TODO: .resultType necessary? + if (sym.info.typeParams.length == args.length) // beta-reduce + transform(sym.info.resultType).normalize // cycles have been checked in typeRef else { // eta-expand assert(isHigherKinded) PolyType(typeParams, transform(sym.info.resultType).normalize) @@ -1251,6 +1248,7 @@ trait Types requires SymbolTable { override def parents: List[Type] = resultType.parents override def decls: Scope = resultType.decls override def symbol: Symbol = resultType.symbol + override def prefix: Type = resultType.prefix override def closure: Array[Type] = resultType.closure override def closureDepth: int = resultType.closureDepth override def baseClasses: List[Symbol] = resultType.baseClasses @@ -1316,7 +1314,7 @@ trait Types requires SymbolTable { case class AnnotatedType(attributes: List[AnnotationInfo[Any]], tp: Type) extends Type { override def toString(): String = { val attString = - if(attributes.isEmpty) + if (attributes.isEmpty) "" else attributes.mkString("@", " @", " ") @@ -1338,7 +1336,7 @@ trait Types requires SymbolTable { * receiver. This method is used for methods like singleDeref and widen, * so that the attributes are remembered more frequently. */ private def maybeRewrap(newtp: Type) = - if(newtp eq tp) this else newtp + if (newtp eq tp) this else newtp // ---------------- methods forwarded to tp ------------------ \\ @@ -1349,7 +1347,7 @@ trait Types requires SymbolTable { override def bounds: TypeBounds = { val oftp = tp.bounds oftp match { - case TypeBounds(lo, hi) if((lo eq this) && (hi eq this)) => mkTypeBounds(this,this) + case TypeBounds(lo, hi) if ((lo eq this) && (hi eq this)) => mkTypeBounds(this,this) case _ => oftp } } @@ -1366,7 +1364,7 @@ trait Types requires SymbolTable { override def baseType(clazz: Symbol): Type = tp.baseType(clazz) override def closure: Array[Type] = { val oftp = tp.closure - if((oftp.length == 1 &&) (oftp(0) eq this)) + if ((oftp.length == 1 &&) (oftp(0) eq this)) Array(this) else oftp @@ -1501,7 +1499,6 @@ trait Types requires SymbolTable { def mkConstantType(value: Constant): ConstantType = unique(new ConstantType(value) with UniqueType) - /** The canonical creator for typerefs. */ def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = typeRef(pre, sym, args, 0) @@ -1589,7 +1586,7 @@ trait Types requires SymbolTable { /** A creator for type applications */ def appliedType(tycon: Type, args: List[Type]): Type = - if(args.isEmpty) tycon //@M! `if(args.isEmpty) tycon' is crucial (otherwise we create new types in phases after typer and then they don't get adapted (??)) + if (args.isEmpty) tycon //@M! `if (args.isEmpty) tycon' is crucial (otherwise we create new types in phases after typer and then they don't get adapted (??)) else tycon match { case TypeRef(pre, sym, _) => typeRef(pre, sym, args) case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args) @@ -1600,6 +1597,17 @@ trait Types requires SymbolTable { throw new Error() } + /** A creater for type parameterizations + * If tparams is empty, simply returns result type + */ + def parameterizedType(tparams: List[Symbol], tpe: Type): Type = + if (tparams.isEmpty) tpe + else + PolyType(tparams, tpe match { + case PolyType(List(), tpe1) => tpe1 + case _ => tpe + }) + // Hash consing -------------------------------------------------------------- private var uniques: HashSet[AnyRef] = _ @@ -1743,7 +1751,7 @@ trait Types requires SymbolTable { else tp case AnnotatedType(attribs, atp) => val atp1 = this(atp) - if(atp1 eq atp) + if (atp1 eq atp) tp else AnnotatedType(attribs, atp1) @@ -1872,7 +1880,7 @@ trait Types requires SymbolTable { /** Map target to type, can be tuned by subclasses */ protected def toType(fromtp: Type, t: T): Type - def apply(tp0: Type): Type = if(from.isEmpty) tp0 else { + def apply(tp0: Type): Type = if (from.isEmpty) tp0 else { val tp = mapOver(tp0) def subst(sym: Symbol, from: List[Symbol], to: List[T]): Type = @@ -1915,7 +1923,7 @@ trait Types requires SymbolTable { case TypeRef(pre, _, args) => typeRef(pre, sym, args, variance) case SingleType(pre, _) => singleType(pre, sym, variance) } - override def apply(tp: Type): Type = if(from.isEmpty) tp else { + override def apply(tp: Type): Type = if (from.isEmpty) tp else { def subst(sym: Symbol, from: List[Symbol], to: List[Symbol]): Symbol = if (from.isEmpty) sym else if (matches(from.head, sym)) to.head @@ -2172,14 +2180,7 @@ trait Types requires SymbolTable { * equivalent types. */ def isSameType(tp1: Type, tp2: Type): boolean = { - //@MAT - def isSameTypeNormalize(tp1: Type, tp2: Type): boolean = { - val tp1n= tp1.normalize - val tp2n= tp2.normalize - ((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n) - } - - val res = (tp1, tp2) match { + (tp1, tp2) match { case (ErrorType, _) => true case (WildcardType, _) => true case (_, ErrorType) => true @@ -2213,7 +2214,7 @@ trait Types requires SymbolTable { case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) => sym1 == sym2 && (phase.erasedTypes || pre1 =:= pre2) && // @M! normalize reduces higher-kinded case to PolyType's - ( (tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) + ((tp1.isHigherKinded && tp2.isHigherKinded && tp1.normalize =:= tp2.normalize) || isSameTypes(args1, args2)) case (RefinedType(parents1, ref1), RefinedType(parents2, ref2)) => def isSubScope(s1: Scope, s2: Scope): boolean = s2.toList.forall { @@ -2259,8 +2260,10 @@ trait Types requires SymbolTable { ((origin1 ne tp1) || (origin2 ne tp2)) && (origin1 =:= origin2) } else false } - - (res || isSameTypeNormalize(tp1, tp2)) //@MAT + } || { + val tp1n = tp1.normalize + val tp2n = tp2.normalize + ((tp1n ne tp1) || (tp2n ne tp2)) && isSameType(tp1n, tp2n) } /** Are <code>tps1</code> and <code>tps2</code> lists of pairwise equivalent @@ -2273,32 +2276,24 @@ trait Types requires SymbolTable { var stc: int = 0 private var pendingSubTypes = new collection.mutable.HashSet[SubTypePair] - def isSubType(tp1: Type, tp2: Type): boolean = { - //@MAT - def isSubTypeNormalize(tp1: Type, tp2: Type): boolean = { - val tp1n= tp1.normalize - val tp2n= tp2.normalize - ((tp1n ne tp1) || (tp2n ne tp2)) && isSubType0(tp1n, tp2n) - } - - try { - stc = stc + 1 - if (stc >= LogPendingSubTypesThreshold) { - val p = new SubTypePair(tp1, tp2) - if (pendingSubTypes contains p) - false - else - try { - pendingSubTypes += p - (isSubType0(tp1, tp2) || isSubTypeNormalize(tp1, tp2)) //@MAT - } finally { - pendingSubTypes -= p - } - } else (isSubType0(tp1, tp2) || isSubTypeNormalize(tp1, tp2)) //@MAT - } finally { - stc = stc - 1 - } + def isSubType(tp1: Type, tp2: Type): boolean = try { + stc = stc + 1 + if (stc >= LogPendingSubTypesThreshold) { + val p = new SubTypePair(tp1, tp2) + if (pendingSubTypes contains p) + false + else + try { + pendingSubTypes += p + isSubType0(tp1, tp2) + } finally { + pendingSubTypes -= p + } + } else isSubType0(tp1, tp2) + } finally { + stc = stc - 1 } + /** hook for IDE */ protected def trackTypeIDE(sym : Symbol) : Boolean = true; @@ -2365,12 +2360,6 @@ trait Types requires SymbolTable { List.forall2(tparams1, tparams2) ((p1, p2) => p2.info.substSym(tparams2, tparams1) <:< p1.info) && res1 <:< res2.substSym(tparams2, tparams1)) - case (_, _) if (tp1.isHigherKinded || tp2.isHigherKinded) => - (tp1.symbol == AllClass - || - tp2.symbol == AnyClass // @M Any and Nothing are super-type resp. subtype of every well-kinded type - || // @M! normalize reduces higher-kinded case to PolyType's - (tp1.isHigherKinded && tp2.isHigherKinded) && isSubType0(tp1.normalize, tp2.normalize)) case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) => lo2 <:< lo1 && hi1 <:< hi2 case (BoundedWildcardType(bounds), _) => @@ -2387,6 +2376,12 @@ trait Types requires SymbolTable { atp1 <:< tp2 case (_, AnnotatedType(_,atp2)) => tp1 <:< atp2 + case (_, _) if (tp1.isHigherKinded || tp2.isHigherKinded) => + (tp1.symbol == AllClass + || + tp2.symbol == AnyClass // @M Any and Nothing are super-type resp. subtype of every well-kinded type + || // @M! normalize reduces higher-kinded case to PolyType's + (tp1.isHigherKinded && tp2.isHigherKinded) && isSubType0(tp1.normalize, tp2.normalize)) case (_, TypeRef(pre2, sym2, args2)) if sym2.isAbstractType && !(tp2 =:= tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo) && { if (!inIDE) true else trackTypeIDE(sym2) @@ -2418,6 +2413,10 @@ trait Types requires SymbolTable { case _ => false } + } || { + val tp1n= tp1.normalize + val tp2n= tp2.normalize + ((tp1n ne tp1) || (tp2n ne tp2)) && isSubType0(tp1n, tp2n) } /** Are <code>tps1</code> and <code>tps2</code> lists of equal length such diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 3039b7efef..38b46209c9 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -58,7 +58,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { * </ul> */ val erasure = new TypeMap { - def apply(tp0: Type): Type = { val tp = tp0.normalize + def apply(tp: Type): Type = { //val tp = tp0.normalize MARTIN: I don't think this is needed? tp match { case ConstantType(_) => tp @@ -91,7 +91,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { else removeDoubleObject(parents map this), decls, clazz) case _ => - mapOver(tp).normalize + mapOver(tp)/*.normalize MARTIN: I don't think this is needed?*/ } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index d7554ea95d..fb3e7931cc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -226,8 +226,9 @@ trait Namers requires Analyzer { tskolems } - //@M? Replace type parameters with their TypeSkolems, which can later be deskolemized to the original type param - // (a skolem is a representation of a bound variable when viewed outside its scope?) + /** Replace type parameters with their TypeSkolems, which can later be deskolemized to the original type param + * (a skolem is a representation of a bound variable when viewed outside its scope) + */ def skolemize(tparams: List[AbsTypeDef]): unit = { val tskolems = newTypeSkolems(tparams map (.symbol)) for (val (tparam, tskolem) <- tparams zip tskolems) tparam.symbol = tskolem @@ -368,7 +369,7 @@ trait Namers requires Analyzer { // --- Lazy Type Assignment -------------------------------------------------- def typeCompleter(tree: Tree) = new TypeCompleter(tree) { - override def complete(sym: Symbol): unit = { //@M? toString (on sym/tree/...? don't know exactly) will force a lazy type and execute this method (quantum debugging!) + override def complete(sym: Symbol): unit = { if (settings.debug.value) log("defining " + sym); val tp = typeSig(tree) sym.setInfo(tp) @@ -440,15 +441,6 @@ trait Namers requires Analyzer { vparamss.map(.map(enterValueParam)) } - /** A creator for polytypes. If tparams is empty, simply returns result type */ - private def makePolyType(tparams: List[Symbol], tpe: Type): Type = - if (tparams.isEmpty) tpe - else - PolyType(tparams, tpe match { - case PolyType(List(), tpe1) => tpe1 - case _ => tpe - }); - private def templateSig(templ0: Template): Type = { var templ = templ0 val clazz = context.owner @@ -491,7 +483,7 @@ trait Namers requires Analyzer { context.scope enter self.symbol clazz.thisSym.name = self.name } - makePolyType(tparamSyms, templateSig(impl)) + parameterizedType(tparamSyms, templateSig(impl)) } private def methodSig(tparams: List[AbsTypeDef], vparamss: List[List[ValDef]], @@ -512,7 +504,7 @@ trait Namers requires Analyzer { } def thisMethodType(restype: Type) = - makePolyType( + parameterizedType( tparamSyms, if (vparamSymss.isEmpty) PolyType(List(), restype) else (vparamSymss :\ restype)(makeMethodType)) @@ -623,11 +615,11 @@ trait Namers requires Analyzer { var ht = typer.typedType(hi).tpe if (ht.isError) ht = AnyClass.tpe - makePolyType(tparamSyms, mkTypeBounds(lt, ht)) //@M + parameterizedType(tparamSyms, mkTypeBounds(lt, ht)) //@M } private def aliasTypeSig(tpsym: Symbol, tparams: List[AbsTypeDef], rhs: Tree): Type = - makePolyType(typer.reenterTypeParams(tparams), typer.typedType(rhs).tpe); + parameterizedType(typer.reenterTypeParams(tparams), typer.typedType(rhs).tpe); def typeSig(tree: Tree): Type = { val sym: Symbol = tree.symbol diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 39ff15d671..f4577bac74 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -689,9 +689,11 @@ abstract class RefChecks extends InfoTransform { case TypeTree() => new TypeTraverser { def traverse(tp: Type): TypeTraverser = tp match { - case tr@TypeRef(pre, sym, _) if tr.isHigherKinded => this //@M a higher-kinded typeref doesn't have any args to check - case TypeRef(pre, sym, args) => checkBounds(pre, sym.owner, sym.typeParams, args); this - case _ => this + case TypeRef(pre, sym, args) => + if (!tp.isHigherKinded) checkBounds(pre, sym.owner, sym.typeParams, args) + this + case _ => + this } } traverse tree.tpe diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index cde3d11de2..c000f97967 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1693,7 +1693,7 @@ trait Typers requires Analyzer { // of the type arguments as we don't know which alternative to choose... here we do val args1 = map2Conserve(args, tparams) { //@M! the polytype denotes the expected kind - (arg, tparam) => typedHigherKindedType(arg, makePolyType(tparam.typeParams, AnyClass.tpe)) + (arg, tparam) => typedHigherKindedType(arg, parameterizedType(tparam.typeParams, AnyClass.tpe)) } typedTypeApply(fun, args1) case PolyType(tparams, restpe) if (tparams.length != 0) => @@ -2029,9 +2029,6 @@ trait Typers requires Analyzer { } } - // @M: copied from Namers - def makePolyType(tparams: List[Symbol], tpe: Type) = if (tparams.isEmpty) tpe else PolyType(tparams, tpe) - // begin typed1 val sym: Symbol = tree.symbol if (sym ne null) sym.initialize @@ -2336,7 +2333,7 @@ trait Typers requires Analyzer { // @M maybe the well-kindedness check should be done when checking the type arguments conform to the type parameters' bounds? val args1 = if(args.length == tparams.length) map2Conserve(args, tparams) { //@M! the polytype denotes the expected kind - (arg, tparam) => typedHigherKindedType(arg, makePolyType(tparam.typeParams, AnyClass.tpe)) + (arg, tparam) => typedHigherKindedType(arg, parameterizedType(tparam.typeParams, AnyClass.tpe)) } else { assert(fun1.symbol.info.isInstanceOf[OverloadedType] || fun1.symbol.isError) // @M this branch is hit for an overloaded polymorphic type. @@ -2496,7 +2493,7 @@ trait Typers requires Analyzer { } else if (tparams.length == args.length) { // @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer) val args1 = map2Conserve(args, tparams) { - (arg, tparam) => typedHigherKindedType(arg, makePolyType(tparam.typeParams, AnyClass.tpe)) //@M! the polytype denotes the expected kind + (arg, tparam) => typedHigherKindedType(arg, parameterizedType(tparam.typeParams, AnyClass.tpe)) //@M! the polytype denotes the expected kind } val argtypes = args1 map (.tpe) val owntype = if (tpt1.symbol.isClass || tpt1.symbol.isTypeMember) // @M! added the latter condition diff --git a/test/files/neg/bug409.check b/test/files/neg/bug409.check index 52327d54a5..296a85ab73 100644 --- a/test/files/neg/bug409.check +++ b/test/files/neg/bug409.check @@ -1,4 +1,4 @@ -bug409.scala:6: error: ';' expected but '(' found. +bug409.scala:6: error: mixins may not have parameters class Toto extends Expr with Case1(12); ^ one error found diff --git a/test/files/neg/bug877.check b/test/files/neg/bug877.check index 297dfe6a97..6c262cdcb9 100644 --- a/test/files/neg/bug877.check +++ b/test/files/neg/bug877.check @@ -1,4 +1,4 @@ -bug877.scala:3: error: ';' expected but '(' found. +bug877.scala:3: error: parents of traits may not have parameters trait Foo extends A(22A, Bug!) {} ^ one error found |