aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Desugar.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/core/Annotations.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeComparer.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeOps.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala15
-rw-r--r--compiler/src/dotty/tools/dotc/printing/Printer.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/Reporter.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java4
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala21
-rw-r--r--compiler/src/dotty/tools/dotc/transform/FullParameterization.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/transform/TailRec.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ImportInfo.scala47
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Inliner.scala11
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Namer.scala28
-rw-r--r--compiler/src/dotty/tools/dotc/typer/RefChecks.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala5
-rw-r--r--compiler/test/dotc/tests.scala1
-rw-r--r--compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala39
-rw-r--r--doc-tool/resources/_layouts/api-page.html2
-rw-r--r--doc-tool/resources/css/api-page.css5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala3
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/DocDriver.scala5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala86
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala5
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala156
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/transform.scala (renamed from doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala)15
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala8
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/entities.scala3
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/util/traversing.scala4
-rw-r--r--project/Build.scala45
-rw-r--r--tests/neg/customArgs/i2002.scala4
-rw-r--r--tests/neg/i1747.scala3
-rw-r--r--tests/neg/i1992.scala9
-rw-r--r--tests/neg/i2000.scala23
-rw-r--r--tests/neg/i2005.scala7
-rw-r--r--tests/neg/i2006.scala10
-rw-r--r--tests/pos/i2009.scala9
-rw-r--r--tests/repl/imports.check2
-rw-r--r--tests/run/i2020.scala8
50 files changed, 585 insertions, 136 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
index deb239143..b5be89440 100644
--- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
@@ -469,7 +469,13 @@ object desugar {
val originalVparams = constr1.vparamss.toIterator.flatten
val tparamAccessors = derivedTparams.map(_.withMods(originalTparams.next.mods))
val caseAccessor = if (isCaseClass) CaseAccessor else EmptyFlags
- val vparamAccessors = derivedVparamss.flatten.map(_.withMods(originalVparams.next.mods | caseAccessor))
+ val vparamAccessors = derivedVparamss match {
+ case first :: rest =>
+ first.map(_.withMods(originalVparams.next.mods | caseAccessor)) ++
+ rest.flatten.map(_.withMods(originalVparams.next.mods))
+ case _ =>
+ Nil
+ }
cpy.TypeDef(cdef)(
name = className,
rhs = cpy.Template(impl)(constr, parents1, self1,
diff --git a/compiler/src/dotty/tools/dotc/core/Annotations.scala b/compiler/src/dotty/tools/dotc/core/Annotations.scala
index 985b1ea3d..5464dce4f 100644
--- a/compiler/src/dotty/tools/dotc/core/Annotations.scala
+++ b/compiler/src/dotty/tools/dotc/core/Annotations.scala
@@ -117,11 +117,17 @@ object Annotations {
}
/** Create an annotation where the symbol and the tree are computed lazily. */
- def deferredSymAndTree(sym: => Symbol, treeFn: Context => Tree)(implicit ctx: Context): Annotation =
+ def deferredSymAndTree(symf: Context => Symbol, treeFn: Context => Tree)(implicit ctx: Context): Annotation =
new LazyAnnotation {
- lazy val symf = sym
-
- override def symbol(implicit ctx: Context): Symbol = symf
+ private[this] var mySym: Symbol = _
+
+ override def symbol(implicit ctx: Context): Symbol = {
+ if (mySym == null || mySym.defRunId != ctx.runId) {
+ mySym = symf(ctx)
+ assert(mySym != null)
+ }
+ mySym
+ }
def complete(implicit ctx: Context) = treeFn(ctx)
}
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index 9e9e39a84..847177e2f 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -9,6 +9,7 @@ import scala.annotation.{ switch, meta }
import scala.collection.{ mutable, immutable }
import PartialFunction._
import collection.mutable
+import util.common.alwaysZero
import scala.reflect.api.{ Universe => ApiUniverse }
object Definitions {
@@ -152,7 +153,7 @@ class Definitions {
resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = {
val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount)
val tparamBounds = tparamNames map (_ => TypeBounds.empty)
- val ptype = PolyType(tparamNames)(_ => tparamBounds, resultTypeFn)
+ val ptype = PolyType(tparamNames, tparamNames.map(alwaysZero))(_ => tparamBounds, resultTypeFn)
enterMethod(cls, name, ptype, flags)
}
diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
index 6063cbf38..fca111702 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -489,7 +489,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
case tp1 @ MethodType(_, formals1) =>
(tp1.signature consistentParams tp2.signature) &&
matchingParams(formals1, formals2, tp1.isJava, tp2.isJava) &&
- (!tp1.isImplicit || tp2.isImplicit) && // non-implicit functions shadow implicit ones
+ (tp1.isImplicit == tp2.isImplicit) &&
isSubType(tp1.resultType, tp2.resultType.subst(tp2, tp1))
case _ =>
false
diff --git a/compiler/src/dotty/tools/dotc/core/TypeOps.scala b/compiler/src/dotty/tools/dotc/core/TypeOps.scala
index c2a7d7ea6..308e6e306 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeOps.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeOps.scala
@@ -401,12 +401,12 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
def forwardRefs(from: Symbol, to: Type, prefs: List[TypeRef]) = to match {
case to @ TypeBounds(lo1, hi1) if lo1 eq hi1 =>
for (pref <- prefs) {
- def forward(): Unit =
+ def forward()(implicit ctx: Context): Unit =
for (argSym <- pref.decls)
if (argSym is BaseTypeArg)
forwardRef(argSym, from, to, cls, decls)
pref.info match {
- case info: TempClassInfo => info.addSuspension(forward)
+ case info: TempClassInfo => info.addSuspension(implicit ctx => forward())
case _ => forward()
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index ae9122853..200e94a1e 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -2603,7 +2603,7 @@ object Types {
case t => mapOver(t)
}
}
- PolyType(paramNames ++ that.paramNames)(
+ PolyType(paramNames ++ that.paramNames, variances ++ that.variances)(
x => this.paramBounds.mapConserve(_.subst(this, x).bounds) ++
that.paramBounds.mapConserve(shift(_).subst(that, x).bounds),
x => shift(that.resultType).subst(that, x).subst(this, x))
@@ -2634,11 +2634,10 @@ object Types {
}
object PolyType {
- def apply(paramNames: List[TypeName], variances: List[Int] = Nil)(
+ def apply(paramNames: List[TypeName], variances: List[Int])(
paramBoundsExp: PolyType => List[TypeBounds],
resultTypeExp: PolyType => Type)(implicit ctx: Context): PolyType = {
- val vs = if (variances.isEmpty) paramNames.map(alwaysZero) else variances
- unique(new PolyType(paramNames, vs)(paramBoundsExp, resultTypeExp))
+ unique(new PolyType(paramNames, variances)(paramBoundsExp, resultTypeExp))
}
def unapply(tl: PolyType): Some[(List[LambdaParam], Type)] =
@@ -3089,14 +3088,14 @@ object Types {
* be no longer temporary. These actions will be performed once `cls` gets a real
* ClassInfo.
*/
- private var suspensions: List[() => Unit] = Nil
+ private var suspensions: List[Context => Unit] = Nil
- def addSuspension(suspension: () => Unit): Unit = suspensions ::= suspension
+ def addSuspension(suspension: Context => Unit): Unit = suspensions ::= suspension
/** Install classinfo with known parents in `denot` and resume all suspensions */
def finalize(denot: SymDenotation, parents: List[TypeRef])(implicit ctx: Context) = {
denot.info = derivedClassInfo(classParents = parents)
- suspensions.foreach(_())
+ suspensions.foreach(_(ctx))
}
}
diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index 5b751ef3c..36d478c6d 100644
--- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -806,7 +806,7 @@ class ClassfileParser(
def classSymbol(externalName: Name)(implicit ctx: Context): Symbol = {
/** Return the symbol of `innerName`, having the given `externalName`. */
def innerSymbol(externalName: Name, innerName: Name, static: Boolean): Symbol = {
- def getMember(sym: Symbol, name: Name): Symbol =
+ def getMember(sym: Symbol, name: Name)(implicit ctx: Context): Symbol =
if (static)
if (sym == classRoot.symbol) staticScope.lookup(name)
else sym.companionModule.info.member(name).symbol
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index ffd594454..fcba957c0 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -554,7 +554,9 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
val end = readEnd()
val tp = readType()
val lazyAnnotTree = readLater(end, rdr => ctx => rdr.readTerm()(ctx))
- annots += Annotation.deferredSymAndTree(tp.typeSymbol, _ => lazyAnnotTree.complete)
+ annots += Annotation.deferredSymAndTree(
+ implicit ctx => tp.typeSymbol,
+ implicit ctx => lazyAnnotTree.complete)
case tag =>
assert(false, s"illegal modifier tag $tag at $currentAddr, end = $end")
}
@@ -769,7 +771,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
cls.setApplicableFlags(fork.indexStats(end))
val constr = readIndexedDef().asInstanceOf[DefDef]
- def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree]): (List[Tree], List[Tree]) =
+ def mergeTypeParamsAndAliases(tparams: List[TypeDef], stats: List[Tree])(implicit ctx: Context): (List[Tree], List[Tree]) =
(tparams, stats) match {
case (tparam :: tparams1, (alias: TypeDef) :: stats1)
if tparam.name == alias.name.expandedName(cls) =>
diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index b01f6cc6a..3a2a45fd2 100644
--- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -932,9 +932,10 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
protected def deferredAnnot(end: Int)(implicit ctx: Context): Annotation = {
val start = readIndex
val atp = readTypeRef()
+ val phase = ctx.phase
Annotation.deferred(
- atp.typeSymbol, implicit ctx1 =>
- atReadPos(start, () => readAnnotationContents(end)(ctx1.withPhase(ctx.phase))))
+ atp.typeSymbol, implicit ctx =>
+ atReadPos(start, () => readAnnotationContents(end)(ctx.withPhase(phase))))
}
/* Read an abstract syntax tree */
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index b46bc401d..c14108d2e 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -993,20 +993,22 @@ object Parsers {
else {
val saved = placeholderParams
placeholderParams = Nil
+
+ def wrapPlaceholders(t: Tree) = try
+ if (placeholderParams.isEmpty) t
+ else new WildcardFunction(placeholderParams.reverse, t)
+ finally placeholderParams = saved
+
val t = expr1(location)
if (in.token == ARROW) {
- placeholderParams = saved
- closureRest(start, location, convertToParams(t))
+ placeholderParams = Nil // don't interpret `_' to the left of `=>` as placeholder
+ wrapPlaceholders(closureRest(start, location, convertToParams(t)))
}
else if (isWildcard(t)) {
placeholderParams = placeholderParams ::: saved
t
}
- else
- try
- if (placeholderParams.isEmpty) t
- else new WildcardFunction(placeholderParams.reverse, t)
- finally placeholderParams = saved
+ else wrapPlaceholders(t)
}
}
diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
index ac25f7cfd..0d1068b8c 100644
--- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -7,6 +7,7 @@ import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annot
import StdNames.{nme, tpnme}
import ast.Trees._, ast._
import typer.Implicits._
+import typer.ImportInfo
import config.Config
import java.lang.Integer.toOctalString
import config.Config.summarizeDepth
@@ -177,7 +178,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
varianceString(variance) ~ name.toString ~ toText(bounds)
changePrec(GlobalPrec) {
"[" ~ Text((tp.variances, tp.paramNames, tp.paramBounds).zipped.map(paramText), ", ") ~
- "] => " ~ toTextGlobal(tp.resultType)
+ "]" ~ (" => " provided !tp.resultType.isInstanceOf[MethodType]) ~
+ toTextGlobal(tp.resultType)
}
case tp: PolyParam =>
polyParamNameString(tp) ~ polyHash(tp.binder)
@@ -502,6 +504,17 @@ class PlainPrinter(_ctx: Context) extends Printer {
"?Unknown Implicit Result?"
}
+ def toText(importInfo: ImportInfo): Text = {
+ val siteStr = importInfo.site.show
+ val exprStr = if (siteStr endsWith ".type") siteStr dropRight 5 else siteStr
+ val selectorStr = importInfo.selectors match {
+ case Ident(name) :: Nil => name.show
+ case _ => "{...}"
+ }
+ s"import $exprStr.$selectorStr"
+ }
+
+
private var maxSummarized = Int.MaxValue
def summarized[T](depth: Int)(op: => T): T = {
diff --git a/compiler/src/dotty/tools/dotc/printing/Printer.scala b/compiler/src/dotty/tools/dotc/printing/Printer.scala
index 506773a4b..e163a83f3 100644
--- a/compiler/src/dotty/tools/dotc/printing/Printer.scala
+++ b/compiler/src/dotty/tools/dotc/printing/Printer.scala
@@ -6,6 +6,7 @@ import Texts._, ast.Trees._
import Types.Type, Symbols.Symbol, Contexts.Context, Scopes.Scope, Constants.Constant,
Names.Name, Denotations._, Annotations.Annotation
import typer.Implicits.SearchResult
+import typer.ImportInfo
/** The base class of all printers
*/
@@ -98,6 +99,9 @@ abstract class Printer {
/** Textual representation of implicit search result */
def toText(result: SearchResult): Text
+ /** Textual representation of info relating to an import clause */
+ def toText(result: ImportInfo): Text
+
/** Perform string or text-producing operation `op` so that only a
* summarized text with given recursion depth is shown
*/
diff --git a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala
index 26c1e5ebc..b2c7abec9 100644
--- a/compiler/src/dotty/tools/dotc/reporting/Reporter.scala
+++ b/compiler/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -171,22 +171,6 @@ trait Reporting { this: Context =>
throw ex
}
}
-
- /** Implements a fold that applies the function `f` to the result of `op` if
- * there are no new errors in the reporter
- *
- * @param op operation checked for errors
- * @param f function applied to result of op
- * @return either the result of `op` if it had errors or the result of `f`
- * applied to it
- */
- def withNoError[A, B >: A](op: => A)(f: A => B): B = {
- val before = reporter.errorCount
- val op0 = op
-
- if (reporter.errorCount > before) op0
- else f(op0)
- }
}
/**
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
index c74130b44..2bf15cb7c 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
@@ -49,7 +49,9 @@ public enum ErrorMessageID {
OverridesNothingButNameExistsID,
ForwardReferenceExtendsOverDefinitionID,
ExpectedTokenButFoundID,
- MixedLeftAndRightAssociativeOpsID;
+ MixedLeftAndRightAssociativeOpsID,
+ CantInstantiateAbstractClassOrTraitID,
+ ;
public int errorNumber() {
return ordinal() - 2;
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
index 7fccebef9..34190c114 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
@@ -1062,7 +1062,7 @@ object messages {
|
|Define `${definition.name}` before it is used,
|or move the definition of `${value.name}` so it does not appear between
- |the declartion of `${definition.name}` and its use,
+ |the declaration of `${definition.name}` and its use,
|or define `${value.name}` as lazy.
|""".stripMargin
}
@@ -1127,4 +1127,23 @@ object messages {
|""".stripMargin
}
+ case class CantInstantiateAbstractClassOrTrait(cls: Symbol, isTrait: Boolean)(implicit ctx: Context)
+ extends Message(CantInstantiateAbstractClassOrTraitID) {
+ val kind = "Usage"
+ private val traitOrAbstract = if (isTrait) hl"a trait" else hl"abstract"
+ val msg = hl"""${cls.name} is ${traitOrAbstract}; it cannot be instantiated"""
+ val explanation =
+ hl"""|Abstract classes and traits need to be extended by a concrete class or object
+ |to make their functionality accessible.
+ |
+ |You may want to create an anonymous class extending ${cls.name} with
+ | ${s"class ${cls.name} { }"}
+ |
+ |or add a companion object with
+ | ${s"object ${cls.name} extends ${cls.name}"}
+ |
+ |You need to implement any abstract members in both cases.
+ |""".stripMargin
+ }
+
}
diff --git a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
index 6c69c735b..9e43fc999 100644
--- a/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
+++ b/compiler/src/dotty/tools/dotc/transform/FullParameterization.scala
@@ -101,6 +101,7 @@ trait FullParameterization {
}
val ctparams = if (abstractOverClass) clazz.typeParams else Nil
val ctnames = ctparams.map(_.name.unexpandedName)
+ val ctvariances = ctparams.map(_.variance)
/** The method result type */
def resultType(mapClassParams: Type => Type) = {
@@ -122,14 +123,14 @@ trait FullParameterization {
info match {
case info: PolyType =>
- PolyType(info.paramNames ++ ctnames)(
+ PolyType(info.paramNames ++ ctnames, info.variances ++ ctvariances)(
pt =>
(info.paramBounds.map(mapClassParams(_, pt).bounds) ++
mappedClassBounds(pt)).mapConserve(_.subst(info, pt).bounds),
pt => resultType(mapClassParams(_, pt)).subst(info, pt))
case _ =>
if (ctparams.isEmpty) resultType(identity)
- else PolyType(ctnames)(mappedClassBounds, pt => resultType(mapClassParams(_, pt)))
+ else PolyType(ctnames, ctvariances)(mappedClassBounds, pt => resultType(mapClassParams(_, pt)))
}
}
diff --git a/compiler/src/dotty/tools/dotc/transform/TailRec.scala b/compiler/src/dotty/tools/dotc/transform/TailRec.scala
index 3e7a7ed89..aa0845605 100644
--- a/compiler/src/dotty/tools/dotc/transform/TailRec.scala
+++ b/compiler/src/dotty/tools/dotc/transform/TailRec.scala
@@ -119,7 +119,7 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
// now this speculatively transforms tree and throws away result in many cases
val rhsSemiTransformed = {
val transformer = new TailRecElimination(origMeth, dd.tparams, owner, thisTpe, mandatory, label, abstractOverClass = defIsTopLevel)
- val rhs = atGroupEnd(transformer.transform(dd.rhs)(_))
+ val rhs = atGroupEnd(implicit ctx => transformer.transform(dd.rhs))
rewrote = transformer.rewrote
rhs
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index 284b9e21e..de017961a 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -683,7 +683,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
*
* { val xs = es; e' = e' + args }
*/
- def typedOpAssign: Tree = track("typedOpAssign") {
+ def typedOpAssign(implicit ctx: Context): Tree = track("typedOpAssign") {
val Apply(Select(lhs, name), rhss) = tree
val lhs1 = typedExpr(lhs)
val liftedDefs = new mutable.ListBuffer[Tree]
@@ -805,16 +805,16 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
* whereas overloaded variants need to have a conforming variant.
*/
def trySelectUnapply(qual: untpd.Tree)(fallBack: Tree => Tree): Tree = {
- val genericProto = new UnapplyFunProto(WildcardType, this)
- def specificProto = new UnapplyFunProto(selType, this)
// try first for non-overloaded, then for overloaded ocurrences
def tryWithName(name: TermName)(fallBack: Tree => Tree)(implicit ctx: Context): Tree =
- tryEither {
- implicit ctx => typedExpr(untpd.Select(qual, name), specificProto)
+ tryEither { implicit ctx =>
+ val specificProto = new UnapplyFunProto(selType, this)
+ typedExpr(untpd.Select(qual, name), specificProto)
} {
(sel, _) =>
- tryEither {
- implicit ctx => typedExpr(untpd.Select(qual, name), genericProto)
+ tryEither { implicit ctx =>
+ val genericProto = new UnapplyFunProto(WildcardType, this)
+ typedExpr(untpd.Select(qual, name), genericProto)
} {
(_, _) => fallBack(sel)
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index fb0497c2b..48f9243f7 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -29,6 +29,7 @@ import ErrorReporting.{err, errorType}
import config.Printers.typr
import collection.mutable
import SymDenotations.NoCompleter
+import dotty.tools.dotc.reporting.diagnostic.messages.CantInstantiateAbstractClassOrTrait
import dotty.tools.dotc.transform.ValueClasses._
object Checking {
@@ -103,7 +104,7 @@ object Checking {
case tref: TypeRef =>
val cls = tref.symbol
if (cls.is(AbstractOrTrait))
- ctx.error(em"$cls is abstract; cannot be instantiated", pos)
+ ctx.error(CantInstantiateAbstractClassOrTrait(cls, isTrait = cls.is(Trait)), pos)
if (!cls.is(Module)) {
// Create a synthetic singleton type instance, and check whether
// it conforms to the self type of the class as seen from that instance.
diff --git a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
index 1238ad568..9d6a01ab7 100644
--- a/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -111,11 +111,23 @@ object ErrorReporting {
errorTree(tree, typeMismatchMsg(normalize(tree.tpe, pt), pt, implicitFailure.postscript))
/** A subtype log explaining why `found` does not conform to `expected` */
- def whyNoMatchStr(found: Type, expected: Type) =
- if (ctx.settings.explaintypes.value)
+ def whyNoMatchStr(found: Type, expected: Type) = {
+ def dropJavaMethod(tp: Type): Type = tp match {
+ case tp: PolyType =>
+ tp.derivedPolyType(resType = dropJavaMethod(tp.resultType))
+ case tp: JavaMethodType =>
+ MethodType(tp.paramNames, tp.paramTypes, dropJavaMethod(tp.resultType))
+ case tp => tp
+ }
+ val found1 = dropJavaMethod(found)
+ val expected1 = dropJavaMethod(expected)
+ if ((found1 eq found) != (expected eq expected1) && (found1 <:< expected1))
+ "\n (Note that Scala's and Java's representation of this type differs)"
+ else if (ctx.settings.explaintypes.value)
"\n" + ctx.typerState.show + "\n" + TypeComparer.explained((found <:< expected)(_))
else
""
+ }
def typeMismatchMsg(found: Type, expected: Type, postScript: String = "") = {
// replace constrained polyparams and their typevars by their bounds where possible
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index 6949221fb..48cf0cfac 100644
--- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
@@ -220,7 +220,7 @@ object Implicits {
}
/** The result of an implicit search */
- abstract class SearchResult extends Showable {
+ sealed abstract class SearchResult extends Showable {
def toText(printer: Printer): Text = printer.toText(this)
}
diff --git a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala
index f7efb2ac2..3bee0bbe8 100644
--- a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala
@@ -5,6 +5,7 @@ package typer
import ast.{tpd, untpd}
import ast.Trees._
import core._
+import printing.{Printer, Showable}
import util.SimpleMap
import Symbols._, Names._, Denotations._, Types._, Contexts._, StdNames._, Flags._
import Decorators.StringInterpolators
@@ -13,9 +14,9 @@ object ImportInfo {
/** The import info for a root import from given symbol `sym` */
def rootImport(refFn: () => TermRef)(implicit ctx: Context) = {
val selectors = untpd.Ident(nme.WILDCARD) :: Nil
- def expr = tpd.Ident(refFn())
- def imp = tpd.Import(expr, selectors)
- new ImportInfo(imp.symbol, selectors, None, isRootImport = true)
+ def expr(implicit ctx: Context) = tpd.Ident(refFn())
+ def imp(implicit ctx: Context) = tpd.Import(expr, selectors)
+ new ImportInfo(implicit ctx => imp.symbol, selectors, None, isRootImport = true)
}
}
@@ -27,14 +28,14 @@ object ImportInfo {
* @param isRootImport true if this is one of the implicit imports of scala, java.lang,
* scala.Predef or dotty.DottyPredef in the start context, false otherwise.
*/
-class ImportInfo(symf: => Symbol, val selectors: List[untpd.Tree],
- symNameOpt: Option[TermName], val isRootImport: Boolean = false)(implicit ctx: Context) {
+class ImportInfo(symf: Context => Symbol, val selectors: List[untpd.Tree],
+ symNameOpt: Option[TermName], val isRootImport: Boolean = false) extends Showable {
// Dotty deviation: we cannot use a lazy val here for the same reason
// that we cannot use one for `DottyPredefModuleRef`.
- def sym = {
+ def sym(implicit ctx: Context) = {
if (mySym == null) {
- mySym = symf
+ mySym = symf(ctx)
assert(mySym != null)
}
mySym
@@ -91,7 +92,7 @@ class ImportInfo(symf: => Symbol, val selectors: List[untpd.Tree],
}
/** The implicit references imported by this import clause */
- def importedImplicits: List[TermRef] = {
+ def importedImplicits(implicit ctx: Context): List[TermRef] = {
val pre = site
if (isWildcardImport) {
val refs = pre.implicitMembers
@@ -115,23 +116,21 @@ class ImportInfo(symf: => Symbol, val selectors: List[untpd.Tree],
* override import Predef.{any2stringAdd => _, StringAdd => _, _} // disables String +
* override import java.lang.{} // disables all imports
*/
- lazy val unimported: Symbol = {
- lazy val sym = site.termSymbol
- def maybeShadowsRoot = symNameOpt match {
- case Some(symName) => defn.ShadowableImportNames.contains(symName)
- case None => false
+ def unimported(implicit ctx: Context): Symbol = {
+ if (myUnimported == null) {
+ lazy val sym = site.termSymbol
+ def maybeShadowsRoot = symNameOpt match {
+ case Some(symName) => defn.ShadowableImportNames.contains(symName)
+ case None => false
+ }
+ myUnimported =
+ if (maybeShadowsRoot && defn.RootImportTypes.exists(_.symbol == sym)) sym
+ else NoSymbol
+ assert(myUnimported != null)
}
- if (maybeShadowsRoot && defn.RootImportTypes.exists(_.symbol == sym)) sym
- else NoSymbol
+ myUnimported
}
+ private[this] var myUnimported: Symbol = _
- override def toString = {
- val siteStr = site.show
- val exprStr = if (siteStr endsWith ".type") siteStr dropRight 5 else siteStr
- val selectorStr = selectors match {
- case Ident(name) :: Nil => name.show
- case _ => "{...}"
- }
- i"import $exprStr.$selectorStr"
- }
+ def toText(printer: Printer) = printer.toText(this)
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala
index fde304c69..27c7d0c2f 100644
--- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala
@@ -27,7 +27,7 @@ import transform.TypeUtils._
object Inliner {
import tpd._
- /** Adds accessors accessors for all non-public term members accessed
+ /** Adds accessors for all non-public term members accessed
* from `tree`. Non-public type members are currently left as they are.
* This means that references to a private type will lead to typing failures
* on the code when it is inlined. Less than ideal, but hard to do better (see below).
@@ -190,7 +190,8 @@ object Inliner {
val inlineCtx = ctx
sym.updateAnnotation(LazyBodyAnnotation { _ =>
implicit val ctx = inlineCtx
- ctx.withNoError(treeExpr(ctx))(makeInlineable)
+ val body = treeExpr(ctx)
+ if (ctx.reporter.hasErrors) body else makeInlineable(body)
})
}
}
@@ -233,8 +234,10 @@ object Inliner {
* and body that replace it.
*/
def inlineCall(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
- if (enclosingInlineds.length < ctx.settings.xmaxInlines.value)
- new Inliner(tree, bodyToInline(tree.symbol)).inlined(pt)
+ if (enclosingInlineds.length < ctx.settings.xmaxInlines.value) {
+ val body = bodyToInline(tree.symbol) // can typecheck the tree and thereby produce errors
+ if (ctx.reporter.hasErrors) tree else new Inliner(tree, body).inlined(pt)
+ }
else errorTree(
tree,
i"""|Maximal number of successive inlines (${ctx.settings.xmaxInlines.value}) exceeded,
diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala
index 3860ba225..d5f171fe3 100644
--- a/compiler/src/dotty/tools/dotc/typer/Namer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala
@@ -24,6 +24,7 @@ import language.implicitConversions
import reporting.diagnostic.messages._
trait NamerContextOps { this: Context =>
+ import NamerContextOps._
/** Enter symbol into current class, if current class is owner of current context,
* or into current scope, if not. Should always be called instead of scope.enter
@@ -119,22 +120,25 @@ trait NamerContextOps { this: Context =>
else monotpe
}
- /** Find moduleClass/sourceModule in effective scope */
- private def findModuleBuddy(name: Name)(implicit ctx: Context) = {
- val scope = effectiveScope
- val it = scope.lookupAll(name).filter(_ is Module)
- assert(it.hasNext, s"no companion $name in $scope")
- it.next
- }
-
/** Add moduleClass or sourceModule functionality to completer
* for a module or module class
*/
- def adjustModuleCompleter(completer: LazyType, name: Name) =
+ def adjustModuleCompleter(completer: LazyType, name: Name) = {
+ val scope = this.effectiveScope
if (name.isTermName)
- completer withModuleClass (_ => findModuleBuddy(name.moduleClassName))
+ completer withModuleClass (implicit ctx => findModuleBuddy(name.moduleClassName, scope))
else
- completer withSourceModule (_ => findModuleBuddy(name.sourceModuleName))
+ completer withSourceModule (implicit ctx => findModuleBuddy(name.sourceModuleName, scope))
+ }
+}
+
+object NamerContextOps {
+ /** Find moduleClass/sourceModule in effective scope */
+ private def findModuleBuddy(name: Name, scope: Scope)(implicit ctx: Context) = {
+ val it = scope.lookupAll(name).filter(_ is Module)
+ assert(it.hasNext, s"no companion $name in $scope")
+ it.next
+ }
}
/** This class creates symbols from definitions and imports and gives them
@@ -378,7 +382,7 @@ class Namer { typer: Typer =>
case ref: RefTree => Some(ref.name.asTermName)
case _ => None
}
- ctx.fresh.setImportInfo(new ImportInfo(sym, imp.selectors, impNameOpt))
+ ctx.fresh.setImportInfo(new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt))
}
/** A new context for the interior of a class */
diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala
index eab91701b..7c573d23c 100644
--- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -789,7 +789,7 @@ class RefChecks extends MiniPhase { thisTransformer =>
val sym = tree.symbol
if (sym.exists && sym.owner.isTerm && !sym.is(Lazy))
currentLevel.levelAndIndex.get(sym) match {
- case Some((level, symIdx)) if symIdx < level.maxIndex =>
+ case Some((level, symIdx)) if symIdx <= level.maxIndex =>
ctx.error(ForwardReferenceExtendsOverDefinition(sym, level.refSym), level.refPos)
case _ =>
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index 498fd001b..06200d3e4 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -145,7 +145,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
*/
def bindingString(prec: Int, whereFound: Context, qualifier: String = "") =
if (prec == wildImport || prec == namedImport) {
- ex"""imported$qualifier by ${hl"${whereFound.importInfo.toString}"}"""
+ ex"""imported$qualifier by ${hl"${whereFound.importInfo}"}"""
} else
ex"""defined$qualifier in ${hl"${whereFound.owner.toString}"}"""
@@ -1964,7 +1964,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (Inliner.hasBodyToInline(tree.symbol) &&
!ctx.owner.ownersIterator.exists(_.isInlineMethod) &&
!ctx.settings.YnoInline.value &&
- !ctx.isAfterTyper)
+ !ctx.isAfterTyper &&
+ !ctx.reporter.hasErrors)
adapt(Inliner.inlineCall(tree, pt), pt)
else if (ctx.typeComparer.GADTused && pt.isValueType)
// Insert an explicit cast, so that -Ycheck in later phases succeeds.
diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala
index 7af903364..a720f1294 100644
--- a/compiler/test/dotc/tests.scala
+++ b/compiler/test/dotc/tests.scala
@@ -184,6 +184,7 @@ class tests extends CompilerTest {
@Test def neg_autoTupling = compileFile(negCustomArgs, "autoTuplingTest", args = "-language:noAutoTupling" :: Nil)
@Test def neg_i1050 = compileFile(negCustomArgs, "i1050", List("-strict"))
@Test def neg_i1240 = compileFile(negCustomArgs, "i1240")(allowDoubleBindings)
+ @Test def neg_i2002 = compileFile(negCustomArgs, "i2002")(allowDoubleBindings)
val negTailcallDir = negDir + "tailcall/"
@Test def neg_tailcall_t1672b = compileFile(negTailcallDir, "t1672b")
diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
index 37d1404bb..971a40a1b 100644
--- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
+++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
@@ -159,4 +159,43 @@ class ErrorMessagesTests extends ErrorMessagesTest {
assertEquals("+:", op2.show)
assertFalse(op2LeftAssoc)
}
+
+ @Test def cantInstantiateAbstract =
+ checkMessagesAfter("refchecks") {
+ """
+ |object Scope {
+ | abstract class Concept
+ | new Concept()
+ |}
+ """.stripMargin
+ }
+ .expect { (ictx, messages) =>
+ implicit val ctx: Context = ictx
+ val defn = ictx.definitions
+
+ assertMessageCount(1, messages)
+ val CantInstantiateAbstractClassOrTrait(cls, isTrait) :: Nil = messages
+ assertEquals("Concept", cls.name.show)
+ assertFalse("expected class", isTrait)
+ }
+
+ @Test def cantInstantiateTrait =
+ checkMessagesAfter("refchecks") {
+ """
+ |object Scope {
+ | trait Concept
+ | new Concept()
+ |}
+ """.stripMargin
+ }
+ .expect { (ictx, messages) =>
+ implicit val ctx: Context = ictx
+ val defn = ictx.definitions
+
+ assertMessageCount(1, messages)
+ val CantInstantiateAbstractClassOrTrait(cls, isTrait) :: Nil = messages
+ assertEquals("Concept", cls.name.show)
+ assertTrue("expected trait", isTrait)
+ }
+
}
diff --git a/doc-tool/resources/_layouts/api-page.html b/doc-tool/resources/_layouts/api-page.html
index 26a4290da..878ec8d8f 100644
--- a/doc-tool/resources/_layouts/api-page.html
+++ b/doc-tool/resources/_layouts/api-page.html
@@ -95,7 +95,7 @@ extraCSS:
{% for member in entity.members %}
<div id="{{ member.signature }}" class="member {% if member.isPrivate %}private{% elsif member.isProtected %}protected{% endif %}">
<div class="member-title">
- <span class="expand-button" onclick="toggleMemberBody(this, '{{ member.signature }}');">[+]</span>
+ <span class="expand-button {% if member.hasShortenedDocstring == false %}invisible{% endif %}" onclick="toggleMemberBody(this, '{{ member.signature }}');">[+]</span>
<span class="member-annotations">
{% for annot in member.annotations %}@{{ annot | split: '.' | last }} {% endfor %}
</span>
diff --git a/doc-tool/resources/css/api-page.css b/doc-tool/resources/css/api-page.css
index 380efb834..1dd4f559c 100644
--- a/doc-tool/resources/css/api-page.css
+++ b/doc-tool/resources/css/api-page.css
@@ -122,6 +122,11 @@ div.entity-section > div.member > div.member-title > span.expand-button:hover {
user-select: none;
}
+div.entity-section > div.member > div.member-title > span.expand-button.invisible,
+div.entity-section > div.member > div.member-title > span.expand-button.invisible:hover {
+ color: transparent;
+}
+
div.entity-section > div.member > div.member-body {
margin: 5px 0 0 39px;
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
index 708c26cc0..c5d20d30b 100644
--- a/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/DocCompiler.scala
@@ -32,6 +32,7 @@ class DocCompiler extends Compiler {
new LinkSuperTypes,
new LinkCompanions,
new AlternateConstructors,
- new SortMembers))
+ new SortMembers)),
+ List(new StatisticsPhase)
)
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala b/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala
index 515de9ae9..1434d5a49 100644
--- a/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/DocDriver.scala
@@ -9,6 +9,7 @@ import model.Package
import dotc.config._
import dotc.core.Comments.ContextDoc
import staticsite.Site
+import dotc.printing.Highlighting._
/** `DocDriver` implements the main entry point to the Dotty documentation
* tool. It's methods are used by the external scala and java APIs.
@@ -43,16 +44,18 @@ class DocDriver extends Driver {
implicit val (filesToDocument, ctx) = setup(args, initCtx.fresh)
val reporter = doCompile(newCompiler(ctx), filesToDocument)(ctx)
val siteRoot = new java.io.File(ctx.settings.siteRoot.value)
+ val projectName = ctx.settings.projectName.value
if (!siteRoot.exists || !siteRoot.isDirectory)
ctx.error(s"Site root does not exist: $siteRoot")
else {
- Site(siteRoot, ctx.settings.projectName.value, ctx.docbase.packages)
+ Site(siteRoot, projectName, ctx.docbase.packages)
.generateApiDocs()
.copyStaticFiles()
.generateHtmlFiles()
.generateBlog()
+ ctx.docbase.printSummary()
System.exit(if (reporter.hasErrors) 1 else 0)
}
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala b/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
index 16f0776fa..8f463833d 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
@@ -2,9 +2,12 @@ package dotty.tools
package dottydoc
package core
-import dotc.core.Symbols.Symbol
+import dotc.core.Symbols._
+import dotc.core.Flags._
+import dotc.core.Decorators._
import dotc.core.Comments.ContextDocstrings
-import model.Package
+import model.{ Package, Entity }
+import model.comment.Comment
import dotc.core.Contexts.Context
import dotc.printing.Highlighting._
@@ -17,6 +20,12 @@ class ContextDottydoc extends ContextDocstrings {
def packages: Map[String, Package] = _packages.toMap
def packagesMutable: mutable.Map[String, Package] = _packages
+ private[this] var _statistics: Map[String, Statistics] = Map.empty
+ def registerStatistics(pkgName: String, stat: Statistics): Unit =
+ _statistics = _statistics + (pkgName -> stat)
+
+ def statistics: Map[String, Statistics] = _statistics
+
/** Should perhaps factorize this into caches that get flushed */
private var _defs: Map[Symbol, Set[Symbol]] = Map.empty
def defs(sym: Symbol): Set[Symbol] = _defs.get(sym).getOrElse(Set.empty)
@@ -49,4 +58,77 @@ class ContextDottydoc extends ContextDocstrings {
}.toString, pos)
def debug(msg: String)(implicit ctx: Context): Unit = debug(msg, NoSourcePosition)
+
+ def printSummary()(implicit ctx: Context): Unit = {
+ def colored(part: Int, total: Int) =
+ if (total == 0) "0"
+ else {
+ val percentage = (part * 100.0 / total).toInt
+ val str = s"$part/$total ($percentage%)"
+
+ if (percentage > 75) Green(str)
+ else if (percentage > 50) Yellow(str)
+ else Red(str)
+ }
+
+ val totalEntities = statistics.totalEntities
+
+ val projectName = ctx.settings.projectName.value
+ val warningsText =
+ if (ctx.reporter.hasWarnings)
+ s"total warnings with regards to compilation and documentation: ${ctx.reporter.warningCount}"
+ else ""
+
+ val api = statistics.values.iterator.map(_.api).foldLeft(Counters(0,0,0,0,0,0))(_ merge _)
+ val internalApi = statistics.values.iterator.map(_.internalApi).foldLeft(Counters(0,0,0,0,0,0))(_ merge _)
+
+ val apiSummary = (for {
+ (pkgName, stat) <- statistics.toList.sortBy(_._1)
+ } yield {
+ val pub = colored(stat.api.publicDocstrings, stat.api.publicEntities)
+ val pro = colored(stat.api.protectedDocstrings, stat.api.protectedEntities)
+ s"""|package $pkgName
+ |${Blue("-" * ctx.settings.pageWidth.value)}
+ |public: $pub \t protected: $pro
+ |""".stripMargin
+ }).mkString("\n")
+
+ val internalSummary = (for {
+ (pkgName, stat) <- statistics.toList.sortBy(_._1)
+ } yield {
+ val pub = colored(stat.internalApi.publicDocstrings, stat.internalApi.publicEntities)
+ val pro = colored(stat.internalApi.protectedDocstrings, stat.internalApi.protectedEntities)
+ val pri = colored(stat.internalApi.privateDocstrings, stat.internalApi.privateEntities)
+ s"""|package $pkgName
+ |${Blue("-" * ctx.settings.pageWidth.value)}
+ |public: $pub \t protected: $pro \t private: $pri
+ |""".stripMargin
+ }).mkString("\n")
+
+ ctx.echo {
+ s"""|${Blue("=" * ctx.settings.pageWidth.value)}
+ |Dottydoc summary report for project `$projectName`
+ |${Blue("=" * ctx.settings.pageWidth.value)}
+ |Documented members in public API:
+ |
+ |$apiSummary
+ |
+ |Summary:
+ |
+ |public members with docstrings: ${colored(api.publicDocstrings, api.publicEntities)}
+ |${hl"${"protected"}"} members with docstrings: ${colored(api.protectedDocstrings, api.protectedEntities)}
+ |${Blue("=" * ctx.settings.pageWidth.value)}
+ |
+ |Documented members in internal API:
+ |
+ |$internalSummary
+ |
+ |Summary internal API:
+ |
+ |public members with docstrings: ${colored(internalApi.publicDocstrings, internalApi.publicEntities)}
+ |${hl"${"protected"}"} members with docstrings: ${colored(internalApi.protectedDocstrings, internalApi.protectedEntities)}
+ |${hl"${"private"}"} members with docstrings: ${colored(internalApi.privateDocstrings, internalApi.privateEntities)}
+ |$warningsText""".stripMargin
+ }
+ }
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
index 460566838..7f44c5656 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
@@ -226,7 +226,7 @@ class DocASTPhase extends Phase {
override def run(implicit ctx: Context): Unit = {
currentRun += 1
- ctx.docbase.echo(s"Compiling ($currentRun/$totalRuns): ${ctx.compilationUnit.source.file.name}")
+ ctx.echo(s"Compiling ($currentRun/$totalRuns): ${ctx.compilationUnit.source.file.name}")
collect(ctx.compilationUnit.tpdTree) // Will put packages in `packages` var
}
@@ -237,8 +237,7 @@ class DocASTPhase extends Phase {
// (2) Set parents of entities, needed for linking
for {
- parentName <- rootPackages(packages)
- parent = packages(parentName)
+ parent <- rootPackages(packages)
child <- parent.members
} setParent(child, to = parent)
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
index 3de8f68f7..2471e9220 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocstringPhase.scala
@@ -14,6 +14,7 @@ import util.syntax._
/** Phase to add docstrings to the Dottydoc AST */
class DocstringPhase extends DocMiniPhase with CommentParser with CommentCleaner {
+
private def getComment(sym: Symbol)(implicit ctx: Context): Option[CompilerComment] =
ctx.docbase.docstring(sym)
.orElse {
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala
new file mode 100644
index 000000000..e7f9a9ec7
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala
@@ -0,0 +1,156 @@
+package dotty.tools
+package dottydoc
+package core
+
+import dotc.core.Phases.Phase
+import dotc.core.Contexts.Context
+import dotc.core.Symbols.Symbol
+import dotc.core.Decorators._
+import dotc.core.Flags._
+import dotc.CompilationUnit
+import dottydoc.util.syntax._
+import dottydoc.util.traversing._
+
+import model._
+
+object Statistics {
+ implicit class MapTotals(val map: Map[String, Statistics]) extends AnyVal {
+ def totalEntities =
+ map.values.foldLeft(0)(_ + _.totalEntities)
+ }
+}
+
+case class Statistics(pkgName: String, api: Counters, internalApi: Counters) {
+ def totalEntities =
+ api.totalEntities + internalApi.totalEntities
+
+ def totalDocstrings =
+ api.totalDocstrings + internalApi.totalDocstrings
+}
+
+case class Counters(
+ publicEntities: Int,
+ privateEntities: Int,
+ protectedEntities: Int,
+
+ publicDocstrings: Int,
+ privateDocstrings: Int,
+ protectedDocstrings: Int
+) {
+ def totalEntities =
+ publicEntities + privateEntities + protectedEntities
+
+ def totalDocstrings =
+ publicDocstrings + privateDocstrings + protectedDocstrings
+
+ def merge(o: Counters): Counters = Counters(
+ publicEntities + o.publicEntities,
+ privateEntities + o.privateEntities,
+ protectedEntities + o.protectedEntities,
+ publicDocstrings + o.publicDocstrings,
+ privateDocstrings + o.privateDocstrings,
+ protectedDocstrings + o.protectedDocstrings
+ )
+}
+
+class StatisticsPhase extends Phase {
+
+ def phaseName = "StatisticsPhase"
+
+ override def run(implicit ctx: Context): Unit = ()
+
+ override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = {
+ for {
+ (pkgName, pack) <- ctx.docbase.packages
+ externalApi = collectPublicStats(pack)
+ internalApi = collectInternalStats(pack)
+ stats = Statistics(pkgName, externalApi, internalApi)
+ } ctx.docbase.registerStatistics(pkgName, stats)
+
+ units
+ }
+
+ def collectPublicStats(pack: Package)(implicit ctx: Context): Counters = {
+ var publicEntities: Int = 0
+ var protectedEntities: Int = 0
+ var publicDocstrings: Int = 0
+ var protectedDocstrings: Int = 0
+
+ if (pack.comment.isDefined) {
+ publicEntities += 1
+ publicDocstrings += 1
+ }
+
+ def doCount(sym: Symbol, comment: Int): Unit =
+ if (!sym.is(Protected)) {
+ publicEntities += 1
+ publicDocstrings += comment
+ }
+ else {
+ protectedEntities += 1
+ protectedDocstrings += comment
+ }
+
+
+ def recur(e: Entity, reachable: Boolean): Unit = {
+ val isVisible = !e.symbol.is(Private) && !e.symbol.privateWithin.exists
+ val shouldCount = isVisible && reachable
+ e match {
+ case e: Package => ()
+ case e: Entity with Members => if (shouldCount) {
+ doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ e.members.foreach { c =>
+ if (!(e.symbol.is(Final) && c.symbol.is(Protected))) recur(c, true)
+ }
+ }
+ case e =>
+ if (shouldCount) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ }
+ }
+
+ pack.members.foreach(recur(_, true))
+ Counters(publicEntities, 0, protectedEntities, publicDocstrings, 0, protectedDocstrings)
+ }
+
+ def collectInternalStats(pack: Package)(implicit ctx: Context): Counters = {
+ var publicEntities: Int = 0
+ var privateEntities: Int = 0
+ var protectedEntities: Int = 0
+ var publicDocstrings: Int = 0
+ var privateDocstrings: Int = 0
+ var protectedDocstrings: Int = 0
+
+ def doCount(sym: Symbol, comment: Int): Unit =
+ if (sym.is(Private)) {
+ privateEntities += 1
+ privateDocstrings += comment
+ }
+ else if (!sym.is(Protected)) {
+ publicEntities += 1
+ publicDocstrings += comment
+ }
+ else {
+ protectedEntities += 1
+ protectedDocstrings += comment
+ }
+
+
+ def recur(e: Entity, reachable: Boolean): Unit = {
+ val internal = !reachable || e.symbol.is(Private) || e.symbol.privateWithin.exists
+ e match {
+ case _: Package => ()
+ case e: Entity with Members =>
+ e.members.foreach { c =>
+ val childIsInternal = !internal || (e.symbol.is(Final) && c.symbol.is(Protected))
+ recur(c, childIsInternal)
+ }
+ if (internal) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ case _ =>
+ if (internal) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ }
+ }
+
+ pack.members.foreach(recur(_, true))
+ Counters(publicEntities, privateEntities, protectedEntities, publicDocstrings, privateDocstrings, protectedDocstrings)
+ }
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
index 1f30e089d..e4b9ae6b6 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
@@ -45,15 +45,15 @@ object transform {
* -------------------------
* To delete a node in the AST, simply return `NonEntity` from transforming method
*/
- abstract class DocMiniTransformations(transformations: List[DocMiniPhase]) extends Phase {
+ trait DocMiniTransformations extends Phase {
+ def transformations: List[DocMiniPhase]
override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = {
for {
- rootName <- rootPackages(ctx.docbase.packages)
- pack = ctx.docbase.packages(rootName)
+ pack <- rootPackages(ctx.docbase.packages)
transformed = performPackageTransform(pack)
- } yield ctx.docbase.packagesMutable(rootName) = transformed
- super.runOn(units)
+ } yield ctx.docbase.packagesMutable(pack.name) = transformed
+ units
}
private def performPackageTransform(pack: Package)(implicit ctx: Context): Package = {
@@ -197,8 +197,9 @@ object transform {
object DocMiniTransformations {
private var previousPhase = 0
- def apply(transformations: DocMiniPhase*) =
- new DocMiniTransformations(transformations.toList) {
+ def apply(miniPhases: DocMiniPhase*) =
+ new DocMiniTransformations {
+ val transformations = miniPhases.toList
val packages = Map.empty[String, Package]
def phaseName = s"MiniTransformation${ previousPhase += 1 }"
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
index e7cf54a03..239656141 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
@@ -55,6 +55,7 @@ object JavaConverters {
"comment" -> ent.comment.map(_.asJava).asJava,
"superTypes" -> ent.superTypes,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"signature" -> ent.signature
) ++ extras).asJava
}
@@ -74,6 +75,7 @@ object JavaConverters {
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"hasCompanion" -> ent.hasCompanion,
"companionPath" -> ent.companionPath.asJava,
"signature" -> ent.signature
@@ -95,6 +97,7 @@ object JavaConverters {
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"hasCompanion" -> ent.hasCompanion,
"companionPath" -> ent.companionPath.asJava,
"signature" -> ent.signature
@@ -115,6 +118,7 @@ object JavaConverters {
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"hasCompanion" -> ent.hasCompanion,
"companionPath" -> ent.companionPath.asJava,
"signature" -> ent.signature
@@ -134,6 +138,7 @@ object JavaConverters {
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"hasVisibleMembers" -> ent.hasVisibleMembers,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"hasCompanion" -> ent.hasCompanion,
"companionPath" -> ent.companionPath.asJava,
"signature" -> ent.signature
@@ -152,6 +157,7 @@ object JavaConverters {
"paramLists" -> ent.paramLists.map(_.asJava).asJava,
"comment" -> ent.comment.map(_.asJava).asJava,
"implicitlyAddedFrom" -> ent.implicitlyAddedFrom.map(_.asJava).asJava,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"signature" -> ent.signature
@@ -168,6 +174,7 @@ object JavaConverters {
"returnValue" -> ent.returnValue.asJava,
"comment" -> ent.comment.map(_.asJava).asJava,
"implicitlyAddedFrom" -> ent.implicitlyAddedFrom.map(_.asJava).asJava,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"signature" -> ent.signature
@@ -183,6 +190,7 @@ object JavaConverters {
"path" -> ent.path.asJava,
"alias" -> ent.alias.map(_.asJava).asJava,
"comment" -> ent.comment.map(_.asJava).asJava,
+ "hasShortenedDocstring" -> ent.hasShortenedDocstring,
"isPrivate" -> ent.isPrivate,
"isProtected" -> ent.isProtected,
"signature" -> ent.signature
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
index 9cbd1f6c8..d35077816 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
@@ -21,6 +21,9 @@ trait Entity { entity =>
def annotations: List[String]
+ def hasShortenedDocstring: Boolean =
+ comment.map(d => d.body.length > d.short.length).getOrElse(false)
+
def signature: String =
entity.name + (entity match {
case o: Object => "$"
diff --git a/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala b/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala
index 9c2e3bf54..956cb9291 100644
--- a/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/util/traversing.scala
@@ -24,7 +24,7 @@ object traversing {
}
- def rootPackages(pkgs: Map[String, Package]): List[String] = {
+ def rootPackages(pkgs: Map[String, Package]): List[Package] = {
var currentDepth = Int.MaxValue
var packs = List.empty[String]
@@ -38,6 +38,6 @@ object traversing {
key :: packs
} else packs
}
- packs
+ packs.map(pkgs.apply)
}
}
diff --git a/project/Build.scala b/project/Build.scala
index f03111f76..376e06bb1 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -56,6 +56,9 @@ object DottyBuild extends Build {
// Compiles the documentation and static site
lazy val genDocs = inputKey[Unit]("run dottydoc to generate static documentation site")
+ // Shorthand for compiling a docs site
+ lazy val dottydoc = inputKey[Unit]("run dottydoc")
+
/** Dottydoc deps */
lazy val dottydocDeps = SettingKey[Seq[ModuleID]](
"dottydocDeps",
@@ -273,17 +276,25 @@ object DottyBuild extends Build {
)
}.evaluated,
+ dottydoc := Def.inputTaskDyn {
+ val args: Seq[String] = spaceDelimited("<arg>").parsed
+ val dottyLib = packageAll.value("dotty-library")
+ val dottyInterfaces = packageAll.value("dotty-interfaces")
+ val otherDeps = (dependencyClasspath in Compile).value.map(_.data).mkString(":")
+ val cp: Seq[String] = Seq("-classpath", s"$dottyLib:$dottyInterfaces:$otherDeps")
+ (runMain in Compile).toTask(s""" dotty.tools.dottydoc.Main ${cp.mkString(" ")} """ + args.mkString(" "))
+ }.evaluated,
+
// Override run to be able to run compiled classfiles
dotr := {
val args: Seq[String] = spaceDelimited("<arg>").parsed
- val java: String = Process("which" :: "java" :: Nil) !!
- val scalaLib = (dependencyClasspath in Runtime, packageAll)
- .map { (attList, _) =>
- attList
- .map(_.data.getAbsolutePath)
- .find(_.contains("scala-library"))
- .toList.mkString(":")
- }.value
+ val java: String = Process("which" :: "java" :: Nil).!!
+ val attList = (dependencyClasspath in Runtime).value
+ val _ = packageAll.value
+ val scalaLib = attList
+ .map(_.data.getAbsolutePath)
+ .find(_.contains("scala-library"))
+ .toList.mkString(":")
if (java == "")
println("Couldn't find java executable on path, please install java to a default location")
@@ -291,7 +302,7 @@ object DottyBuild extends Build {
println("Couldn't find scala-library on classpath, please run using script in bin dir instead")
} else {
val dottyLib = packageAll.value("dotty-library")
- s"""$java -classpath .:$dottyLib:$scalaLib ${args.mkString(" ")}""" !
+ s"""$java -classpath .:$dottyLib:$scalaLib ${args.mkString(" ")}""".!
}
},
run := Def.inputTaskDyn {
@@ -327,7 +338,7 @@ object DottyBuild extends Build {
partestLockFile.createNewFile
partestLockFile.deleteOnExit
},
- runPartestRunner <<= Def.inputTaskDyn {
+ runPartestRunner := Def.inputTaskDyn {
// Magic! This is both an input task and a dynamic task. Apparently
// command line arguments get passed to the last task in an aliased
// sequence (see partest alias below), so this works.
@@ -341,7 +352,7 @@ object DottyBuild extends Build {
s"""-dottyJars ${jars.length + 2} dotty.jar dotty-lib.jar ${jars.mkString(" ")}"""
// Provide the jars required on the classpath of run tests
runTask(Test, "dotty.partest.DPConsoleRunner", dottyJars + " " + args.mkString(" "))
- },
+ }.evaluated,
/* Add the sources of scalajs-ir.
* To guarantee that dotty can bootstrap without depending on a version
@@ -386,7 +397,10 @@ object DottyBuild extends Build {
// http://grokbase.com/t/gg/simple-build-tool/135ke5y90p/sbt-setting-jvm-boot-paramaters-for-scala
// packageAll should always be run before tests
- javaOptions <++= (dependencyClasspath in Runtime, packageAll) map { (attList, pA) =>
+ javaOptions ++= {
+ val attList = (dependencyClasspath in Runtime).value
+ val pA = packageAll.value
+
// put needed dependencies on classpath:
val path = for {
file <- attList.map(_.data)
@@ -632,7 +646,7 @@ object DottyInjectedPlugin extends AutoPlugin {
/* Make sure jsDependencyManifest runs after compile, otherwise compile
* might remove the entire directory afterwards.
*/
- jsDependencyManifest <<= jsDependencyManifest.dependsOn(compile)
+ jsDependencyManifest := jsDependencyManifest.dependsOn(compile).value
)))
lazy val `dotty-bench` = project.in(file("bench")).
@@ -652,7 +666,10 @@ object DottyInjectedPlugin extends AutoPlugin {
parallelExecution in Test := false,
// http://grokbase.com/t/gg/simple-build-tool/135ke5y90p/sbt-setting-jvm-boot-paramaters-for-scala
- javaOptions <++= (dependencyClasspath in Runtime, packageBin in Compile) map { (attList, bin) =>
+ javaOptions ++= {
+ val attList = (dependencyClasspath in Runtime).value
+ val bin = (packageBin in Compile).value
+
// put the Scala {library, reflect, compiler} in the classpath
val path = for {
file <- attList.map(_.data)
diff --git a/tests/neg/customArgs/i2002.scala b/tests/neg/customArgs/i2002.scala
new file mode 100644
index 000000000..5561b77b8
--- /dev/null
+++ b/tests/neg/customArgs/i2002.scala
@@ -0,0 +1,4 @@
+class Test {
+ def foo(i: Int): Int = i
+ def foo(implicit i: Int): Int = i // error
+}
diff --git a/tests/neg/i1747.scala b/tests/neg/i1747.scala
new file mode 100644
index 000000000..54492aaed
--- /dev/null
+++ b/tests/neg/i1747.scala
@@ -0,0 +1,3 @@
+class Coll[E] extends java.util.Collection[E] { // error: needs to be abstract
+ def toArray[T](a: Array[T]): Array[T] = ??? // error: cannot override
+}
diff --git a/tests/neg/i1992.scala b/tests/neg/i1992.scala
new file mode 100644
index 000000000..818b46771
--- /dev/null
+++ b/tests/neg/i1992.scala
@@ -0,0 +1,9 @@
+object Test {
+ def main(args: Array[String]) = {
+ val x: Int => Unit =
+ y => println(x) // error: `x` is a forward reference
+ implicit val z: String => Unit =
+ y => println(implicitly[String => Unit]) // error: `z` is a forward reference
+ }
+}
+
diff --git a/tests/neg/i2000.scala b/tests/neg/i2000.scala
new file mode 100644
index 000000000..aa1250f08
--- /dev/null
+++ b/tests/neg/i2000.scala
@@ -0,0 +1,23 @@
+object test1 {
+ class C[A] { def foo(a: A) = "c" }
+ class D extends C[String] { override def foo(implicit s: String) = "d" } // error
+}
+
+object test2 {
+ class C[A] { final def foo(a: A) = "c" }
+ class D extends C[String] { def foo(implicit s: String) = "d" } // error
+ object Test {
+ def main(args: Array[String]) =
+ new D
+ }
+}
+
+object test3 {
+ class A {
+ def foo(implicit i: Int): Int = i + i
+ }
+
+ class B extends A {
+ override def foo(i: Int): Int = i // error
+ }
+}
diff --git a/tests/neg/i2005.scala b/tests/neg/i2005.scala
new file mode 100644
index 000000000..fc2e4ddec
--- /dev/null
+++ b/tests/neg/i2005.scala
@@ -0,0 +1,7 @@
+
+object Test {
+ val a = 42
+ def main(args: Array[String]) = {
+ val a: Int = a // error
+ }
+}
diff --git a/tests/neg/i2006.scala b/tests/neg/i2006.scala
new file mode 100644
index 000000000..f1b48b011
--- /dev/null
+++ b/tests/neg/i2006.scala
@@ -0,0 +1,10 @@
+object Test {
+
+ inline def foo(f: ImplicitFunction1[Int, Int]): AnyRef = f // error
+ inline def bar(f: ImplicitFunction1[Int, Int]) = f // error
+
+ def main(args: Array[String]) = {
+ foo(implicit thisTransaction => 43)
+ bar(implicit thisTransaction => 44)
+ }
+}
diff --git a/tests/pos/i2009.scala b/tests/pos/i2009.scala
new file mode 100644
index 000000000..e2cf47203
--- /dev/null
+++ b/tests/pos/i2009.scala
@@ -0,0 +1,9 @@
+object Test {
+
+ trait Gen[T] {
+ def map[U](f: T => U): Gen[U] = ???
+ }
+
+ def f[T](implicit g: Gen[T]): Gen[() => T] =
+ g map ( () => _ )
+}
diff --git a/tests/repl/imports.check b/tests/repl/imports.check
index 5260589a9..345fac142 100644
--- a/tests/repl/imports.check
+++ b/tests/repl/imports.check
@@ -11,7 +11,7 @@ scala> buf += xs
11 |buf += xs
| ^^
| found: scala.collection.immutable.List[Int](o.xs)
- | required: String
+ | required: Int
|
scala> buf ++= xs
val res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 2, 3)
diff --git a/tests/run/i2020.scala b/tests/run/i2020.scala
new file mode 100644
index 000000000..78794a590
--- /dev/null
+++ b/tests/run/i2020.scala
@@ -0,0 +1,8 @@
+object Test {
+
+ case class Foo(x: Int)(y: Int)
+
+ def main(args: Array[String]) =
+ assert(Foo(1)(1) == Foo(1)(2))
+
+}