aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala19
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala44
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java1
-rw-r--r--compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala14
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Applications.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/util/SourcePosition.scala8
-rw-r--r--compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala14
-rw-r--r--doc-tool/resources/_layouts/api-page.html15
-rw-r--r--doc-tool/resources/css/dottydoc.css6
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala14
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/transform.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala3
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/entities.scala2
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/factories.scala18
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/model/internal.scala1
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala1
-rw-r--r--tests/neg/customArgs/typers.scala2
-rw-r--r--tests/neg/i1050c.scala3
-rw-r--r--tests/neg/i2030.scala5
-rw-r--r--tests/neg/i2033.scala21
-rw-r--r--tests/run/builder.check2
-rw-r--r--tests/run/builder.scala12
-rw-r--r--tests/run/hmap.scala97
29 files changed, 277 insertions, 59 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index 847177e2f..79e97becb 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -906,13 +906,6 @@ class Definitions {
/** The type of the boxed class corresponding to primitive value type `tp`. */
def boxedType(tp: Type)(implicit ctx: Context): TypeRef = boxedTypes(scalaClassName(tp))
- def wrapArrayMethodName(elemtp: Type): TermName = {
- val cls = elemtp.classSymbol
- if (cls.isPrimitiveValueClass) nme.wrapXArray(cls.name)
- else if (cls.derivesFrom(ObjectClass) && !cls.isPhantomClass) nme.wrapRefArray
- else nme.genericWrapArray
- }
-
type PrimitiveClassEnc = Int
val ByteEnc = 2
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index c14108d2e..b27bff37a 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -1607,6 +1607,7 @@ object Parsers {
* LocalModifier ::= abstract | final | sealed | implicit | lazy
*/
def modifiers(allowed: BitSet = modifierTokens, start: Modifiers = Modifiers()): Modifiers = {
+ @tailrec
def loop(mods: Modifiers): Modifiers = {
if (allowed contains in.token) {
val isAccessMod = accessModifierTokens contains in.token
@@ -2057,7 +2058,7 @@ object Parsers {
val name = ident().toTypeName
val constr = atPos(in.lastOffset) {
val tparams = typeParamClauseOpt(ParamOwner.Class)
- val cmods = constrModsOpt()
+ val cmods = constrModsOpt(name)
val vparamss = paramClauses(name, mods is Case)
makeConstructor(tparams, vparamss).withMods(cmods)
@@ -2070,11 +2071,11 @@ object Parsers {
/** ConstrMods ::= AccessModifier
* | Annotation {Annotation} (AccessModifier | `this')
*/
- def constrModsOpt(): Modifiers = {
+ def constrModsOpt(owner: Name): Modifiers = {
val mods = modifiers(accessModifierTokens, annotsAsMods())
if (mods.hasAnnotations && !mods.hasFlags)
if (in.token == THIS) in.nextToken()
- else syntaxError("`private', `protected', or `this' expected")
+ else syntaxError(AnnotatedPrimaryConstructorRequiresModifierOrThis(owner), mods.annotations.last.pos)
mods
}
diff --git a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala
index 86f34e64d..e20f846ac 100644
--- a/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala
+++ b/compiler/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala
@@ -6,6 +6,7 @@ import parsing.Tokens._
import scala.annotation.switch
import scala.collection.mutable.StringBuilder
import core.Contexts.Context
+import util.Chars.{ LF, FF, CR, SU }
import Highlighting.{Highlight, HighlightBuffer}
/** This object provides functions for syntax highlighting in the REPL */
@@ -26,7 +27,7 @@ object SyntaxHighlighting {
private def valDef(str: String) = ValDefColor + str + NoColor
private def operator(str: String) = TypeColor + str + NoColor
private def annotation(str: String) =
- if (str.trim == "@") str else AnnotationColor + str + NoColor
+ if (str.trim == "@") str else { AnnotationColor + str + NoColor }
private val tripleQs = Console.RED_B + "???" + NoColor
private val keywords: Seq[String] = for {
@@ -152,7 +153,11 @@ object SyntaxHighlighting {
var open = 1
while (open > 0 && remaining.nonEmpty) {
curr = takeChar()
- newBuf += curr
+ if (curr == '@') {
+ appendWhile('@', !typeEnders.contains(_), annotation)
+ newBuf append CommentColor
+ }
+ else newBuf += curr
if (curr == '*' && remaining.nonEmpty) {
curr = takeChar()
@@ -163,6 +168,11 @@ object SyntaxHighlighting {
newBuf += curr
if (curr == '*') open += 1
}
+
+ (curr: @switch) match {
+ case LF | FF | CR | SU => newBuf append CommentColor
+ case _ => ()
+ }
}
prev = curr
newBuf append NoColor
@@ -236,6 +246,11 @@ object SyntaxHighlighting {
newBuf += curr
closing = 0
}
+
+ (curr: @switch) match {
+ case LF | FF | CR | SU => newBuf append LiteralColor
+ case _ => ()
+ }
}
newBuf append NoColor
prev = curr
diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala
index 190445d60..17eb8d39b 100644
--- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala
+++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala
@@ -5,9 +5,12 @@ package reporting
import core.Contexts.Context
import core.Decorators._
import printing.Highlighting.{Blue, Red}
+import printing.SyntaxHighlighting
import diagnostic.{ErrorMessageID, Message, MessageContainer, NoExplanation}
import diagnostic.messages._
import util.SourcePosition
+import util.Chars.{ LF, CR, FF, SU }
+import scala.annotation.switch
import scala.collection.mutable
@@ -38,20 +41,37 @@ trait MessageRendering {
*/
def sourceLines(pos: SourcePosition)(implicit ctx: Context): (List[String], List[String], Int) = {
var maxLen = Int.MinValue
- def render(xs: List[Int]) =
- xs.map(pos.source.offsetToLine(_))
- .map { lineNbr =>
- val prefix = s"${lineNbr + 1} |"
- maxLen = math.max(maxLen, prefix.length)
- (prefix, pos.lineContent(lineNbr).stripLineEnd)
- }
- .map { case (prefix, line) =>
- val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix)
- hl"$lnum$line"
- }
+ def render(offsetAndLine: (Int, String)): String = {
+ val (offset, line) = offsetAndLine
+ val lineNbr = pos.source.offsetToLine(offset)
+ val prefix = s"${lineNbr + 1} |"
+ maxLen = math.max(maxLen, prefix.length)
+ val lnum = Red(" " * math.max(0, maxLen - prefix.length) + prefix).show
+ lnum + line.stripLineEnd
+ }
+
+ def linesFrom(arr: Array[Char]): List[String] = {
+ def pred(c: Char) = (c: @switch) match {
+ case LF | CR | FF | SU => true
+ case _ => false
+ }
+ val (line, rest0) = arr.span(!pred(_))
+ val (_, rest) = rest0.span(pred)
+ new String(line) :: { if (rest.isEmpty) Nil else linesFrom(rest) }
+ }
+ val syntax =
+ if (ctx.settings.color.value != "never")
+ SyntaxHighlighting(pos.linesSlice).toArray
+ else pos.linesSlice
+ val lines = linesFrom(syntax)
val (before, after) = pos.beforeAndAfterPoint
- (render(before), render(after), maxLen)
+
+ (
+ before.zip(lines).map(render),
+ after.zip(lines.drop(before.length)).map(render),
+ maxLen
+ )
}
/** The column markers aligned under the error */
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
index 2bf15cb7c..bbd93eb30 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java
@@ -51,6 +51,7 @@ public enum ErrorMessageID {
ExpectedTokenButFoundID,
MixedLeftAndRightAssociativeOpsID,
CantInstantiateAbstractClassOrTraitID,
+ AnnotatedPrimaryConstructorRequiresModifierOrThisID,
;
public int errorNumber() {
diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
index 34190c114..e367e9ab2 100644
--- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
+++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala
@@ -1146,4 +1146,18 @@ object messages {
|""".stripMargin
}
+ case class AnnotatedPrimaryConstructorRequiresModifierOrThis(cls: Name)(implicit ctx: Context)
+ extends Message(AnnotatedPrimaryConstructorRequiresModifierOrThisID) {
+ val kind = "Syntax"
+ val msg = hl"""${"private"}, ${"protected"}, or ${"this"} expected for annotated primary constructor"""
+ val explanation =
+ hl"""|When using annotations with a primary constructor of a class,
+ |the annotation must be followed by an access modifier
+ |(${"private"} or ${"protected"}) or ${"this"}.
+ |
+ |For example:
+ | ${"class Sample @deprecated this(param: Parameter) { ..."}
+ | ^^^^
+ |""".stripMargin
+ }
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala
index de017961a..222717e7e 100644
--- a/compiler/src/dotty/tools/dotc/typer/Applications.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala
@@ -450,7 +450,16 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
def typedArg(arg: Arg, formal: Type): Arg = arg
def addArg(arg: TypedArg, formal: Type) =
- ok = ok & isCompatible(argType(arg, formal), formal)
+ ok = ok & {
+ argType(arg, formal) match {
+ case ref: TermRef if ref.denot.isOverloaded =>
+ // in this case we could not resolve overloading because no alternative
+ // matches expected type
+ false
+ case argtpe =>
+ isCompatible(argtpe, formal)
+ }
+ }
def makeVarArg(n: Int, elemFormal: Type) = {}
def fail(msg: => Message, arg: Arg) =
ok = false
@@ -1375,7 +1384,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
else WildcardType)
val commonFormal = defn.FunctionOf(commonParamTypes, WildcardType)
overload.println(i"pretype arg $arg with expected type $commonFormal")
- pt.typedArg(arg, commonFormal)
+ pt.typedArg(arg, commonFormal)(ctx.addMode(Mode.ImplicitsEnabled))
}
}
}
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index 48f9243f7..1ca7eb107 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -327,7 +327,7 @@ object Checking {
if (!sym.is(Deferred))
fail(i"`@native' members may not have implementation")
}
- else if (sym.is(Deferred, butNot = Param) && !sym.isSelfSym) {
+ else if (sym.is(Deferred, butNot = Param) && !sym.isType && !sym.isSelfSym) {
if (!sym.owner.isClass || sym.owner.is(Module) || sym.owner.isAnonymousClass)
fail(i"only classes can have declared but undefined members$varNote")
checkWithDeferred(Private)
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index d5afae90c..759cc62e9 100644
--- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
@@ -496,6 +496,7 @@ trait Implicits { self: Typer =>
|| (to isRef defn.UnitClass)
|| (from.tpe isRef defn.NothingClass)
|| (from.tpe isRef defn.NullClass)
+ || !(ctx.mode is Mode.ImplicitsEnabled)
|| (from.tpe eq NoPrefix)) NoImplicitMatches
else
try inferImplicit(to.stripTypeVar.widenExpr, from, from.pos)
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index 33e320ce5..57e3c1b88 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -2023,7 +2023,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
// try an implicit conversion
inferView(tree, pt) match {
case SearchSuccess(inferred, _, _, _) =>
- adapt(inferred, pt)
+ adapt(inferred, pt)(ctx.retractMode(Mode.ImplicitsEnabled))
case failure: SearchFailure =>
if (pt.isInstanceOf[ProtoType] && !failure.isInstanceOf[AmbiguousImplicits]) tree
else err.typeMismatch(tree, pt, failure)
diff --git a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala
index aad4995d8..be5c46995 100644
--- a/compiler/src/dotty/tools/dotc/util/SourcePosition.scala
+++ b/compiler/src/dotty/tools/dotc/util/SourcePosition.scala
@@ -12,9 +12,14 @@ extends interfaces.SourcePosition {
def lineContent: String = source.lineContent(point)
def point: Int = pos.point
+
/** The line of the position, starting at 0 */
def line: Int = source.offsetToLine(point)
+ /** Extracts the lines from the underlying source file as `Array[Char]`*/
+ def linesSlice: Array[Char] =
+ source.content.slice(source.startOfLine(start), source.nextLine(end))
+
/** The lines of the position */
def lines: List[Int] =
List.range(source.offsetToLine(start), source.offsetToLine(end + 1)) match {
@@ -25,9 +30,6 @@ extends interfaces.SourcePosition {
def lineOffsets: List[Int] =
lines.map(source.lineToOffset(_))
- def lineContent(lineNumber: Int): String =
- source.lineContent(source.lineToOffset(lineNumber))
-
def beforeAndAfterPoint: (List[Int], List[Int]) =
lineOffsets.partition(_ <= point)
diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
index 971a40a1b..d6e687a1e 100644
--- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
+++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala
@@ -198,4 +198,18 @@ class ErrorMessagesTests extends ErrorMessagesTest {
assertTrue("expected trait", isTrait)
}
+ @Test def constructorModifier =
+ checkMessagesAfter("frontend") {
+ """
+ |class AnotherClass @deprecated ()
+ """.stripMargin
+ }
+ .expect { (ictx, messages) =>
+ implicit val ctx: Context = ictx
+ val defn = ictx.definitions
+
+ assertMessageCount(1, messages)
+ val AnnotatedPrimaryConstructorRequiresModifierOrThis(cls) :: Nil = messages
+ assertEquals("AnotherClass", cls.show)
+ }
}
diff --git a/doc-tool/resources/_layouts/api-page.html b/doc-tool/resources/_layouts/api-page.html
index 878ec8d8f..2d2f0265a 100644
--- a/doc-tool/resources/_layouts/api-page.html
+++ b/doc-tool/resources/_layouts/api-page.html
@@ -134,12 +134,25 @@ extraCSS:
{% endfor %}
{% endif %}
- {% if member.kind == "type" and member.alias != null %}
+ {% if member.kind == "type" %}
+ {% for tparam in member.typeParams %}
+ {% if forloop.first %}
+ <span class="no-left">[</span>
+ {% endif %}
+ {% if forloop.last %}
+ <span class="no-left">{{ tparam }}</span>
+ <span class="no-left">]</span>
+ {% else %}
+ <span class="no-left">{{ tparam }}, </span>
+ {% endif %}
+ {% endfor %}
+ {% if member.alias != null %}
<span class="type-alias">
<span class="equals"> = </span>
{% renderRef member.alias %}
</span>
{% endif %}
+ {% endif %}
{% if member.returnValue %}
<span class="no-left">: {% renderRef member.returnValue %}</span>
diff --git a/doc-tool/resources/css/dottydoc.css b/doc-tool/resources/css/dottydoc.css
index 7e7c501bf..0b833830c 100644
--- a/doc-tool/resources/css/dottydoc.css
+++ b/doc-tool/resources/css/dottydoc.css
@@ -328,3 +328,9 @@ pre > code.hljs {
padding: 10px;
background: transparent;
}
+
+blockquote {
+ padding: 0 1em;
+ color: #777;
+ border-left: 0.25em solid #ddd;
+}
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
index 7f44c5656..cfb66fa56 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
@@ -8,7 +8,7 @@ import dotc.CompilationUnit
import dotc.config.Printers.dottydoc
import dotc.core.Contexts.Context
import dotc.core.Comments.ContextDocstrings
-import dotc.core.Types.NoType
+import dotc.core.Types.{PolyType, NoType}
import dotc.core.Phases.Phase
import dotc.core.Symbols.{ Symbol, NoSymbol }
@@ -92,8 +92,16 @@ class DocASTPhase extends Phase {
val sym = t.symbol
if (sym.is(Flags.Synthetic | Flags.Param))
NonEntity
- else
- TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe))
+ else {
+ val tparams = t.rhs.tpe match {
+ case tp: PolyType => tp.paramRefs.zip(tp.variances).map { case (tp, variance) =>
+ val varianceSym = if (variance == 1) "+" else if (variance == -1) "-" else ""
+ varianceSym + tp.paramName.show
+ }
+ case _ => Nil
+ }
+ TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe), tparams)
+ }
/** trait */
case t @ TypeDef(n, rhs) if t.symbol.is(Flags.Trait) =>
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
index e4b9ae6b6..5174c0922 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/transform.scala
@@ -92,6 +92,7 @@ object transform {
t.name,
t.path,
t.alias,
+ t.typeParams,
t.comment,
t.parent
)
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
index 239656141..4a9bfce0c 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/JavaConverters.scala
@@ -189,6 +189,7 @@ object JavaConverters {
"name" -> ent.name,
"path" -> ent.path.asJava,
"alias" -> ent.alias.map(_.asJava).asJava,
+ "typeParams" -> ent.typeParams.asJava,
"comment" -> ent.comment.map(_.asJava).asJava,
"hasShortenedDocstring" -> ent.hasShortenedDocstring,
"isPrivate" -> ent.isPrivate,
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala
index b7a33a7ef..5ff28f914 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/comment/CommentParser.scala
@@ -6,6 +6,7 @@ import dotty.tools.dottydoc.util.syntax._
import dotty.tools.dotc.util.Positions._
import dotty.tools.dotc.core.Symbols._
import dotty.tools.dotc.core.Contexts.Context
+import dotty.tools.dotc.core.Decorators._
import scala.collection.mutable
import dotty.tools.dotc.config.Printers.dottydoc
import scala.util.matching.Regex
@@ -196,7 +197,7 @@ trait CommentParser extends util.MemberLookup {
)
for ((key, _) <- bodyTags) ctx.docbase.warn(
- s"Tag '@${key.name}' is not recognised",
+ hl"Tag '${"@" + key.name}' is not recognised",
// FIXME: here the position is stretched out over the entire comment,
// with the point being at the very end. This ensures that the entire
// comment will be visible in error reporting. A more fine-grained
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
index d35077816..d0f1a82c7 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/entities.scala
@@ -108,7 +108,7 @@ trait Package extends Entity with Members with SuperTypes {
val kind = "package"
}
-trait TypeAlias extends Entity with Modifiers {
+trait TypeAlias extends Entity with Modifiers with TypeParams {
val kind = "type"
def alias: Option[Reference]
def isAbstract: Boolean = !alias.isDefined
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
index 568b532b7..3e766a990 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/factories.scala
@@ -4,7 +4,8 @@ package model
import comment._
import references._
import dotty.tools.dotc
-import dotc.core.Types._
+import dotc.core.Types
+import Types._
import dotc.core.TypeApplications._
import dotc.core.Contexts.Context
import dotc.core.Symbols.{ Symbol, ClassSymbol }
@@ -105,17 +106,8 @@ object factories {
case ci: ClassInfo =>
typeRef(ci.cls.name.show, query = ci.typeSymbol.showFullName)
- case tl: PolyType => {
- // FIXME: should be handled correctly
- // example, in `Option`:
- //
- // ```scala
- // def companion: GenericCompanion[collection.Iterable]
- // ```
- //
- // Becomes: def companion: [+X0] -> collection.Iterable[X0]
- typeRef(tl.show + " (not handled)")
- }
+ case tl: PolyType =>
+ expandTpe(tl.resType)
case OrType(left, right) =>
OrTypeReference(expandTpe(left), expandTpe(right))
@@ -148,6 +140,8 @@ object factories {
prefix + tp.name.show.split("\\$").last
}
.toList
+ case tp: Types.TypeAlias =>
+ typeParams(tp.alias.typeSymbol)
case _ =>
Nil
}
diff --git a/doc-tool/src/dotty/tools/dottydoc/model/internal.scala b/doc-tool/src/dotty/tools/dottydoc/model/internal.scala
index bf50c0232..b50c93ee5 100644
--- a/doc-tool/src/dotty/tools/dottydoc/model/internal.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/model/internal.scala
@@ -31,6 +31,7 @@ object internal {
name: String,
path: List[String],
alias: Option[Reference],
+ typeParams: List[String] = Nil,
var comment: Option[Comment] = None,
var parent: Entity = NonEntity
) extends TypeAlias
diff --git a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala
index cd2ea587d..bc4a74c4f 100644
--- a/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/staticsite/tags.scala
@@ -180,6 +180,7 @@ object tags {
override def render(ctx: TemplateContext, nodes: LNode*): AnyRef =
(nodes(0).render(ctx), nodes(1).render(ctx)) match {
case (t: Title, parent: String) => renderTitle(t, parent)
+ case (t: Title, _) => renderTitle(t, "./") // file is in top dir
case _ => null
}
}
diff --git a/tests/neg/customArgs/typers.scala b/tests/neg/customArgs/typers.scala
index 49742ebbd..9432ab039 100644
--- a/tests/neg/customArgs/typers.scala
+++ b/tests/neg/customArgs/typers.scala
@@ -30,7 +30,7 @@ object typers {
}
type L[X] = scala.collection.immutable.List[X]
- type M[X, Y] <: scala.collection.immutable.Map[X, Y] // error: only classes can have declared but undefined members
+ type M[X, Y] <: scala.collection.immutable.Map[X, Y] // old-error: only classes can have declared but undefined members
object hk {
def f(x: L) // error: missing type parameter
diff --git a/tests/neg/i1050c.scala b/tests/neg/i1050c.scala
index 19570eb83..ecfaa3ea3 100644
--- a/tests/neg/i1050c.scala
+++ b/tests/neg/i1050c.scala
@@ -27,7 +27,8 @@ object Tiark4 {
v.brand("boom!")
}
object V { // error: cannot be instantiated
- type Y >: Any <: Nothing // error: only classes can have declared but undefined members
+ type Y >: Any <: Nothing // old-error: only classes can have declared but undefined members
+ type Z
}
object Tiark5 {
trait A { type L <: Nothing }
diff --git a/tests/neg/i2030.scala b/tests/neg/i2030.scala
new file mode 100644
index 000000000..2d049f4e6
--- /dev/null
+++ b/tests/neg/i2030.scala
@@ -0,0 +1,5 @@
+// This used to take ~12s, the check should be that
+// it runs in reasonable time (i.e. instantaneous).
+object a {
+ val x: String | Int = 'a // error
+}
diff --git a/tests/neg/i2033.scala b/tests/neg/i2033.scala
new file mode 100644
index 000000000..b28a0d99e
--- /dev/null
+++ b/tests/neg/i2033.scala
@@ -0,0 +1,21 @@
+import java.io._
+import collection._
+object Test {
+ def check(obj: AnyRef): Unit = {
+ val bos = new ByteArrayOutputStream()
+ val out = new ObjectOutputStream(println) // error
+ val arr = bos toByteArray ()
+ val in = (())
+ val deser = ()
+ val lhs = mutable LinkedHashSet ()
+ check(lhs)
+ }
+}
+
+// minimization
+object Test2 {
+ class ObjectOutputStream(out: String) {
+ def this() = this("")
+ }
+ val out = new ObjectOutputStream(println) // error
+}
diff --git a/tests/run/builder.check b/tests/run/builder.check
index 48f7d9253..04048dfcc 100644
--- a/tests/run/builder.check
+++ b/tests/run/builder.check
@@ -1 +1 @@
-Table(Row(Cell(A1), Cell(B1)), Row(Cell(A2), Cell(B2)))
+Table(Row(Cell(top left), Cell(top right)), Row(Cell(botttom left), Cell(bottom right)))
diff --git a/tests/run/builder.scala b/tests/run/builder.scala
index 532a95071..d09e9f2c8 100644
--- a/tests/run/builder.scala
+++ b/tests/run/builder.scala
@@ -12,9 +12,7 @@ class Row {
override def toString = cells.mkString("Row(", ", ", ")")
}
-class Cell(elem: String) {
- override def toString = s"Cell($elem)"
-}
+case class Cell(elem: String)
object Test {
@@ -36,12 +34,12 @@ object Test {
val data =
table {
row {
- cell("A1")
- cell("B1")
+ cell("top left")
+ cell("top right")
}
row {
- cell("A2")
- cell("B2")
+ cell("botttom left")
+ cell("bottom right")
}
}
diff --git a/tests/run/hmap.scala b/tests/run/hmap.scala
new file mode 100644
index 000000000..d84419ce1
--- /dev/null
+++ b/tests/run/hmap.scala
@@ -0,0 +1,97 @@
+trait Tuple
+case class TCons[H, T <: Tuple](h: H, t: T) extends Tuple
+final case object TNil extends Tuple
+
+// Type level natural numbers -------------------------------------------------
+
+sealed trait Nat
+sealed trait Succ[P <: Nat] extends Nat
+sealed trait Zero extends Nat
+
+// Accessor type class to compute the N'th element of an Tuple L --------------
+
+trait At[L <: Tuple, N <: Nat, Out] {
+ def apply(l: L): Out
+}
+
+object At {
+ implicit def caseZero[H, T <: Tuple]: At[H TCons T, Zero, H] =
+ new At[H TCons T, Zero, H] {
+ def apply(l: H TCons T): H = {
+ val (h TCons _) = l
+ h
+ }
+ }
+
+ implicit def caseN[H, T <: Tuple, N <: Nat, O]
+ (implicit a: At[T, N, O]): At[H TCons T, Succ[N], O] =
+ new At[H TCons T, Succ[N], O] {
+ def apply(l: H TCons T): O = {
+ val (_ TCons t) = l
+ a(t)
+ }
+ }
+}
+
+// An HMap is an Tuple with HEntry elements. We are reusing Tuple for it's nice syntax
+
+final case class HEntry[K, V](value: V)
+
+// Accessor type class to compute the element of type K in a HMap L -----------
+
+trait PhantomGet[K, M <: Tuple, I <: Nat] // extends PhantomAny
+
+object PhantomGet {
+ implicit def getHead[K, V, T <: Tuple]
+ : PhantomGet[K, HEntry[K, V] TCons T, Zero] = null
+
+ implicit def getTail[K, H, T <: Tuple, I <: Nat]
+ (implicit t: PhantomGet[K, T, I])
+ : PhantomGet[K, H TCons T, Succ[I]] = null
+}
+
+// Syntax ---------------------------------------------------------------------
+
+object syntax {
+ object hmap {
+ implicit class HmapGet[M <: Tuple](m: M) {
+ def get[K, V, I <: Nat](k: K)
+ (implicit
+ g: PhantomGet[k.type, M, I],
+ a: At[M, I, HEntry[k.type, V]]
+ ): V = a(m).value
+ }
+
+ def --[K, V](key: K, value: V) = HEntry[key.type, V](value)
+ }
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ import syntax.hmap._
+
+ val map1 =
+ TCons(HEntry[K = "name"]("foo"),
+ TCons(HEntry[K = "genre"](true),
+ TCons(HEntry[K = "moneyz"](123),
+ TCons(HEntry[K = "cat"]("bar"),
+ (TNil: TNil.type)))))
+
+ assert(map1.get("name") == "foo")
+ assert(map1.get("genre") == true)
+ assert(map1.get("moneyz") == 123)
+ assert(map1.get("cat") == "bar")
+
+ val map2 =
+ TCons(--("name" , "foo"),
+ TCons(--("genre" , true),
+ TCons(--("moneyz", 123),
+ TCons(--("cat" , "bar"),
+ TNil))))
+
+ assert(map2.get("name") == "foo")
+ assert(map2.get("genre") == true)
+ assert(map2.get("moneyz") == 123)
+ assert(map2.get("cat") == "bar")
+ }
+}