diff options
27 files changed, 711 insertions, 614 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 13ddff08c..211683c0a 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -7,6 +7,7 @@ import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, F import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ import Decorators._ import language.higherKinds +import typer.FrontEnd import collection.mutable.ListBuffer import util.Property import reporting.diagnostic.messages._ @@ -363,7 +364,7 @@ object desugar { if (mods.is(Abstract) || hasRepeatedParam) Nil // cannot have default arguments for repeated parameters, hence copy method is not issued else { def copyDefault(vparam: ValDef) = - makeAnnotated(defn.UncheckedVarianceAnnot, refOfDef(vparam)) + makeAnnotated("scala.annotation.unchecked.uncheckedVariance", refOfDef(vparam)) val copyFirstParams = derivedVparamss.head.map(vparam => cpy.ValDef(vparam)(rhs = copyDefault(vparam))) val copyRestParamss = derivedVparamss.tail.nestedMap(vparam => @@ -559,7 +560,7 @@ object desugar { case VarPattern(named, tpt) => derivedValDef(original, named, tpt, rhs, mods) case _ => - val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs) + val rhsUnchecked = makeAnnotated("scala.unchecked", rhs) val vars = getVariables(pat) val isMatchingTuple: Tree => Boolean = { case Tuple(es) => es.length == vars.length @@ -688,11 +689,28 @@ object desugar { new ImplicitFunction(params, body) } - /** Add annotation with class `cls` to tree: - * tree @cls + /** Add annotation to tree: + * tree @fullName + * + * The annotation is usually represented as a TypeTree referring to the class + * with the given name `fullName`. However, if the annotation matches a file name + * that is still to be entered, the annotation is represented as a cascade of `Selects` + * following `fullName`. This is necessary so that we avoid reading an annotation from + * the classpath that is also compiled from source. */ - def makeAnnotated(cls: Symbol, tree: Tree)(implicit ctx: Context) = - Annotated(tree, untpd.New(untpd.TypeTree(cls.typeRef), Nil)) + def makeAnnotated(fullName: String, tree: Tree)(implicit ctx: Context) = { + val parts = fullName.split('.') + val ttree = ctx.typerPhase match { + case phase: FrontEnd if phase.stillToBeEntered(parts.last) => + val prefix = + ((Ident(nme.ROOTPKG): Tree) /: parts.init)((qual, name) => + Select(qual, name.toTermName)) + Select(prefix, parts.last.toTypeName) + case _ => + TypeTree(ctx.requiredClass(fullName).typeRef) + } + Annotated(tree, untpd.New(ttree, Nil)) + } private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(implicit ctx: Context) = { val vdef = ValDef(named.name.asTermName, tpt, rhs) diff --git a/compiler/src/dotty/tools/dotc/config/Config.scala b/compiler/src/dotty/tools/dotc/config/Config.scala index 7744a5479..119af9483 100644 --- a/compiler/src/dotty/tools/dotc/config/Config.scala +++ b/compiler/src/dotty/tools/dotc/config/Config.scala @@ -133,6 +133,8 @@ object Config { */ final val LogPendingFindMemberThreshold = 10 - /** Maximal number of outstanding recursive calls to findMember */ + /** Maximal number of outstanding recursive calls to findMember before backing out + * when findMemberLimit is set. + */ final val PendingFindMemberLimit = LogPendingFindMemberThreshold * 4 } diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 334306f19..8930983f3 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -757,8 +757,14 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { if (args1.isEmpty) args2.isEmpty else args2.nonEmpty && { val v = tparams.head.paramVariance - (v > 0 || isSubType(args2.head, args1.head)) && - (v < 0 || isSubType(args1.head, args2.head)) + def isSub(tp1: Type, tp2: Type) = tp2 match { + case tp2: TypeBounds => + tp2.contains(tp1) + case _ => + (v > 0 || isSubType(tp2, tp1)) && + (v < 0 || isSubType(tp1, tp2)) + } + isSub(args1.head, args2.head) } && isSubArgs(args1.tail, args2.tail, tparams) /** Test whether `tp1` has a base type of the form `B[T1, ..., Tn]` where diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala index f134412a7..c2a7d7ea6 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala @@ -10,7 +10,8 @@ import NameOps._ import Decorators._ import StdNames._ import Annotations._ -import util.SimpleMap +import config.Config +import util.{SimpleMap, Property} import collection.mutable import ast.tpd._ @@ -67,7 +68,10 @@ trait TypeOps { this: Context => // TODO: Make standalone object. if (thiscls.derivesFrom(cls) && pre.baseTypeRef(thiscls).exists) { if (theMap != null && theMap.currentVariance <= 0 && !isLegalPrefix(pre)) { ctx.base.unsafeNonvariant = ctx.runId - AnnotatedType(pre, Annotation(defn.UnsafeNonvariantAnnot, Nil)) + pre match { + case AnnotatedType(_, ann) if ann.symbol == defn.UnsafeNonvariantAnnot => pre + case _ => AnnotatedType(pre, Annotation(defn.UnsafeNonvariantAnnot, Nil)) + } } else pre } @@ -85,13 +89,15 @@ trait TypeOps { this: Context => // TODO: Make standalone object. if (sym.isStatic) tp else { val pre1 = asSeenFrom(tp.prefix, pre, cls, theMap) - if (pre1.isUnsafeNonvariant) - pre1.member(tp.name).info match { + if (pre1.isUnsafeNonvariant) { + val safeCtx = ctx.withProperty(TypeOps.findMemberLimit, Some(())) + pre1.member(tp.name)(safeCtx).info match { case TypeAlias(alias) => // try to follow aliases of this will avoid skolemization. return alias case _ => } + } tp.derivedSelect(pre1) } case tp: ThisType => @@ -546,7 +552,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object. def dynamicsEnabled = featureEnabled(defn.LanguageModuleClass, nme.dynamics) - def testScala2Mode(msg: String, pos: Position) = { + def testScala2Mode(msg: => String, pos: Position) = { if (scala2Mode) migrationWarning(msg, pos) scala2Mode } @@ -554,4 +560,10 @@ trait TypeOps { this: Context => // TODO: Make standalone object. object TypeOps { @sharable var track = false // !!!DEBUG + + /** When a property with this key is set in a context, it limit the number + * of recursive member searches. If the limit is reached, findMember returns + * NoDenotation. + */ + val findMemberLimit = new Property.Key[Unit] } diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 069b4f60d..636204f64 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -217,6 +217,14 @@ object Types { case _ => false } + /** Is this the type of a method with a leading empty parameter list? + */ + def isNullaryMethod(implicit ctx: Context): Boolean = this match { + case MethodType(Nil, _) => true + case tp: PolyType => tp.resultType.isNullaryMethod + case _ => false + } + /** Is this an alias TypeBounds? */ def isAlias: Boolean = this.isInstanceOf[TypeAlias] @@ -573,8 +581,12 @@ object Types { { val recCount = ctx.findMemberCount + 1 ctx.findMemberCount = recCount - if (recCount >= Config.LogPendingFindMemberThreshold) + if (recCount >= Config.LogPendingFindMemberThreshold) { ctx.pendingMemberSearches = name :: ctx.pendingMemberSearches + if (ctx.property(TypeOps.findMemberLimit).isDefined && + ctx.findMemberCount > Config.PendingFindMemberLimit) + return NoDenotation + } } //assert(ctx.findMemberCount < 20) diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 76f82d8af..1e8fb9d26 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -730,7 +730,7 @@ object Parsers { in.token match { case ARROW => functionRest(t :: Nil) - case FORSOME => syntaxError("existential types no longer supported; use a wildcard type or dependent type instead"); t + case FORSOME => syntaxError(ExistentialTypesNoLongerSupported()); t case _ => t } } @@ -783,7 +783,9 @@ object Parsers { */ def simpleType(): Tree = simpleTypeRest { if (in.token == LPAREN) - atPos(in.offset) { makeTupleOrParens(inParens(argTypes())) } + atPos(in.offset) { + makeTupleOrParens(inParens(argTypes(namedOK = false, wildOK = true))) + } else if (in.token == LBRACE) atPos(in.offset) { RefinedTypeTree(EmptyTree, refinement()) } else if (isSimpleLiteral) { SingletonTypeTree(literal()) } @@ -805,7 +807,8 @@ object Parsers { private def simpleTypeRest(t: Tree): Tree = in.token match { case HASH => simpleTypeRest(typeProjection(t)) - case LBRACKET => simpleTypeRest(atPos(startOffset(t)) { AppliedTypeTree(t, typeArgs(namedOK = true)) }) + case LBRACKET => simpleTypeRest(atPos(startOffset(t)) { + AppliedTypeTree(t, typeArgs(namedOK = true, wildOK = true)) }) case _ => t } @@ -826,7 +829,7 @@ object Parsers { /** ArgTypes ::= Type {`,' Type} * | NamedTypeArg {`,' NamedTypeArg} */ - def argTypes(namedOK: Boolean = false) = { + def argTypes(namedOK: Boolean, wildOK: Boolean) = { def otherArgs(first: Tree, arg: () => Tree): List[Tree] = { val rest = if (in.token == COMMA) { @@ -836,8 +839,9 @@ object Parsers { else Nil first :: rest } + def typParser() = if (wildOK) typ() else toplevelTyp() if (namedOK && in.token == IDENTIFIER) - typ() match { + typParser() match { case Ident(name) if in.token == EQUALS => in.nextToken() otherArgs(NamedArg(name, typ()), namedTypeArg) @@ -845,7 +849,7 @@ object Parsers { if (in.token == EQUALS) println(s"??? $firstArg") otherArgs(firstArg, typ) } - else commaSeparated(typ) + else commaSeparated(typParser) } /** FunArgType ::= Type | `=>' Type @@ -873,7 +877,7 @@ object Parsers { /** TypeArgs ::= `[' Type {`,' Type} `]' * NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]' */ - def typeArgs(namedOK: Boolean = false): List[Tree] = inBrackets(argTypes(namedOK)) + def typeArgs(namedOK: Boolean, wildOK: Boolean): List[Tree] = inBrackets(argTypes(namedOK, wildOK)) /** Refinement ::= `{' RefineStatSeq `}' */ @@ -1250,7 +1254,7 @@ object Parsers { in.nextToken() simpleExprRest(selector(t), canApply = true) case LBRACKET => - val tapp = atPos(startOffset(t), in.offset) { TypeApply(t, typeArgs(namedOK = true)) } + val tapp = atPos(startOffset(t), in.offset) { TypeApply(t, typeArgs(namedOK = true, wildOK = false)) } simpleExprRest(tapp, canApply = true) case LPAREN | LBRACE if canApply => val app = atPos(startOffset(t), in.offset) { Apply(t, argumentExprs()) } @@ -1501,7 +1505,7 @@ object Parsers { def simplePatternRest(t: Tree): Tree = { var p = t if (in.token == LBRACKET) - p = atPos(startOffset(t), in.offset) { TypeApply(p, typeArgs()) } + p = atPos(startOffset(t), in.offset) { TypeApply(p, typeArgs(namedOK = false, wildOK = false)) } if (in.token == LPAREN) p = atPos(startOffset(t), in.offset) { Apply(p, argumentPatterns()) } p diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 9dda233bf..b55b7e868 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -5,8 +5,7 @@ package diagnostic import dotc.core._ import Contexts.Context, Decorators._, Symbols._, Names._, NameOps._, Types._ -import util.{SourceFile, NoSource} -import util.{SourcePosition, NoSourcePosition} +import util.SourcePosition import config.Settings.Setting import interfaces.Diagnostic.{ERROR, WARNING, INFO} import printing.Highlighting._ @@ -901,4 +900,27 @@ object messages { val msg = hl"trying to define package with same name as `$existing`" val explanation = "" } + + case class ExistentialTypesNoLongerSupported()(implicit ctx: Context) extends Message(34) { + val kind = "Syntax" + val msg = + hl"""|Existential types are no longer supported - + |use a wildcard or dependent type instead""" + val explanation = + hl"""|The use of existential types is no longer supported. + | + |You should use a wildcard or dependent type instead. + | + |For example: + | + |Instead of using ${"forSome"} to specify a type variable + | + |${"List[T forSome { type T }]"} + | + |Try using a wildcard type variable + | + |${"List[_]"} + |""" + } + } diff --git a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala index 192227261..71ced3175 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimByName.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimByName.scala @@ -71,7 +71,7 @@ class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransform def transformArg(arg: Tree, formal: Type): Tree = formal.dealias match { case formalExpr: ExprType => - val argType = arg.tpe.widen + val argType = arg.tpe.widenIfUnstable val argFun = arg match { case Apply(Select(qual, nme.apply), Nil) if qual.tpe.derivesFrom(defn.FunctionClass(0)) && isPureExpr(qual) => diff --git a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala index 6a273b91e..d01195614 100644 --- a/compiler/src/dotty/tools/dotc/transform/LiftTry.scala +++ b/compiler/src/dotty/tools/dotc/transform/LiftTry.scala @@ -57,7 +57,7 @@ class LiftTry extends MiniPhase with IdentityDenotTransformer { thisTransform => ctx.debuglog(i"lifting tree at ${tree.pos}, current owner = ${ctx.owner}") val fn = ctx.newSymbol( ctx.owner, ctx.freshName("liftedTree").toTermName, Synthetic | Method, - MethodType(Nil, tree.tpe), coord = tree.pos) + MethodType(Nil, tree.tpe.widenIfUnstable), coord = tree.pos) tree.changeOwnerAfter(ctx.owner, fn, thisTransform) Block(DefDef(fn, tree) :: Nil, ref(fn).appliedToNone) } diff --git a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala index fea478c9b..3c11827fc 100644 --- a/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -71,21 +71,24 @@ class SuperAccessors(thisTransformer: DenotTransformer) { val Select(qual, name) = sel val sym = sel.symbol val clazz = qual.symbol.asClass - var supername = name.superName - if (clazz is Trait) supername = supername.expandedName(clazz) - - val superAcc = clazz.info.decl(supername).suchThat(_.signature == sym.signature).symbol orElse { - ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz") - val deferredOrPrivate = if (clazz is Trait) Deferred | ExpandedName else Private - val acc = ctx.newSymbol( - clazz, supername, SuperAccessor | Artifact | Method | deferredOrPrivate, - sel.tpe.widenSingleton.ensureMethodic, coord = sym.coord).enteredAfter(thisTransformer) - // Diagnostic for SI-7091 - if (!accDefs.contains(clazz)) - ctx.error(s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz is Package}. Accessor required for ${sel} (${sel.show})", sel.pos) - else accDefs(clazz) += DefDef(acc, EmptyTree) - acc - } + var superName = name.superName + if (clazz is Trait) superName = superName.expandedName(clazz) + val superInfo = sel.tpe.widenSingleton.ensureMethodic + + val superAcc = clazz.info.decl(superName) + .suchThat(_.signature == superInfo.signature).symbol + .orElse { + ctx.debuglog(s"add super acc ${sym.showLocated} to $clazz") + val deferredOrPrivate = if (clazz is Trait) Deferred | ExpandedName else Private + val acc = ctx.newSymbol( + clazz, superName, SuperAccessor | Artifact | Method | deferredOrPrivate, + superInfo, coord = sym.coord).enteredAfter(thisTransformer) + // Diagnostic for SI-7091 + if (!accDefs.contains(clazz)) + ctx.error(s"Internal error: unable to store accessor definition in ${clazz}. clazz.hasPackageFlag=${clazz is Package}. Accessor required for ${sel} (${sel.show})", sel.pos) + else accDefs(clazz) += DefDef(acc, EmptyTree) + acc + } This(clazz).select(superAcc).withPos(sel.pos) } diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 8a18e63c0..42c24ffb7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -657,18 +657,20 @@ trait Applications extends Compatibility { self: Typer with Dynamic => case err: ErrorType => untpd.cpy.Apply(tree)(fun1, tree.args).withType(err) case TryDynamicCallType => typedDynamicApply(tree, pt) case _ => - tryEither { - implicit ctx => simpleApply(fun1, proto) - } { - (failedVal, failedState) => - def fail = { failedState.commit(); failedVal } - // Try once with original prototype and once (if different) with tupled one. - // The reason we need to try both is that the decision whether to use tupled - // or not was already taken but might have to be revised when an implicit - // is inserted on the qualifier. - tryWithImplicitOnQualifier(fun1, originalProto).getOrElse( - if (proto eq originalProto) fail - else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail)) + if (originalProto.isDropped) fun1 + else + tryEither { + implicit ctx => simpleApply(fun1, proto) + } { + (failedVal, failedState) => + def fail = { failedState.commit(); failedVal } + // Try once with original prototype and once (if different) with tupled one. + // The reason we need to try both is that the decision whether to use tupled + // or not was already taken but might have to be revised when an implicit + // is inserted on the qualifier. + tryWithImplicitOnQualifier(fun1, originalProto).getOrElse( + if (proto eq originalProto) fail + else tryWithImplicitOnQualifier(fun1, proto).getOrElse(fail)) } } } diff --git a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala index cd374e32c..6eff63e2b 100644 --- a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -19,6 +19,15 @@ class FrontEnd extends Phase { override def isTyper = true import ast.tpd + /** The contexts for compilation units that are parsed but not yet entered */ + private var remaining: List[Context] = Nil + + /** Does a source file ending with `<name>.scala` belong to a compilation unit + * that is parsed but not yet entered? + */ + def stillToBeEntered(name: String): Boolean = + remaining.exists(_.compilationUnit.toString.endsWith(name + ".scala")) + def monitor(doing: String)(body: => Unit)(implicit ctx: Context) = try body catch { @@ -75,7 +84,11 @@ class FrontEnd extends Phase { } unitContexts foreach (parse(_)) record("parsedTrees", ast.Trees.ntrees) - unitContexts.foreach(enterSyms(_)) + remaining = unitContexts + while (remaining.nonEmpty) { + enterSyms(remaining.head) + remaining = remaining.tail + } unitContexts.foreach(enterAnnotations(_)) unitContexts.foreach(typeCheck(_)) record("total trees after typer", ast.Trees.ntrees) diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index ed6b95c3b..eb46a131f 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -40,7 +40,9 @@ object ProtoTypes { /** Test compatibility after normalization in a fresh typerstate. */ def normalizedCompatible(tp: Type, pt: Type)(implicit ctx: Context) = { val nestedCtx = ctx.fresh.setExploreTyperState - isCompatible(normalize(tp, pt)(nestedCtx), pt)(nestedCtx) + val normTp = normalize(tp, pt)(nestedCtx) + isCompatible(normTp, pt)(nestedCtx) || + pt.isRef(defn.UnitClass) && normTp.isParameterless } private def disregardProto(pt: Type)(implicit ctx: Context): Boolean = pt.dealias match { @@ -250,6 +252,22 @@ object ProtoTypes { /** Somebody called the `tupled` method of this prototype */ def isTupled: Boolean = myTupled.isInstanceOf[FunProto] + /** If true, the application of this prototype was canceled. */ + private var toDrop: Boolean = false + + /** Cancel the application of this prototype. This can happen for a nullary + * application `f()` if `f` refers to a symbol that exists both in parameterless + * form `def f` and nullary method form `def f()`. A common example for such + * a method is `toString`. If in that case the type in the denotation is + * parameterless, we compensate by dropping the application. + */ + def markAsDropped() = { + assert(args.isEmpty) + toDrop = true + } + + def isDropped: Boolean = toDrop + override def toString = s"FunProto(${args mkString ","} => $resultType)" def map(tm: TypeMap)(implicit ctx: Context): FunProto = diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index dcbd444f9..3192546cd 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -299,7 +299,9 @@ object RefChecks { !member.isAnyOverride) { // (*) Exclusion for default getters, fixes SI-5178. We cannot assign the Override flag to // the default getter: one default getter might sometimes override, sometimes not. Example in comment on ticket. - if (autoOverride(member)) + // Also excluded under Scala2 mode are overrides of default methods of Java traits. + if (autoOverride(member) || + other.owner.is(JavaTrait) && ctx.testScala2Mode("`override' modifier required when a Java 8 default method is re-implemented", member.pos)) member.setFlag(Override) else if (member.owner != clazz && other.owner != clazz && !(other.owner derivesFrom member.owner)) emitOverrideError( @@ -326,7 +328,8 @@ object RefChecks { overrideError("needs to be a stable, immutable value") } else if (member.is(ModuleVal) && !other.isRealMethod && !other.is(Deferred | Lazy)) { overrideError("may not override a concrete non-lazy value") - } else if (member.is(Lazy, butNot = Module) && !other.isRealMethod && !other.is(Lazy)) { + } else if (member.is(Lazy, butNot = Module) && !other.isRealMethod && !other.is(Lazy) && + !ctx.testScala2Mode("may not override a non-lazy value", member.pos)) { overrideError("may not override a non-lazy value") } else if (other.is(Lazy) && !other.isRealMethod && !member.is(Lazy)) { overrideError("must be declared lazy to override a lazy value") diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 07a27a498..fe158dfe2 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1640,13 +1640,19 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case _ => false } - /** Add apply node or implicit conversions. Two strategies are tried, and the first - * that is successful is picked. If neither of the strategies are successful, continues with - * `fallBack`. + /** Potentially add apply node or implicit conversions. Before trying either, + * if the function is applied to an empty parameter list (), we try + * + * 0th strategy: If `tree` overrides a nullary method, mark the prototype + * so that the argument is dropped and return `tree` itself. + * + * After that, two strategies are tried, and the first that is successful is picked. + * If neither of the strategies are successful, continues with`fallBack`. * * 1st strategy: Try to insert `.apply` so that the result conforms to prototype `pt`. * This strategy is not tried if the prototype represents already * another `.apply` or `.apply()` selection. + * * 2nd strategy: If tree is a select `qual.name`, try to insert an implicit conversion * around the qualifier part `qual` so that the result conforms to the expected type * with wildcard result type. @@ -1661,8 +1667,15 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def tryImplicit = tryInsertImplicitOnQualifier(tree, pt).getOrElse(fallBack) - if (isApplyProto(pt)) tryImplicit - else tryEither(tryApply(_))((_, _) => tryImplicit) + pt match { + case pt @ FunProto(Nil, _, _) + if tree.symbol.allOverriddenSymbols.exists(_.info.isNullaryMethod) => + pt.markAsDropped() + tree + case _ => + if (isApplyProto(pt)) tryImplicit + else tryEither(tryApply(_))((_, _) => tryImplicit) + } } /** If this tree is a select node `qual.name`, try to insert an implicit conversion diff --git a/compiler/test/dotc/scala-collections.blacklist b/compiler/test/dotc/scala-collections.blacklist index 97f12244e..7d3008bbc 100644 --- a/compiler/test/dotc/scala-collections.blacklist +++ b/compiler/test/dotc/scala-collections.blacklist @@ -1,221 +1,66 @@ -../scala-scala/src/library/scala/annotation/unchecked/uncheckedVariance.scala +## Errors having to do with bootstrap -../scala-scala/src/library/scala/AnyVal.scala -# 55 |abstract class AnyVal extends Any { -# |^ -# |illegal redefinition of standard class AnyVal +../scala-scala/src/library/scala/Function1.scala +../scala-scala/src/library/scala/Function2.scala +# Cyclic reference because of @specialized annotation -../scala-scala/src/library/scala/collection/convert/Wrappers.scala -# 34 | def remove() = throw new UnsupportedOperationException -# | ^ -# | overriding method remove in trait Iterator of type ()Unit; -# | method remove of type ()Unit needs `override' modifier +## Errors having to do with deep subtypes ../scala-scala/src/library/scala/collection/generic/ParSetFactory.scala - -../scala-scala/src/library/scala/collection/mutable/DefaultEntry.scala -# 22 | "(kv: " + key + ", " + value + ")" + (if (next != null) " -> " + next.toString else "") -# | ^^^^ -# | cyclic reference involving method toString - -../scala-scala/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala -# 78 | override def toString() = imap.toString() -# | ^^^^^^^^^^^^^^^ -# | missing argument for parameter index of method apply: (index: Int)Char - -../scala-scala/src/library/scala/collection/mutable/LinkedHashMap.scala -# 102 | protected class FilteredKeys(p: A => Boolean) extends super.FilteredKeys(p) { -# | ^^^^^^^^^^^^^^^^^^^^ -# | cyclic inheritance: class FilteredKeys extends itself -# ... - -../scala-scala/src/library/scala/collection/mutable/ObservableMap.scala -# assertion failed - -../scala-scala/src/library/scala/collection/mutable/ObservableSet.scala -# 35 | publish(new Include(elem) with Undoable { def undo = -=(elem) }) -# | ^ -# | overriding method undo in trait Undoable of type ()Unit; -# | method undo of type => scala.collection.mutable.ObservableSet[A] has incompatible type - -../scala-scala/src/library/scala/collection/mutable/SynchronizedQueue.scala -# 102 | override def toString() = synchronized { super.toString() } -# | ^^^^^^^^^^^^^^^^ -# | missing argument for parameter index of method apply: (index: Int)Char - -../scala-scala/src/library/scala/collection/mutable/UnrolledBuffer.scala -# 347 | override def toString = array.take(size).mkString("Unrolled[" + array.length + "](", ", ", ")") + " -> " + (if (next ne null) next.toString else "") -# | ^^^^ -# | cyclic reference involving method toString - -../scala-scala/src/library/scala/collection/mutable/SynchronizedBuffer.scala -# assertion failed - -../scala-scala/src/library/scala/collection/parallel/mutable/ParArray.scala -# 648 | class Map[S](f: T => S, targetarr: Array[Any], offset: Int, howmany: Int) extends Task[Unit, Map[S]] { -# | ^ -# | overriding class Map in trait ParIterableLike; -# | class Map cannot be used here - class definitions cannot be overridden +# This gives a deep subtype violation when run with the rest of the whitelist. +# Works without -Yno-deep-subtypes, though. ../scala-scala/src/library/scala/collection/parallel/mutable/ParMap.scala -# 42 | override def updated [U >: V](key: K, value: U): ParMap[K, U] = this + ((key, value)) -# | ^^^^^^^^^^^^^^^^^^^^^ -# | found: scala.collection.parallel.ParMap[K, U] -# | required: scala.collection.parallel.mutable.ParMap'[K, U] -# | -# | where: ParMap is a trait in package parallel -# | ParMap' is a trait in package mutable - - -../scala-scala/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala -# 91 | new { val chain = c } with ResizableParArrayCombiner[T] // was: with EnvironmentPassingCombiner[T, ParArray[T]] -# | ^ -# | early definitions are not supported; use trait parameters instead - -../scala-scala/src/library/scala/collection/parallel/mutable/ParTrieMap.scala -# 136 | it.iterated = this.iterated -# | ^^^^^^^^^^^ -# | value `iterated` is not a member of scala.collection.concurrent.TrieMapIterator[K, V](it) - -../scala-scala/src/library/scala/collection/parallel/package.scala -# 75 | implicit def factory2ops[From, Elem, To](bf: CanBuildFrom[From, Elem, To]) = new FactoryOps[From, Elem, To] { -# | ^ -# | result type of implicit definition needs to be given explicitly - -../scala-scala/src/library/scala/collection/parallel/ParIterable.scala -# 304 | protected implicit def task2ops[R, Tp](tsk: SSCTask[R, Tp]) = new TaskOps[R, Tp] { -# | ^ -# | result type of implicit definition needs to be given explicitly - -../scala-scala/src/library/scala/collection/parallel/ParIterableLike.scala -# 324 | protected implicit def delegatedSignalling2ops[PI <: DelegatedSignalling](it: PI) = new SignallingOps[PI] { -# | ^ -# | result type of implicit definition needs to be given explicitly +# -Yno-deep-subtypes fails ../scala-scala/src/library/scala/collection/parallel/ParMap.scala +# -Yno-deep-subtypes fails + ../scala-scala/src/library/scala/collection/parallel/ParMapLike.scala +# -Yno-deep-subtypes fails + + + +## Ycheck failures, presumably linked to TailCalls + +../scala-scala/src/library/scala/collection/parallel/ParIterableLike.scala +# -Ycheck:classOf fails ../scala-scala/src/library/scala/collection/parallel/ParSeqLike.scala -# 334 | protected trait Accessor[R, Tp] extends super.Accessor[R, Tp] { -# | ^^^^^^^^^^^^^^^^^^^^^ -# | cyclic inheritance: trait Accessor extends itself - -../scala-scala/src/library/scala/collection/parallel/RemainsIterator.scala -# 617 | class Zipped[S](ti: SeqSplitter[S]) extends super.Zipped[S](ti) with SeqSplitter[(T, S)] { -# | ^^^^^^^^^^^^^^^^^^ -# | cyclic inheritance: class Zipped extends itself - -../scala-scala/src/library/scala/collection/parallel/Tasks.scala -# 429 | fjtask.body.result -# | ^^^^^^^^^^^ -# | value `body` is not a member of ForkJoinTasks.this.WrappedTask[R, Tp](fjtask) - -../scala-scala/src/library/scala/concurrent/Future.scala -# 188 | implicit val ec = internalExecutor -# | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -# | type of implicit definition needs to be given explicitly - -../scala-scala/src/library/scala/concurrent/SyncChannel.scala -# 45 | writeReq.get -# | ^^^^^^^^^^^^ -# | none of the overloaded alternatives of method get in class SyncVar with types -# | (timeout: Long)Option[Boolean] -# | => Boolean -# | match expected type Unit - -../scala-scala/src/library/scala/concurrent/impl/ExecutionContextImpl.scala -# assertion failed - -../scala-scala/src/library/scala/concurrent/package.scala -# assertion failed +# -Ycheck:classOf fails + +../scala-scala/src/library/scala/util/control/TailCalls.scala +# -Ycheck:classOf fails + -../scala-scala/src/library/scala/Function1.scala -../scala-scala/src/library/scala/Function2.scala -../scala-scala/src/library/scala/Function3.scala -../scala-scala/src/library/scala/Function4.scala -../scala-scala/src/library/scala/Function5.scala -../scala-scala/src/library/scala/Function6.scala -../scala-scala/src/library/scala/Function7.scala -../scala-scala/src/library/scala/Function8.scala -../scala-scala/src/library/scala/Function9.scala -../scala-scala/src/library/scala/Function10.scala -../scala-scala/src/library/scala/Function11.scala -../scala-scala/src/library/scala/Function12.scala -../scala-scala/src/library/scala/Function13.scala -../scala-scala/src/library/scala/Function14.scala -../scala-scala/src/library/scala/Function15.scala -../scala-scala/src/library/scala/Function16.scala -../scala-scala/src/library/scala/Function17.scala -../scala-scala/src/library/scala/Function18.scala -../scala-scala/src/library/scala/Function19.scala -../scala-scala/src/library/scala/Function20.scala -../scala-scala/src/library/scala/Function21.scala -../scala-scala/src/library/scala/Function22.scala - -../scala-scala/src/library/scala/io/BufferedSource.scala -# 38 | override lazy val iter = ( -# | ^ -# | overriding getter iter in class Source of type => collection.Iterator[Char]; -# | lazy value iter of type collection.Iterator[Char] may not override a non-lazy value - -../scala-scala/src/library/scala/io/Source.scala -# 303 | report(pos, msg, out) -# | ^^^ -# | not found: msg + +## Errors having to do with unavailable APIs or language features: ../scala-scala/src/library/scala/reflect/ClassManifestDeprecatedApis.scala # 51 | import Manifest._ # | ^^^^^^^^ # | not found: Manifest + ../scala-scala/src/library/scala/reflect/ClassTag.scala # 124 | val Short : ClassTag[scala.Short] = Manifest.Short # | ^^^^^^^^ # | not found: Manifest + ../scala-scala/src/library/scala/reflect/Manifest.scala # 104 | private def readResolve(): Any = Manifest.Short # | ^^^^^^^^ # | not found: Manifest -../scala-scala/src/library/scala/reflect/NameTransformer.scala -# 89 | if (buf eq null) name else buf.toString() -# | ^^^^^^^^^^^^^^ -# | missing argument for parameter index of method apply: (index: Int)Char -../scala-scala/src/library/scala/reflect/package.scala -# 63 | private[scala] def materializeClassTag[T](): ClassTag[T] = macro ??? -# | ^^^^^ -# | not found: macro - -../scala-scala/src/library/scala/runtime/Tuple2Zipped.scala -# 122 | val buf = bf(x._1) -# | ^^^^ -# | found: T1 -# | required: CC1[_] - -../scala-scala/src/library/scala/runtime/Tuple3Zipped.scala -# 131 | val buf = bf(x._1) -# | ^^^^ -# | found: T1 -# | required: CC1[_] - -../scala-scala/src/library/scala/StringContext.scala -# 168 | def f[A >: Any](args: A*): String = macro ??? -# | ^^^^^ -# | not found: macro ../scala-scala/src/library/scala/text/Document.scala +# Lots of type errors for pattern matches, having to do with the fact +# that Document contains a :: method without corresponding extractor, +# but still wants to extract lists using ::. We won't support that. +# Since Document should have been removed already, let's ignore it. -../scala-scala/src/library/scala/util/control/Exception.scala -# scala.MatchError: PostfixOp(Select(Ident(pf),isDefinedAt),_) (of class dotty.tools.dotc.ast.untpd$PostfixOp) -# at dotty.tools.dotc.ast.Trees$Instance$TreeAccumulator.foldOver(Trees.scala:1173) - -../scala-scala/src/library/scala/util/control/TailCalls.scala -# assertion failed - -../scala-scala/src/library/scala/util/hashing/Hashing.scala -# 35 | implicit def default[T] = new Default[T] -# | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -# | result type of implicit definition needs to be given explicitly - +../scala-scala/src/library/scala/AnyVal.scala +# 55 |abstract class AnyVal extends Any { +# |^ +# |illegal redefinition of standard class AnyVal +# (This is intended) -../scala-scala/src/library/scala/util/Sorting.scala -# assertion failed: invalid prefix ImplicitMethodType(List(ord), List(RefinedType(TypeRef(ThisType(TypeRef(NoPrefix,math)),Ordering), scala$math$Ordering$$T, TypeAlias(TypeRef(NoPrefix,K), 0))), RefinedType(TypeRef(ThisType(TypeRef(NoPrefix,math)),Ordering), scala$math$Ordering$$T, TypeAlias(TypeRef(NoPrefix,K), 0))) diff --git a/compiler/test/dotc/scala-collections.whitelist b/compiler/test/dotc/scala-collections.whitelist index cdec1ab12..cb7fd29b9 100644 --- a/compiler/test/dotc/scala-collections.whitelist +++ b/compiler/test/dotc/scala-collections.whitelist @@ -7,6 +7,8 @@ ../scala-scala/src/library/scala/runtime/RichInt.scala ../scala-scala/src/library/scala/runtime/RichLong.scala ../scala-scala/src/library/scala/runtime/RichShort.scala +../scala-scala/src/library/scala/runtime/Tuple2Zipped.scala +../scala-scala/src/library/scala/runtime/Tuple3Zipped.scala ../scala-scala/src/library/scala/Array.scala ../scala-scala/src/library/scala/NotImplementedError.scala ../scala-scala/src/library/scala/AnyValCompanion.scala @@ -62,6 +64,7 @@ ../scala-scala/src/library/scala/Serializable.scala ../scala-scala/src/library/scala/Specializable.scala ../scala-scala/src/library/scala/Symbol.scala +../scala-scala/src/library/scala/StringContext.scala ../scala-scala/src/library/scala/UninitializedError.scala ../scala-scala/src/library/scala/UninitializedFieldError.scala ../scala-scala/src/library/scala/collection/IndexedSeqOptimized.scala @@ -87,6 +90,13 @@ ../scala-scala/src/library/scala/collection/mutable/ArrayBuilder.scala ../scala-scala/src/library/scala/collection/mutable/ObservableBuffer.scala +../scala-scala/src/library/scala/collection/mutable/DefaultEntry.scala +../scala-scala/src/library/scala/collection/mutable/LinkedHashMap.scala +../scala-scala/src/library/scala/collection/mutable/ObservableMap.scala +../scala-scala/src/library/scala/collection/mutable/ObservableSet.scala +../scala-scala/src/library/scala/collection/mutable/SynchronizedQueue.scala +../scala-scala/src/library/scala/collection/mutable/UnrolledBuffer.scala +../scala-scala/src/library/scala/collection/mutable/SynchronizedBuffer.scala ../scala-scala/src/library/scala/collection/immutable/Stack.scala ../scala-scala/src/library/scala/collection/immutable/StringLike.scala @@ -265,10 +275,9 @@ ../scala-scala/src/library/scala/collection/generic/SetFactory.scala ../scala-scala/src/library/scala/collection/generic/ParFactory.scala -# https://github.com/lampepfl/dotty/issues/974 -> @smarter ../scala-scala/src/library/scala/collection/generic/MutableSortedSetFactory.scala -# cyclic reference, maybe related to #974 -> @smarter +# deep subtype #../scala-scala/src/library/scala/collection/generic/ParSetFactory.scala ../scala-scala/src/library/scala/collection/generic/OrderedTraversableFactory.scala @@ -284,12 +293,14 @@ ../scala-scala/src/library/scala/util/Try.scala +../scala-scala/src/library/scala/util/control/Exception.scala ../scala-scala/src/library/scala/util/control/Breaks.scala ../scala-scala/src/library/scala/util/control/ControlThrowable.scala ../scala-scala/src/library/scala/util/control/NonFatal.scala ../scala-scala/src/library/scala/util/control/NoStackTrace.scala ../scala-scala/src/library/scala/util/DynamicVariable.scala ../scala-scala/src/library/scala/util/Either.scala +../scala-scala/src/library/scala/util/hashing/Hashing.scala ../scala-scala/src/library/scala/util/hashing/ByteswapHashing.scala ../scala-scala/src/library/scala/util/hashing/MurmurHash3.scala ../scala-scala/src/library/scala/util/hashing/package.scala @@ -297,6 +308,7 @@ ../scala-scala/src/library/scala/util/MurmurHash.scala ../scala-scala/src/library/scala/util/Properties.scala ../scala-scala/src/library/scala/util/Random.scala +../scala-scala/src/library/scala/util/Sorting.scala ../scala-scala/src/library/scala/collection/mutable/AnyRefMap.scala ../scala-scala/src/library/scala/collection/mutable/ArrayBuffer.scala @@ -363,6 +375,7 @@ ../scala-scala/src/library/scala/collection/mutable/TreeSet.scala ../scala-scala/src/library/scala/collection/mutable/Undoable.scala ../scala-scala/src/library/scala/collection/mutable/WeakHashMap.scala +../scala-scala/src/library/scala/collection/mutable/ImmutableMapAdaptor.scala ../scala-scala/src/library/scala/collection/convert/DecorateAsJava.scala ../scala-scala/src/library/scala/collection/convert/DecorateAsScala.scala @@ -370,6 +383,7 @@ ../scala-scala/src/library/scala/collection/convert/package.scala ../scala-scala/src/library/scala/collection/convert/WrapAsJava.scala ../scala-scala/src/library/scala/collection/convert/WrapAsScala.scala +../scala-scala/src/library/scala/collection/convert/Wrappers.scala ../scala-scala/src/library/scala/collection/concurrent/Map.scala ../scala-scala/src/library/scala/collection/concurrent/TrieMap.scala @@ -386,8 +400,8 @@ ../scala-scala/src/library/scala/compat/Platform.scala -../scala-scala/src/library/scala/sys/SystemProperties.scala ../scala-scala/src/library/scala/sys/package.scala +../scala-scala/src/library/scala/sys/SystemProperties.scala ../scala-scala/src/library/scala/sys/Prop.scala ../scala-scala/src/library/scala/sys/PropImpl.scala ../scala-scala/src/library/scala/sys/BooleanProp.scala @@ -413,6 +427,8 @@ ../scala-scala/src/library/scala/io/Codec.scala ../scala-scala/src/library/scala/io/Position.scala ../scala-scala/src/library/scala/io/StdIn.scala +../scala-scala/src/library/scala/io/BufferedSource.scala +../scala-scala/src/library/scala/io/Source.scala ../scala-scala/src/library/scala/math/BigDecimal.scala ../scala-scala/src/library/scala/math/BigInt.scala @@ -428,6 +444,8 @@ ../scala-scala/src/library/scala/reflect/macros/internal/macroImpl.scala ../scala-scala/src/library/scala/reflect/NoManifest.scala ../scala-scala/src/library/scala/reflect/OptManifest.scala +../scala-scala/src/library/scala/reflect/NameTransformer.scala +../scala-scala/src/library/scala/reflect/package.scala ../scala-scala/src/library/scala/Responder.scala @@ -435,6 +453,8 @@ ../scala-scala/src/library/scala/collection/script/Message.scala ../scala-scala/src/library/scala/collection/script/Scriptable.scala +../scala-scala/src/library/scala/concurrent/package.scala +../scala-scala/src/library/scala/concurrent/Future.scala ../scala-scala/src/library/scala/concurrent/Awaitable.scala ../scala-scala/src/library/scala/concurrent/BatchingExecutor.scala ../scala-scala/src/library/scala/concurrent/BlockContext.scala @@ -455,9 +475,19 @@ ../scala-scala/src/library/scala/concurrent/SyncVar.scala ../scala-scala/src/library/scala/concurrent/TaskRunner.scala ../scala-scala/src/library/scala/concurrent/ThreadPoolRunner.scala - +../scala-scala/src/library/scala/concurrent/SyncChannel.scala +../scala-scala/src/library/scala/concurrent/impl/ExecutionContextImpl.scala + +../scala-scala/src/library/scala/collection/parallel/package.scala +../scala-scala/src/library/scala/collection/parallel/ParIterable.scala +#../scala-scala/src/library/scala/collection/parallel/ParMap.scala +#../scala-scala/src/library/scala/collection/parallel/ParMapLike.scala +#../scala-scala/src/library/scala/collection/parallel/ParIterableLike.scala +#../scala-scala/src/library/scala/collection/parallel/ParSeqLike.scala ../scala-scala/src/library/scala/collection/parallel/Combiner.scala ../scala-scala/src/library/scala/collection/parallel/mutable/LazyCombiner.scala +../scala-scala/src/library/scala/collection/parallel/mutable/ResizableParArrayCombiner.scala +../scala-scala/src/library/scala/collection/parallel/RemainsIterator.scala ../scala-scala/src/library/scala/collection/parallel/mutable/package.scala ../scala-scala/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala ../scala-scala/src/library/scala/collection/parallel/mutable/ParHashMap.scala @@ -468,13 +498,17 @@ ../scala-scala/src/library/scala/collection/parallel/mutable/ParSeq.scala ../scala-scala/src/library/scala/collection/parallel/mutable/ParSet.scala ../scala-scala/src/library/scala/collection/parallel/mutable/ParSetLike.scala +../scala-scala/src/library/scala/collection/parallel/mutable/ParTrieMap.scala ../scala-scala/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala +../scala-scala/src/library/scala/collection/parallel/mutable/ParArray.scala +#../scala-scala/src/library/scala/collection/parallel/mutable/ParMap.scala ../scala-scala/src/library/scala/collection/parallel/ParSeq.scala ../scala-scala/src/library/scala/collection/parallel/ParSet.scala ../scala-scala/src/library/scala/collection/parallel/ParSetLike.scala ../scala-scala/src/library/scala/collection/parallel/PreciseSplitter.scala ../scala-scala/src/library/scala/collection/parallel/Splitter.scala ../scala-scala/src/library/scala/collection/parallel/TaskSupport.scala +../scala-scala/src/library/scala/collection/parallel/Tasks.scala ../scala-scala/src/library/scala/Console.scala ../scala-scala/src/library/scala/Enumeration.scala @@ -503,6 +537,7 @@ ../scala-scala/src/library/scala/annotation/tailrec.scala ../scala-scala/src/library/scala/annotation/TypeConstraint.scala ../scala-scala/src/library/scala/annotation/unchecked/uncheckedStable.scala +../scala-scala/src/library/scala/annotation/unchecked/uncheckedVariance.scala ../scala-scala/src/library/scala/annotation/unspecialized.scala ../scala-scala/src/library/scala/annotation/varargs.scala @@ -546,6 +581,28 @@ ../scala-scala/src/library/scala/Function.scala ../scala-scala/src/library/scala/Function0.scala +#../scala-scala/src/library/scala/Function1.scala +#../scala-scala/src/library/scala/Function2.scala +../scala-scala/src/library/scala/Function3.scala +../scala-scala/src/library/scala/Function4.scala +../scala-scala/src/library/scala/Function5.scala +../scala-scala/src/library/scala/Function6.scala +../scala-scala/src/library/scala/Function7.scala +../scala-scala/src/library/scala/Function8.scala +../scala-scala/src/library/scala/Function9.scala +../scala-scala/src/library/scala/Function10.scala +../scala-scala/src/library/scala/Function11.scala +../scala-scala/src/library/scala/Function12.scala +../scala-scala/src/library/scala/Function13.scala +../scala-scala/src/library/scala/Function14.scala +../scala-scala/src/library/scala/Function15.scala +../scala-scala/src/library/scala/Function16.scala +../scala-scala/src/library/scala/Function17.scala +../scala-scala/src/library/scala/Function18.scala +../scala-scala/src/library/scala/Function19.scala +../scala-scala/src/library/scala/Function20.scala +../scala-scala/src/library/scala/Function21.scala +../scala-scala/src/library/scala/Function22.scala ../scala-scala/src/library/scala/Tuple1.scala ../scala-scala/src/library/scala/Tuple2.scala diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala index 43b679c71..483c22984 100644 --- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala @@ -46,7 +46,7 @@ class DocASTPhase extends Phase { def membersFromSymbol(sym: Symbol): List[Entity] = { if (sym.info ne NoType) { - val defs = sym.info.bounds.hi.membersBasedOnFlags(Flags.Method, Flags.Synthetic | Flags.Private) + val defs = sym.info.bounds.hi.finalResultType.membersBasedOnFlags(Flags.Method, Flags.Synthetic | Flags.Private) .filterNot(_.symbol.owner.name.show == "Any") .map { meth => DefImpl( diff --git a/docs/docs/contributing/workflow.md b/docs/docs/contributing/workflow.md index 48f71053e..fb8da0da3 100644 --- a/docs/docs/contributing/workflow.md +++ b/docs/docs/contributing/workflow.md @@ -33,7 +33,7 @@ Here are some useful debugging `<OPTIONS>`: * `-Xprint:PHASE1,PHASE2,...` or `-Xprint:all`: prints the `AST` after each specified phase. Phase names can be found by searching - `src/dotty/tools/dotc/transform/` for `phaseName`. + `compiler/src/dotty/tools/dotc/transform/` for `phaseName`. * `-Ylog:PHASE1,PHASE2,...` or `-Ylog:all`: enables `ctx.log("")` logging for the specified phase. * `-Ycheck:all` verifies the consistency of `AST` nodes between phases, in @@ -42,7 +42,7 @@ Here are some useful debugging `<OPTIONS>`: `-Ycheck:tailrec,resolveSuper,mixin,restoreScopes,labelDef`. Additional logging information can be obtained by changes some `noPrinter` to -`new Printer` in `src/dotty/tools/dotc/config/Printers.scala`. This enables the +`new Printer` in `compiler/src/dotty/tools/dotc/config/Printers.scala`. This enables the `subtyping.println("")` and `ctx.traceIndented("", subtyping)` style logging. ## Running tests ## diff --git a/docs/docs/index.md b/docs/docs/index.md index 8fceedbd0..0d9bc6b6f 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -20,6 +20,7 @@ Index - [Eclipse](contributing/eclipse.md) setting up dev environment - [Intellij-IDEA](contributing/intellij-idea.md) setting up dev environment * Internals document the compiler internals + - [Syntax Summary](internals/syntax.md) - [Project Structure](internals/overall-structure.md) of the project - [Backend](internals/backend.md) details on the bytecode backend diff --git a/docs/docs/internals/backend.md b/docs/docs/internals/backend.md index f10cf1e82..47974b5ff 100644 --- a/docs/docs/internals/backend.md +++ b/docs/docs/internals/backend.md @@ -4,7 +4,7 @@ title: "Backend Internals" --- The code for the backend is split up by functionality and assembled in the -objet `GenBCode`. +object `GenBCode`. ```none object GenBCode --- [defines] --> PlainClassBuilder GenBCode also defines class BCodePhase, the compiler phase @@ -61,29 +61,29 @@ ready for serialization to disk. Currently the queue subsystem is all sequential, but as can be seen in http://magarciaepfl.github.io/scala/ the above design enables overlapping (a.1) -building of ClassNodes, (a.2) intra-method optimizations, and (a.3) +building of `ClassNodes`, (a.2) intra-method optimizations, and (a.3) serialization to disk. -This subsystem is described in detail in GenBCode.scala +This subsystem is described in detail in `GenBCode.scala` #### (b) Bytecode-level types, BType #### The previous bytecode emitter goes to great lengths to reason about bytecode-level types in terms of Symbols. -GenBCode uses BType as a more direct representation. A BType is immutable, and +`GenBCode` uses `BType` as a more direct representation. A `BType` is immutable, and a value class (once the rest of GenBCode is merged from http://magarciaepfl.github.io/scala/ ). Whether value class or not, its API is the same. That API doesn't reach into -the type checker. Instead, each method on a BType answers a question that can -be answered based on the BType itself. Sounds too simple to be good? It's a +the type checker. Instead, each method on a `BType` answers a question that can +be answered based on the `BType` itself. Sounds too simple to be good? It's a good building block, that's what it is. -The internal representation of a BType is based on what the JVM uses: internal -names (eg Ljava/lang/String; ) and method descriptors; as defined in the JVM -spec (that's why they aren't documented in GenBCode, just read the spec). +The internal representation of a `BType` is based on what the JVM uses: internal +names (e.g. `Ljava/lang/String;` ) and method descriptors; as defined in the JVM +spec (that's why they aren't documented in `GenBCode`, just read the [JVM 8 spec](https://docs.oracle.com/javase/specs/jvms/se8/html/)). -All things BType can be found in BCodeGlue.scala +All things `BType` can be found in `BCodeGlue.scala` #### (c) Utilities offering a more "high-level" API to bytecode emission #### Bytecode can be emitted one opcode at a time, but there are recurring patterns @@ -93,7 +93,7 @@ For example, when emitting a load-constant, a dedicated instruction exists for emitting load-zero. Similarly, emitting a switch can be done according to one of two strategies. -All these utilities are encapsulated in file BCodeIdiomatic.scala. They know +All these utilities are encapsulated in file `BCodeIdiomatic.scala`. They know nothing about the type checker (because, just between us, they don't need to). #### (d) Mapping between type-checker types and BTypes #### @@ -109,10 +109,10 @@ To understand how it's built, see: final def exemplar(csym0: Symbol): Tracked = { ... } ``` -Details in BCodeTypes.scala +Details in `BCodeTypes.scala` #### (e) More "high-level" utilities for bytecode emission #### -In the spirit of BCodeIdiomatic, utilities are added in BCodeHelpers for +In the spirit of `BCodeIdiomatic`, utilities are added in `BCodeHelpers` for emitting: - bean info class @@ -122,4 +122,4 @@ emitting: #### (f) Building an ASM ClassNode given an AST TypeDef #### -It's done by PlainClassBuilder +It's done by `PlainClassBuilder`(see `GenBCode.scala`). diff --git a/docs/docs/internals/overall-structure.md b/docs/docs/internals/overall-structure.md index 08d9ebe97..1b4e22f1b 100644 --- a/docs/docs/internals/overall-structure.md +++ b/docs/docs/internals/overall-structure.md @@ -37,7 +37,7 @@ list of sub-packages and their focus. ├── reporting // Reporting of error messages, warnings and other info. ├── rewrite // Helpers for rewriting Scala 2's constructs into dotty's. ├── transform // Miniphases and helpers for tree transformations. -├── typer //Type-checking and other frontend phases +├── typer // Type-checking and other frontend phases └── util // General purpose utility classes and modules. ``` @@ -93,7 +93,9 @@ phases. The current list of phases is specified in class [Compiler] as follows: ```scala def phases: List[List[Phase]] = List( List(new FrontEnd), // Compiler frontend: scanner, parser, namer, typer + List(new sbt.ExtractDependencies), // Sends information on classes' dependencies to sbt via callbacks List(new PostTyper), // Additional checks and cleanups after type checking + List(new sbt.ExtractAPI), // Sends a representation of the API of classes to sbt via callbacks List(new Pickler), // Generate TASTY info List(new FirstTransform, // Some transformations to put trees into a canonical form new CheckReentrant), // Internal use only: Check that compiled program has no data races involving global vars @@ -106,18 +108,22 @@ phases. The current list of phases is specified in class [Compiler] as follows: new TailRec, // Rewrite tail recursion to loops new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods new ClassOf), // Expand `Predef.classOf` calls. - List(new PatternMatcher, // Compile pattern matches + List(new TryCatchPatterns, // Compile cases in try/catch + new PatternMatcher, // Compile pattern matches new ExplicitOuter, // Add accessors to outer classes from nested ones. new ExplicitSelf, // Make references to non-trivial self types explicit as casts + new ShortcutImplicits, // Allow implicit functions without creating closures new CrossCastAnd, // Normalize selections involving intersection types. new Splitter), // Expand selections involving union types into conditionals List(new VCInlineMethods, // Inlines calls to value class methods + new IsInstanceOfEvaluator, // Issues warnings when unreachable statements are present in match/if expressions new SeqLiterals, // Express vararg arguments as arrays new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods new Getters, // Replace non-private vals and vars with getter defs (fields are added later) new ElimByName, // Expand by-name parameters and arguments new AugmentScala2Traits, // Expand traits defined in Scala 2.11 to simulate old-style rewritings - new ResolveSuper), // Implement super accessors and add forwarders to trait methods + new ResolveSuper, // Implement super accessors and add forwarders to trait methods + new ArrayConstructors), // Intercept creation of (non-generic) arrays and intrinsify. List(new Erasure), // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements. List(new ElimErasedValueType, // Expand erased value types to their underlying implementation types new VCElideAllocations, // Peep-hole optimization to eliminate unnecessary value class allocations @@ -137,9 +143,12 @@ phases. The current list of phases is specified in class [Compiler] as follows: new Flatten, // Lift all inner classes to package scope new RestoreScopes), // Repair scopes rendered invalid by moving definitions in prior phases of the group List(new ExpandPrivate, // Widen private definitions accessed from nested classes + new SelectStatic, // get rid of selects that would be compiled into GetStatic new CollectEntryPoints, // Find classes with main methods + new CollectSuperCalls, // Find classes that are called with super + new DropInlined, // Drop Inlined nodes, since backend has no use for them + new MoveStatics, // Move static methods to companion classes new LabelDefs), // Converts calls to labels to jumps - List(new GenSJSIR), // Generate .js code List(new GenBCode) // Generate JVM bytecode ) ``` @@ -180,10 +189,10 @@ Phases fall into four categories: * Code generators: These map the transformed trees to Java classfiles or Javascript files. -[dotty.tools]: https://github.com/lampepfl/dotty/tree/master/src/dotty/tools -[dotc]: https://github.com/lampepfl/dotty/tree/master/src/dotty/tools/dotc -[Main]: https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Main.scala -[Driver]: https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Driver.scala -[Compiler]: https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Compiler.scala -[Run]: https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/Run.scala -[Context]: https://github.com/lampepfl/dotty/blob/master/src/dotty/tools/dotc/core/Contexts.scala +[dotty.tools]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools +[dotc]: https://github.com/lampepfl/dotty/tree/master/compiler/src/dotty/tools/dotc +[Main]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Main.scala +[Driver]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Driver.scala +[Compiler]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Compiler.scala +[Run]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/Run.scala +[Context]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Contexts.scala diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md new file mode 100644 index 000000000..7c8cb1ea2 --- /dev/null +++ b/docs/docs/internals/syntax.md @@ -0,0 +1,356 @@ +--- +layout: default +title: "Scala Syntax Summary" +--- + +The following descriptions of Scala tokens uses literal characters `‘c’` when +referring to the ASCII fragment `\u0000` – `\u007F`. + +_Unicode escapes_ are used to represent the Unicode character with the given +hexadecimal code: + +```ebnf +UnicodeEscape ::= ‘\’ ‘u’ {‘u’} hexDigit hexDigit hexDigit hexDigit +hexDigit ::= ‘0’ | … | ‘9’ | ‘A’ | … | ‘F’ | ‘a’ | … | ‘f’ +``` + +Informal descriptions are typeset as `“some comment”`. + +### Lexical Syntax +The lexical syntax of Scala is given by the following grammar in EBNF +form. + +```ebnf +whiteSpace ::= ‘\u0020’ | ‘\u0009’ | ‘\u000D’ | ‘\u000A’ +upper ::= ‘A’ | … | ‘Z’ | ‘\$’ | ‘_’ “… and Unicode category Lu” +lower ::= ‘a’ | … | ‘z’ “… and Unicode category Ll” +letter ::= upper | lower “… and Unicode categories Lo, Lt, Nl” +digit ::= ‘0’ | … | ‘9’ +paren ::= ‘(’ | ‘)’ | ‘[’ | ‘]’ | ‘{’ | ‘}’ +delim ::= ‘`’ | ‘'’ | ‘"’ | ‘.’ | ‘;’ | ‘,’ +opchar ::= “printableChar not matched by (whiteSpace | upper | lower | + letter | digit | paren | delim | opchar | Unicode_Sm | + Unicode_So)” +printableChar ::= “all characters in [\u0020, \u007F] inclusive” +charEscapeSeq ::= ‘\’ (‘b’ | ‘t’ | ‘n’ | ‘f’ | ‘r’ | ‘"’ | ‘'’ | ‘\’) + +op ::= opchar {opchar} +varid ::= lower idrest +alphaid ::= upper idrest + | varid +plainid ::= alphaid + | op +id ::= plainid + | ‘`’ { charNoBackQuoteOrNewline | UnicodeEscape | charEscapeSeq } ‘`’ + | INT // interpolation id, only for quasi-quotes +idrest ::= {letter | digit} [‘_’ op] + +integerLiteral ::= (decimalNumeral | hexNumeral) [‘L’ | ‘l’] +decimalNumeral ::= ‘0’ | nonZeroDigit {digit} +hexNumeral ::= ‘0’ (‘x’ | ‘X’) hexDigit {hexDigit} +digit ::= ‘0’ | nonZeroDigit +nonZeroDigit ::= ‘1’ | … | ‘9’ + +floatingPointLiteral + ::= digit {digit} ‘.’ {digit} [exponentPart] [floatType] + | ‘.’ digit {digit} [exponentPart] [floatType] + | digit {digit} exponentPart [floatType] + | digit {digit} [exponentPart] floatType +exponentPart ::= (‘E’ | ‘e’) [‘+’ | ‘-’] digit {digit} +floatType ::= ‘F’ | ‘f’ | ‘D’ | ‘d’ + +booleanLiteral ::= ‘true’ | ‘false’ + +characterLiteral ::= ‘'’ (printableChar | charEscapeSeq) ‘'’ + +stringLiteral ::= ‘"’ {stringElement} ‘"’ + | ‘"""’ multiLineChars ‘"""’ +stringElement ::= printableChar \ (‘"’ | ‘\’) + | UnicodeEscape + | charEscapeSeq +multiLineChars ::= {[‘"’] [‘"’] char \ ‘"’} {‘"’} +processedStringLiteral + ::= alphaid ‘"’ {printableChar \ (‘"’ | ‘$’) | escape} ‘"’ + | alphaid ‘"""’ {[‘"’] [‘"’] char \ (‘"’ | ‘$’) | escape} {‘"’} ‘"""’ +escape ::= ‘$$’ + | ‘$’ letter { letter | digit } + | ‘{’ Block [‘;’ whiteSpace stringFormat whiteSpace] ‘}’ +stringFormat ::= {printableChar \ (‘"’ | ‘}’ | ‘ ’ | ‘\t’ | ‘\n’)} + +symbolLiteral ::= ‘'’ plainid + +comment ::= ‘/*’ “any sequence of characters; nested comments are allowed” ‘*/’ + | ‘//’ “any sequence of characters up to end of line” + +nl ::= “new line character” +semi ::= ‘;’ | nl {nl} +``` + + +## Context-free Syntax + +The context-free syntax of Scala is given by the following EBNF +grammar: + +### Literals and Paths +```ebnf +SimpleLiteral ::= [‘-’] integerLiteral + | [‘-’] floatingPointLiteral + | booleanLiteral + | characterLiteral + | stringLiteral +Literal ::= SimpleLiteral + | processedStringLiteral + | symbolLiteral + | ‘null’ + +QualId ::= id {‘.’ id} +ids ::= id {‘,’ id} + +Path ::= StableId + | [id ‘.’] ‘this’ +StableId ::= id + | Path ‘.’ id + | [id ‘.’] ‘super’ [ClassQualifier] ‘.’ id +ClassQualifier ::= ‘[’ id ‘]’ +``` + +### Types +```ebnf +Type ::= [‘implicit’] FunArgTypes ‘=>’ Type Function(ts, t) + | HkTypeParamClause ‘=>’ Type TypeLambda(ps, t) + | InfixType +FunArgTypes ::= InfixType + | ‘(’ [ FunArgType {‘,’ FunArgType } ] ‘)’ +InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2) +RefinedType ::= WithType {[nl] Refinement} RefinedTypeTree(t, ds) +WithType ::= AnnotType {‘with’ AnnotType} (deprecated) +AnnotType ::= SimpleType {Annotation} Annotated(t, annot) +SimpleType ::= SimpleType (TypeArgs | NamedTypeArgs) AppliedTypeTree(t, args) + | SimpleType ‘#’ id Select(t, name) + | StableId + | Path ‘.’ ‘type’ SingletonTypeTree(p) + | ‘(’ ArgTypes ‘)’ Tuple(ts) + | ‘_’ TypeBounds + | Refinement RefinedTypeTree(EmptyTree, refinement) + | SimpleLiteral SingletonTypeTree(l) +ArgTypes ::= Type {‘,’ Type} + | NamedTypeArg {‘,’ NamedTypeArg} +FunArgType ::= Type + | ‘=>’ Type PrefixOp(=>, t) +ParamType ::= [‘=>’] ParamValueType +ParamValueType ::= Type [‘*’] PostfixOp(t, "*") +TypeArgs ::= ‘[’ ArgTypes ‘]’ ts +NamedTypeArg ::= id ‘=’ Type NamedArg(id, t) +NamedTypeArgs ::= ‘[’ NamedTypeArg {‘,’ NamedTypeArg} ‘]’ nts +Refinement ::= ‘{’ [Dcl] {semi [Dcl]} ‘}’ ds +TypeBounds ::= [‘>:’ Type] [‘<:’ Type] | INT TypeBoundsTree(lo, hi) +TypeParamBounds ::= TypeBounds {‘<%’ Type} {‘:’ Type} ContextBounds(typeBounds, tps) +``` + +### Expressions +```ebnf +Expr ::= [‘implicit’] FunParams ‘=>’ Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr) + | Expr1 +BlockResult ::= [‘implicit’] FunParams ‘=>’ Block + | Expr1 +FunParams ::= Bindings + | id + | ‘_’ +Expr1 ::= ‘if’ ‘(’ Expr ‘)’ {nl} Expr [[semi] ‘else’ Expr] If(Parens(cond), thenp, elsep?) + | ‘if’ Expr ‘then’ Expr [[semi] ‘else’ Expr] If(cond, thenp, elsep?) + | ‘while’ ‘(’ Expr ‘)’ {nl} Expr WhileDo(Parens(cond), body) + | ‘while’ Expr ‘do’ Expr WhileDo(cond, body) + | ‘do’ Expr [semi] ‘while’ Expr DoWhile(expr, cond) + | ‘try’ Expr Catches [‘finally’ Expr] Try(expr, catches, expr?) + | ‘try’ Expr [‘finally’ Expr] Try(expr, Nil, expr?) + | ‘throw’ Expr Throw(expr) + | ‘return’ [Expr] Return(expr?) + | ForExpr + | [SimpleExpr ‘.’] id ‘=’ Expr Assign(expr, expr) + | SimpleExpr1 ArgumentExprs ‘=’ Expr Assign(expr, expr) + | PostfixExpr [Ascription] + | PostfixExpr ‘match’ ‘{’ CaseClauses ‘}’ Match(expr, cases) -- point on match +Ascription ::= ‘:’ InfixType Typed(expr, tp) + | ‘:’ Annotation {Annotation} Typed(expr, Annotated(EmptyTree, annot)*) +Catches ::= ‘catch’ Expr +PostfixExpr ::= InfixExpr [id] PostfixOp(expr, op) +InfixExpr ::= PrefixExpr + | InfixExpr id [nl] InfixExpr InfixOp(expr, op, expr) +PrefixExpr ::= [‘-’ | ‘+’ | ‘~’ | ‘!’] SimpleExpr PrefixOp(expr, op) +SimpleExpr ::= ‘new’ Template New(templ) + | BlockExpr + | SimpleExpr1 [‘_’] PostfixOp(expr, _) +SimpleExpr1 ::= Literal + | Path + | ‘_’ + | ‘(’ ExprsInParens ‘)’ Parens(exprs) + | SimpleExpr ‘.’ id Select(expr, id) + | SimpleExpr (TypeArgs | NamedTypeArgs) TypeApply(expr, args) + | SimpleExpr1 ArgumentExprs Apply(expr, args) + | XmlExpr +ExprsInParens ::= ExprInParens {‘,’ ExprInParens} +ExprInParens ::= PostfixExpr ‘:’ Type + | Expr +ParArgumentExprs ::= ‘(’ ExprsInParens ‘)’ exprs + | ‘(’ [ExprsInParens] PostfixExpr ‘:’ ‘_’ ‘*’ ‘)’ exprs :+ Typed(expr, Ident(wildcardStar)) +ArgumentExprs ::= ParArgumentExprs + | [nl] BlockExpr +BlockExpr ::= ‘{’ CaseClauses ‘}’ Match(EmptyTree, cases) + | ‘{’ Block ‘}’ block // starts at { +Block ::= {BlockStat semi} [BlockResult] Block(stats, expr?) +BlockStat ::= Import + | {Annotation} [‘implicit’ | ‘lazy’] Def + | {Annotation} {LocalModifier} TmplDef + | Expr1 + +ForExpr ::= ‘for’ (‘(’ Enumerators ‘)’ | ‘{’ Enumerators ‘}’) ForYield(enums, expr) + {nl} [‘yield’] Expr + | ‘for’ Enumerators (‘do’ Expr | ‘yield’ Expr) ForDo(enums, expr) +Enumerators ::= Generator {semi Enumerator | Guard} +Enumerator ::= Generator + | Guard + | Pattern1 ‘=’ Expr GenAlias(pat, expr) +Generator ::= Pattern1 ‘<-’ Expr GenFrom(pat, expr) +Guard ::= ‘if’ PostfixExpr + +CaseClauses ::= CaseClause { CaseClause } CaseDef(pat, guard?, block) // block starts at => +CaseClause ::= ‘case’ (Pattern [Guard] ‘=>’ Block | INT) + +Pattern ::= Pattern1 { ‘|’ Pattern1 } Alternative(pats) +Pattern1 ::= PatVar ‘:’ RefinedType Bind(name, Typed(Ident(wildcard), tpe)) + | Pattern2 +Pattern2 ::= [varid ‘@’] InfixPattern Bind(name, pat) +InfixPattern ::= SimplePattern { id [nl] SimplePattern } InfixOp(pat, op, pat) +SimplePattern ::= PatVar Ident(wildcard) + | Literal Bind(name, Ident(wildcard)) + | ‘(’ [Patterns] ‘)’ Parens(pats) Tuple(pats) + | XmlPattern + | SimplePattern1 [TypeArgs] [ArgumentPatterns] +SimplePattern1 ::= Path + | ‘{’ Block ‘}’ + | SimplePattern1 ‘.’ id +PatVar ::= varid + | ‘_’ +Patterns ::= Pattern {‘,’ Pattern} +ArgumentPatterns ::= ‘(’ [Patterns] ‘)’ Apply(fn, pats) + | ‘(’ [Patterns ‘,’] Pattern2 ‘:’ ‘_’ ‘*’ ‘)’ +``` + +### Type and Value Parameters +```ebnf +ClsTypeParamClause::= ‘[’ ClsTypeParam {‘,’ ClsTypeParam} ‘]’ +ClsTypeParam ::= {Annotation} [{Modifier} type] [‘+’ | ‘-’] TypeDef(Modifiers, name, tparams, bounds) + id [HkTypeParamClause] TypeParamBounds Bound(below, above, context) + +DefTypeParamClause::= ‘[’ DefTypeParam {‘,’ DefTypeParam} ‘]’ +DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeParamBounds + +TypTypeParamClause::= ‘[’ TypTypeParam {‘,’ TypTypeParam} ‘]’ +TypTypeParam ::= {Annotation} id [HkTypeParamClause] TypeBounds + +HkTypeParamClause ::= ‘[’ HkTypeParam {‘,’ HkTypeParam} ‘]’ +HkTypeParam ::= {Annotation} [‘+’ | ‘-’] (Id[HkTypeParamClause] | ‘_’) + TypeBounds + +ClsParamClauses ::= {ClsParamClause} [[nl] ‘(’ ‘implicit’ ClsParams ‘)’] +ClsParamClause ::= [nl] ‘(’ [ClsParams] ‘)’ +ClsParams ::= ClsParam {‘,’ ClsParam} +ClsParam ::= {Annotation} ValDef(mods, id, tpe, expr) -- point of mods on val/var + [{Modifier} (‘val’ | ‘var’) | ‘inline’] Param +Param ::= id ‘:’ ParamType [‘=’ Expr] + | INT + +DefParamClauses ::= {DefParamClause} [[nl] ‘(’ ‘implicit’ DefParams ‘)’] +DefParamClause ::= [nl] ‘(’ [DefParams] ‘)’ +DefParams ::= DefParam {‘,’ DefParam} +DefParam ::= {Annotation} [‘inline’] Param ValDef(mods, id, tpe, expr) -- point of mods at id. +``` + +### Bindings and Imports +```ebnf +Bindings ::= ‘(’ Binding {‘,’ Binding} ‘)’ +Binding ::= (id | ‘_’) [‘:’ Type] ValDef(_, id, tpe, EmptyTree) + +Modifier ::= LocalModifier + | AccessModifier + | ‘override’ +LocalModifier ::= ‘abstract’ + | ‘final’ + | ‘sealed’ + | ‘implicit’ + | ‘lazy’ +AccessModifier ::= (‘private’ | ‘protected’) [AccessQualifier] +AccessQualifier ::= ‘[’ (id | ‘this’) ‘]’ + +Annotation ::= ‘@’ SimpleType {ParArgumentExprs} Apply(tpe, args) + +TemplateBody ::= [nl] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’ (self, stats) +TemplateStat ::= Import + | {Annotation [nl]} {Modifier} Def + | {Annotation [nl]} {Modifier} Dcl + | Expr1 +SelfType ::= id [‘:’ InfixType] ‘=>’ ValDef(_, name, tpt, _) + | ‘this’ ‘:’ InfixType ‘=>’ + +Import ::= ‘import’ ImportExpr {‘,’ ImportExpr} +ImportExpr ::= StableId ‘.’ (id | ‘_’ | ImportSelectors) Import(expr, sels) +ImportSelectors ::= ‘{’ {ImportSelector ‘,’} (ImportSelector | ‘_’) ‘}’ +ImportSelector ::= id [‘=>’ id | ‘=>’ ‘_’] Ident(name), Pair(id, id) +``` + +### Declarations and Definitions +```ebnf +Dcl ::= ‘val’ ValDcl + | ‘var’ VarDcl + | ‘def’ DefDcl + | ‘type’ {nl} TypeDcl + | INT + +ValDcl ::= ids ‘:’ Type PatDef(_, ids, tpe, EmptyTree) +VarDcl ::= ids ‘:’ Type PatDef(_, ids, tpe, EmptyTree) +DefDcl ::= DefSig [‘:’ Type] DefDef(_, name, tparams, vparamss, tpe, EmptyTree) +DefSig ::= id [DefTypeParamClause] DefParamClauses +TypeDcl ::= id [TypTypeParamClause] [‘=’ Type] TypeDefTree(_, name, tparams, tpt) + | id [HkTypeParamClause] TypeBounds TypeDefTree(_, name, tparams, bounds) + +Def ::= ‘val’ PatDef + | ‘var’ VarDef + | ‘def’ DefDef + | ‘type’ {nl} TypeDcl + | TmplDef + | INT +PatDef ::= Pattern2 {‘,’ Pattern2} [‘:’ Type] ‘=’ Expr PatDef(_, pats, tpe?, expr) +VarDef ::= PatDef + | ids ‘:’ Type ‘=’ ‘_’ +DefDef ::= DefSig [‘:’ Type] ‘=’ Expr DefDef(_, name, tparams, vparamss, tpe, expr) + | DefSig [nl] ‘{’ Block ‘}’ DefDef(_, name, tparams, vparamss, tpe, Block) + | ‘this’ DefParamClause DefParamClauses DefDef(_, <init>, Nil, vparamss, EmptyTree, expr | Block) + (‘=’ ConstrExpr | [nl] ConstrBlock) + +TmplDef ::= ([‘case’] ‘class’ | ‘trait’) ClassDef + | [‘case’] ‘object’ ObjectDef +ClassDef ::= id [ClsTypeParamClause] ClassDef(mods, name, tparams, templ) + [ConstrMods] ClsParamClauses TemplateOpt with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat +ConstrMods ::= AccessModifier + | Annotation {Annotation} (AccessModifier | ‘this’) +ObjectDef ::= id TemplateOpt ModuleDef(mods, name, template) // no constructor +TemplateOpt ::= [‘extends’ Template | [nl] TemplateBody] +Template ::= ConstrApps [TemplateBody] | TemplateBody Template(constr, parents, self, stats) +ConstrApps ::= ConstrApp {‘with’ ConstrApp} +ConstrApp ::= AnnotType {ArgumentExprs} Apply(tp, args) +ConstrExpr ::= SelfInvocation + | ConstrBlock +SelfInvocation ::= ‘this’ ArgumentExprs {ArgumentExprs} +ConstrBlock ::= ‘{’ SelfInvocation {semi BlockStat} ‘}’ + +TopStatSeq ::= TopStat {semi TopStat} +TopStat ::= {Annotation [nl]} {Modifier} TmplDef + | Import + | Packaging + | PackageObject +Packaging ::= ‘package’ QualId [nl] ‘{’ TopStatSeq ‘}’ Package(qid, stats) +PackageObject ::= ‘package’ ‘object’ ObjectDef object with package in mods. + +CompilationUnit ::= {‘package’ QualId semi} TopStatSeq Package(qid, stats) +``` diff --git a/docs/syntax-summary.txt b/docs/syntax-summary.txt deleted file mode 100644 index d382507d3..000000000 --- a/docs/syntax-summary.txt +++ /dev/null @@ -1,327 +0,0 @@ -% $Id: SyntaxSummary.tex 21104 2010-03-08 13:49:27Z odersky $ - -\chapter{Scala Syntax Summary}\label{sec:syntax} -\todo{introduce SeqPattern syntax} - -The lexical syntax of Scala is given by the following grammar in EBNF -form. - -{\small -\begin{lstlisting} - upper ::= `A' | $\cdots$ | `Z' | `$\Dollar$' | `_' $\mbox{\rm\em and Unicode category Lu}$ - lower ::= `a' | $\cdots$ | `z' $\mbox{\rm\em and Unicode category Ll}$ - letter ::= upper | lower $\mbox{\rm\em and Unicode categories Lo, Lt, Nl}$ - digit ::= `0' | $\cdots$ | `9' - opchar ::= $\mbox{\rm\em ``all other characters in \U{0020-007F} and Unicode}$ - $\mbox{\rm\em categories Sm, So except parentheses ([{}]) and periods''}$ - - op ::= opchar {opchar} - varid ::= lower idrest - alphaid ::= upper idrest - | varid - plainid ::= alphaid - | op - id ::= plainid - | `\`' stringLit `\`' - | INT // interpolation id, only for quasi-quotes - idrest ::= {letter | digit} [`_' op] - - integerLiteral ::= (decimalNumeral | hexNumera) [`L' | `l'] - decimalNumeral ::= `0' | nonZeroDigit {digit} - hexNumeral ::= `0' `x' hexDigit {hexDigit} - digit ::= `0' | nonZeroDigit - nonZeroDigit ::= `1' | $\cdots$ | `9' - octalDigit ::= `0' | $\cdots$ | `7' - - floatingPointLiteral - ::= digit {digit} `.' {digit} [exponentPart] [floatType] - | `.' digit {digit} [exponentPart] [floatType] - | digit {digit} exponentPart [floatType] - | digit {digit} [exponentPart] floatType - exponentPart ::= (`E' | `e') [`+' | `-'] digit {digit} - floatType ::= `F' | `f' | `D' | `d' - - booleanLiteral ::= `true' | `false' - - characterLiteral ::= `\'' printableChar `\'' - | `\'' charEscapeSeq `\'' - - stringLiteral ::= `"' {stringElement} `"' - | `"""' {[`"'] [`"'] char \ `"'} {`"'} `"""' - stringElement ::= printableChar \ (`"' | `\') - | charEscapeSeq - charEscapeSeq ::= `\b' | `\n' | `\t' | `\f' | `\r' | `"' | `'' | `\\' - - processedStringLiteral - ::= alphaid`"' {printableChar \ (`"' | `$') | escape} `"' - | alphaid `"""' {[`"'] [`"'] char \ (`"' | `$') | escape} {`"'} `"""' - escape ::= `$$' \comment{$} - | `$' letter { letter | digit } - | `{' Block [`;' whiteSpace stringFormat whiteSpace] `}' - stringFormat ::= {printableChar \ (`"' | `}' | ` ' | `\t' | `\n')} - whiteSpace ::= {` ' | `\t'} - - symbolLiteral ::= `'' plainid - - comment ::= `/*' $\mbox{\rm\em ``any sequence of characters''}$ `*/' - | `//' $\mbox{\rm\em ``any sequence of characters up to end of line''}$ - - nl ::= $\mbox{\rm\em ``new line character''}$ - semi ::= `;' | nl {nl} -\end{lstlisting}} - -The context-free syntax of Scala is given by the following EBNF -grammar. - -{\small -\begin{lstlisting} - SimpleLiteral ::= [`-'] integerLiteral - | [`-'] floatingPointLiteral - | booleanLiteral - | characterLiteral - | stringLiteral - Literal ::= SimpleLiteral - | processedStringLiteral - | symbolLiteral - | `null' - - QualId ::= id {`.' id} - ids ::= id {`,' id} - - Path ::= StableId - | [id `.'] `this' - StableId ::= id - | Path `.' id - | [id '.'] `super' [ClassQualifier] `.' id - ClassQualifier ::= `[' id `]' - - Type ::= [`implicit'] FunArgTypes `=>' Type Function(ts, t) - | HkTypeParamClause `=>' Type TypeLambda(ps, t) - | InfixType - FunArgTypes ::= InfixType - | `(' [ FunArgType {`,' FunArgType } ] `)' - InfixType ::= RefinedType {id [nl] RefinedType} InfixOp(t1, op, t2) - RefinedType ::= WithType {[nl] Refinement} RefinedTypeTree(t, ds) - WithType ::= AnnotType {`with' AnnotType} (deprecated) - AnnotType ::= SimpleType {Annotation} Annotated(t, annot) - SimpleType ::= SimpleType (TypeArgs | NamedTypeArgs) AppliedTypeTree(t, args) - | SimpleType `#' id Select(t, name) - | StableId - | Path `.' `type' SingletonTypeTree(p) - | `(' ArgTypes ')' Tuple(ts) - | `_' TypeBounds - | Refinement RefinedTypeTree(EmptyTree, refinement) - | SimpleLiteral SingletonTypeTree(l) - ArgTypes ::= Type {`,' Type} - | NamedTypeArg {`,' NamedTypeArg } - FunArgType ::= Type - | `=>' Type PrefixOp(=>, t) - ParamType ::= [`=>'] ParamValueType - ParamValueType ::= Type [`*'] PostfixOp(t, "*") - TypeArgs ::= `[' ArgTypes `]' ts - NamedTypeArg ::= id `=' Type NamedArg(id, t) - NamedTypeArgs ::= `[' NamedTypeArg {`,' NamedTypeArg} `]' nts - Refinement ::= `{' [Dcl] {semi [Dcl]} `}' ds - TypeBounds ::= [`>:' Type] [`<: Type] | INT TypeBoundsTree(lo, hi) - TypeParamBounds ::= TypeBounds {`<%' Type} {`:' Type} ContextBounds(typeBounds, tps) - - Expr ::= [`implicit'] FunParams `=>' Expr Function(args, expr), Function(ValDef([implicit], id, TypeTree(), EmptyTree), expr) - FunParams ::= Bindings - | id - | `_' - ExprInParens ::= PostfixExpr `:' Type - | Expr - BlockResult ::= [`implicit'] FunParams `=>' Block - | Expr1 - Expr1 ::= `if' `(' Expr `)' {nl} Expr [[semi] else Expr] If(Parens(cond), thenp, elsep?) - | `if' Expr `then' Expr [[semi] else Expr] If(cond, thenp, elsep?) - | `while' `(' Expr `)' {nl} Expr WhileDo(Parens(cond), body) - | `while' Expr `do' Expr WhileDo(cond, body) - | `do' Expr [semi] `while' Expr DoWhile(expr, cond) - | `try' Expr Catches [`finally' Expr] Try(expr, catches, expr?) - | `try' Expr [`finally' Expr] Try(expr, Nil, expr?) - | `throw' Expr Throw(expr) - | `return' [Expr] Return(expr?) - | ForExpr - | [SimpleExpr `.'] id `=' Expr Assign(expr, expr) - | SimpleExpr1 ArgumentExprs `=' Expr Assign(expr, expr) - | PostfixExpr [Ascription] - | PostfixExpr `match' `{' CaseClauses `}' Match(expr, cases) -- point on match - Ascription ::= `:' InfixType Typed(expr, tp) - | `:' Annotation {Annotation} Typed(expr, Annotated(EmptyTree, annot)*) - Catches ::= `catch' Expr - PostfixExpr ::= InfixExpr [id] PostfixOp(expr, op) - InfixExpr ::= PrefixExpr - | InfixExpr id [nl] InfixExpr InfixOp(expr, op, expr) - PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr PrefixOp(expr, op) - SimpleExpr ::= `new' Template New(templ) - | BlockExpr - | SimpleExpr1 [`_'] PostfixOp(expr, _) - SimpleExpr1 ::= Literal - | Path - | `_' - | `(' ExprsInParens2 `)' Parens(exprs) - | SimpleExpr `.' id Select(expr, id) - | SimpleExpr (TypeArgs | NamedTypeArgs) TypeApply(expr, args) - | SimpleExpr1 ArgumentExprs Apply(expr, args) - | XmlExpr - ExprsInParens ::= ExprInParens {`,' ExprInParens} - ParArgumentExprs ::= `(' [ExprsInParens] `)' exprs - | `(' [ExprsInParens `,'] PostfixExpr `:' `_' `*' ')' exprs :+ Typed(expr, Ident(wildcardStar)) - ArgumentExprs ::= ParArgumentExprs - | [nl] BlockExpr - BlockExpr ::= `{' CaseClauses `}' Match(EmptyTree, cases) - | `{' Block `}' block // starts at { - Block ::= {BlockStat semi} [BlockResult] Block(stats, expr?) - BlockStat ::= Import - | {Annotation} [`implicit' | `lazy'] Def - | {Annotation} {LocalModifier} TmplDef - | Expr1 - | - - ForExpr ::= `for' (`(' Enumerators `)' | `{' Enumerators `}') ForYield(enums, expr) - {nl} [`yield'] Expr ForDo(enums, expr) - | `for' Enumerators (`do' Expr | `yield' Expr) - - Enumerators ::= Generator {semi Enumerator | Guard} - Enumerator ::= Generator - | Guard - | Pattern1 `=' Expr GenAlias(pat, expr) - Generator ::= Pattern1 `<-' Expr GenFrom(pat, expr) - Guard ::= `if' PostfixExpr - - CaseClauses ::= CaseClause { CaseClause } - CaseClause ::= `case' (Pattern [Guard] `=>' Block | INT) CaseDef(pat, guard?, block) // block starts at => - - Pattern ::= Pattern1 { `|' Pattern1 } Alternative(pats) - Pattern1 ::= PatVar `:' RefinedType Bind(name, Typed(Ident(wildcard), tpe)) - | Pattern2 - Pattern2 ::= [varid `@'] InfixPattern Bind(name, pat) - InfixPattern ::= SimplePattern { id [nl] SimplePattern } InfixOp(pat, op, pat) - SimplePattern ::= PatVar Ident(wildcard) - | Literal Bind(name, Ident(wildcard)) - | `(' [Patterns] `)' Parens(pats) Tuple(pats) - | XmlPattern - | SimplePattern1 [TypeArgs] [ArgumentPatterns] - SimplePattern1 ::= Path - | `{' Block `}' - | SimplePattern1 `.' id - PatVar ::= varid - | `_' - Patterns ::= Pattern {`,' Pattern} - ArgumentPatterns ::= `(' [Patterns] `)' Apply(fn, pats) - | `(' [Patterns `,'] Pattern2 `:' `_' `*' ') - - ClsTypeParamClause::= `[' ClsTypeParam {`,' ClsTypeParam} `]' - ClsTypeParam ::= {Annotation} [{Modifier} type] [`+' | `-'] TypeDef(Modifiers, name, tparams, bounds) - id [HkTypeParamClause] TypeParamBounds Bound(below, above, context) - - DefTypeParamClause::= `[' DefTypeParam {`,' DefTypeParam} `]' - DefTypeParam ::= {Annotation} id [HkTypeParamClause] TypeParamBounds - - TypTypeParamCaluse::= `[' TypTypeParam {`,' TypTypeParam} `]' - TypTypeParam ::= {Annotation} id [HkTypeParamClause] TypeBounds - - HkTypeParamClause ::= `[' HkTypeParam {`,' HkTypeParam} `]' - HkTypeParam ::= {Annotation} ['+' | `-'] (Id[HkTypeParamClause] | `_') - TypeBounds - - ClsParamClauses ::= {ClsParamClause} [[nl] `(' `implicit' ClsParams `)'] - ClsParamClause ::= [nl] `(' [ClsParams] ')' - ClsParams ::= ClsParam {`' ClsParam} - ClsParam ::= {Annotation} - [{Modifier} (`val' | `var') | `inline'] Param ValDef(mods, id, tpe, expr) -- point of mods on val/var - Param ::= id `:' ParamType [`=' Expr] - | INT - - DefParamClauses ::= {DefParamClause} [[nl] `(' `implicit' DefParams `)'] - DefParamClause ::= [nl] `(' [DefParams] ')' - DefParams ::= DefParam {`,' DefParam} - DefParam ::= {Annotation} [`inline'] Param ValDef(mods, id, tpe, expr) -- point of mods at id. - - Bindings ::= `(' Binding {`,' Binding}] `)' - Binding ::= (id | `_') [`:' Type] ValDef(_, id, tpe, EmptyTree) - - Modifier ::= LocalModifier - | AccessModifier - | `override' - LocalModifier ::= `abstract' - | `final' - | `sealed' - | `implicit' - | `lazy' - AccessModifier ::= (`private' | `protected') [AccessQualifier] - AccessQualifier ::= `[' (id | `this') `]' - - Annotation ::= `@' SimpleType {ParArgumentExprs} Apply(tpe, args) - - TemplateBody ::= [nl] `{' [SelfType] TemplateStat {semi TemplateStat} `} (self, stats) - TemplateStat ::= Import - | {Annotation [nl]} {Modifier} Def - | {Annotation [nl]} {Modifier} Dcl - | Expr1 - | - SelfType ::= id [`:' InfixType] `=>' ValDef(_, name, tpt, _) - | `this' `:' InfixType `=> - - Import ::= `import' ImportExpr {`,' ImportExpr} - ImportExpr ::= StableId `.' (id | `_' | ImportSelectors) Import(expr, sels) - ImportSelectors ::= `{' {ImportSelector `,'} (ImportSelector | `_') `}' - ImportSelector ::= id [`=>' id | `=>' `_'] Ident(name), Pair(id, id) - - Dcl ::= `val' ValDcl - | `var' VarDcl - | `def' DefDcl - | `type' {nl} TypeDcl - | INT - - ValDcl ::= ids `:' Type PatDef(_, ids, tpe, EmptyTree) - VarDcl ::= ids `:' Type PatDef(_, ids, tpe, EmptyTree) - DefDcl ::= DefSig [`:' Type] DefDef(_, name, tparams, vparamss, tpe, EmptyTree) - DefSig ::= id [DefTypeParamClause] DefParamClauses - TypeDcl ::= id [TypTypeParamClause] ['=' Type] TypeDefTree(_, name, tparams, tpt) - | id [HkTypeParamClause] TypeBounds TypeDefTree(_, name, tparams, bounds) - - Def ::= `val' PatDef - | `var' VarDef - | `def' DefDef - | `type' {nl} TypeDcl - | TmplDef - | INT - PatDef ::= Pattern2 {`,' Pattern2} [`:' Type] `=' Expr PatDef(_, pats, tpe?, expr) - VarDef ::= PatDef - | ids `:' Type `=' `_' - DefDef ::= DefSig [`:' Type] `=' Expr DefDef(_, name, tparams, vparamss, tpe, expr) - | DefSig [nl] `{' Block `}' DefDef(_, name, tparams, vparamss, tpe, Block) - | `this' DefParamClause DefParamClauses DefDef(_, <init>, Nil, vparamss, EmptyTree, expr | Block) - (`=' ConstrExpr | [nl] ConstrBlock) - - TmplDef ::= ([`case'] `class' | `trait') ClassDef - | [`case'] `object' ObjectDef - ClassDef ::= id [ClsTypeParamClause] ClassDef(mods, name, tparams, templ) // - [ConstrMods] ClsParamClauses TemplateOpt with DefDef(_, <init>, Nil, vparamss, EmptyTree, EmptyTree) as first stat - ConstrMods ::= AccessModifier - | Annotation {Annotation} (AccessModifier | `this') - ObjectDef ::= id TemplateOpt ModuleDef(mods, name, template) // no constructor - TemplateOpt ::= [`extends' Template | [nl] TemplateBody] - Template ::= ConstrApps [TemplateBody] | TemplateBody Template(constr, parents, self, stats) - ConstrApps ::= ConstrApp {`with' ConstrApp} - ConstrApp ::= AnnotType {ArgumentExprs} Apply(tp, args) - - ConstrExpr ::= SelfInvocation - | ConstrBlock - ConstrBlock ::= `{' SelfInvocation {semi BlockStat} `}' - SelfInvocation ::= `this' ArgumentExprs {ArgumentExprs} - - TopStatSeq ::= TopStat {semi TopStat} - TopStat ::= {Annotation [nl]} {Modifier} TmplDef - | Import - | Packaging - | PackageObject - | - Packaging ::= `package' QualId [nl] `{' TopStatSeq `}' Package(qid, stats) - PackageObject ::= `package' `object' ObjectDef object with package in mods. - - CompilationUnit ::= {`package' QualId semi} TopStatSeq Package(qid, stats) -\end{lstlisting} -} diff --git a/tests/neg/i1716.scala b/tests/neg/i1716.scala new file mode 100644 index 000000000..1a3fd71d0 --- /dev/null +++ b/tests/neg/i1716.scala @@ -0,0 +1,9 @@ +object Fail { + def f(m: Option[Int]): Unit = { + m match { + case x @ Some[_] => // error + case _ => + } + } + Some[_] // error +} diff --git a/tests/pos/hkwild.scala b/tests/pos/hkwild.scala new file mode 100644 index 000000000..49bea7d01 --- /dev/null +++ b/tests/pos/hkwild.scala @@ -0,0 +1,6 @@ +class Test[T1](val x: T1) { + def invert[El1, CC1[X]](implicit w1: T1 <:< CC1[El1]) = { + val buf: CC1[_] = w1(x) + ??? + } +} diff --git a/tests/pos/i1795.scala b/tests/pos/i1795.scala new file mode 100644 index 000000000..3e8bd1e97 --- /dev/null +++ b/tests/pos/i1795.scala @@ -0,0 +1,13 @@ +sealed trait T1 {type M1} + +case object o1 extends T1 + +sealed trait T2 {type M2} + +case object o2 extends T2 + +class TestX { + type TestT1 <: T1 {type M1 = TestT2} + type TestT2 <: T2 {type M2 = TestT1} + //val x: TestT1 = o1 +} |