diff options
22 files changed, 190 insertions, 89 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index bf11a442e..27be8c9d6 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -1077,6 +1077,13 @@ object Trees { /** Hook to indicate that a transform of some subtree should be skipped */ protected def skipTransform(tree: Tree)(implicit ctx: Context): Boolean = false + /** For untyped trees, this is just the identity. + * For typed trees, a context derived form `ctx` that records `call` as the + * innermost enclosing call for which the inlined version is currently + * processed. + */ + protected def inlineContext(call: Tree)(implicit ctx: Context): Context = ctx + abstract class TreeMap(val cpy: TreeCopier = inst.cpy) { def transform(tree: Tree)(implicit ctx: Context): Tree = @@ -1121,7 +1128,7 @@ object Trees { case SeqLiteral(elems, elemtpt) => cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt)) case Inlined(call, bindings, expansion) => - cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)) + cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion)(inlineContext(call))) case TypeTree() => tree case SingletonTypeTree(ref) => @@ -1225,7 +1232,7 @@ object Trees { case SeqLiteral(elems, elemtpt) => this(this(x, elems), elemtpt) case Inlined(call, bindings, expansion) => - this(this(x, bindings), expansion) + this(this(x, bindings), expansion)(inlineContext(call)) case TypeTree() => x case SingletonTypeTree(ref) => diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala index ed268fda7..d1d886c55 100644 --- a/compiler/src/dotty/tools/dotc/ast/tpd.scala +++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala @@ -933,10 +933,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** A key to be used in a context property that tracks enclosing inlined calls */ private val InlinedCalls = new Property.Key[List[Tree]] - /** A context derived form `ctx` that records `call` as innermost enclosing - * call for which the inlined version is currently processed. - */ - def inlineContext(call: Tree)(implicit ctx: Context): Context = + override def inlineContext(call: Tree)(implicit ctx: Context): Context = ctx.fresh.setProperty(InlinedCalls, call :: enclosingInlineds) /** All enclosing calls that are currently inlined, from innermost to outermost */ diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala index 24d583b19..190445d60 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -5,7 +5,7 @@ package reporting import core.Contexts.Context import core.Decorators._ import printing.Highlighting.{Blue, Red} -import diagnostic.{Message, MessageContainer, NoExplanation} +import diagnostic.{ErrorMessageID, Message, MessageContainer, NoExplanation} import diagnostic.messages._ import util.SourcePosition @@ -95,9 +95,10 @@ trait MessageRendering { if (pos.exists) Blue({ val file = pos.source.file.toString val errId = - if (message.errorId != NoExplanation.ID) - s"[E${"0" * (3 - message.errorId.toString.length) + message.errorId}] " - else "" + if (message.errorId ne ErrorMessageID.NoExplanationID) { + val errorNumber = message.errorId.errorNumber() + s"[E${"0" * (3 - errorNumber.toString.length) + errorNumber}] " + } else "" val kind = if (message.kind == "") diagnosticLevel else s"${message.kind} $diagnosticLevel" diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java new file mode 100644 index 000000000..43930a56e --- /dev/null +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/ErrorMessageID.java @@ -0,0 +1,57 @@ +package dotty.tools.dotc.reporting.diagnostic; + +/** Unique IDs identifying the messages */ +public enum ErrorMessageID { + + // IMPORTANT: Add new IDs only at the end and never remove IDs + + LazyErrorId, // // errorNumber: -2 + NoExplanationID, // errorNumber: -1 + + EmptyCatchOrFinallyBlockID, // errorNumber: 0 + EmptyCatchBlockID, // errorNumber: 1 + EmptyCatchAndFinallyBlockID, // errorNumber: 2 + DeprecatedWithOperatorID, + CaseClassMissingParamListID, + DuplicateBindID, + MissingIdentID, + TypeMismatchID, + NotAMemberID, + EarlyDefinitionsNotSupportedID, + TopLevelImplicitClassID, + ImplicitCaseClassID, + ObjectMayNotHaveSelfTypeID, + TupleTooLongID, + RepeatedModifierID, + InterpolatedStringErrorID, + UnboundPlaceholderParameterID, + IllegalStartSimpleExprID, + MissingReturnTypeID, + YieldOrDoExpectedInForComprehensionID, + ProperDefinitionNotFoundID, + ByNameParameterNotSupportedID, + WrongNumberOfTypeArgsID, + IllegalVariableInPatternAlternativeID, + TypeParamsTypeExpectedID, + IdentifierExpectedID, + AuxConstructorNeedsNonImplicitParameterID, + IncorrectRepeatedParameterSyntaxID, + IllegalLiteralID, + PatternMatchExhaustivityID, + MatchCaseUnreachableID, + SeqWildcardPatternPosID, + IllegalStartOfSimplePatternID, + PkgDuplicateSymbolID, + ExistentialTypesNoLongerSupportedID, + UnboundWildcardTypeID, + DanglingThisInPathID, + OverridesNothingID, + OverridesNothingButNameExistsID, + ForwardReferenceExtendsOverDefinitionID, + ExpectedTokenButFoundID; + + public int errorNumber() { + return ordinal() - 2; + } + +} diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala index ab1222dab..09d7ae975 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/Message.scala @@ -30,11 +30,10 @@ object Message { * Instead use the `persist` method to create an instance that does not keep a * reference to these contexts. * - * @param errorId a unique number identifying the message, this will later be + * @param errorId a unique id identifying the message, this will later be * used to reference documentation online */ -abstract class Message(val errorId: Int) { self => - import messages._ +abstract class Message(val errorId: ErrorMessageID) { self => /** The `msg` contains the diagnostic message e.g: * @@ -116,7 +115,7 @@ class ExtendMessage(_msg: () => Message)(f: String => String) { self => } /** The fallback `Message` containing no explanation and having no `kind` */ -class NoExplanation(val msg: String) extends Message(NoExplanation.ID) { +class NoExplanation(val msg: String) extends Message(ErrorMessageID.NoExplanationID) { val explanation = "" val kind = "" @@ -127,8 +126,6 @@ class NoExplanation(val msg: String) extends Message(NoExplanation.ID) { * lacks an explanation */ object NoExplanation { - final val ID = -1 - def unapply(m: Message): Option[Message] = if (m.explanation == "") Some(m) else None diff --git a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala index 94611e10d..3ca780419 100644 --- a/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala @@ -17,6 +17,7 @@ import dotc.parsing.Scanners.Token import dotc.parsing.Tokens import printing.Highlighting._ import printing.Formatting +import ErrorMessageID._ object messages { @@ -94,8 +95,8 @@ object messages { // Syntax Errors ---------------------------------------------------------- // - abstract class EmptyCatchOrFinallyBlock(tryBody: untpd.Tree, errNo: Int)(implicit ctx: Context) - extends Message(errNo) { + abstract class EmptyCatchOrFinallyBlock(tryBody: untpd.Tree, errNo: ErrorMessageID)(implicit ctx: Context) + extends Message(EmptyCatchOrFinallyBlockID) { val explanation = { val tryString = tryBody match { case Block(Nil, untpd.EmptyTree) => "{}" @@ -131,7 +132,7 @@ object messages { } case class EmptyCatchBlock(tryBody: untpd.Tree)(implicit ctx: Context) - extends EmptyCatchOrFinallyBlock(tryBody, 1) { + extends EmptyCatchOrFinallyBlock(tryBody, EmptyCatchBlockID) { val kind = "Syntax" val msg = hl"""|The ${"catch"} block does not contain a valid expression, try @@ -139,7 +140,7 @@ object messages { } case class EmptyCatchAndFinallyBlock(tryBody: untpd.Tree)(implicit ctx: Context) - extends EmptyCatchOrFinallyBlock(tryBody, 2) { + extends EmptyCatchOrFinallyBlock(tryBody, EmptyCatchAndFinallyBlockID) { val kind = "Syntax" val msg = hl"""|A ${"try"} without ${"catch"} or ${"finally"} is equivalent to putting @@ -147,7 +148,7 @@ object messages { } case class DeprecatedWithOperator()(implicit ctx: Context) - extends Message(3) { + extends Message(DeprecatedWithOperatorID) { val kind = "Syntax" val msg = hl"""${"with"} as a type operator has been deprecated; use `&' instead""" @@ -158,7 +159,7 @@ object messages { } case class CaseClassMissingParamList(cdef: untpd.TypeDef)(implicit ctx: Context) - extends Message(4) { + extends Message(CaseClassMissingParamListID) { val kind = "Syntax" val msg = hl"""|A ${"case class"} must have at least one parameter list""" @@ -172,7 +173,7 @@ object messages { // Type Errors ------------------------------------------------------------ // case class DuplicateBind(bind: untpd.Bind, tree: untpd.CaseDef)(implicit ctx: Context) - extends Message(5) { + extends Message(DuplicateBindID) { val kind = "Naming" val msg = em"duplicate pattern variable: `${bind.name}`" @@ -199,7 +200,7 @@ object messages { } case class MissingIdent(tree: untpd.Ident, treeKind: String, name: String)(implicit ctx: Context) - extends Message(6) { + extends Message(MissingIdentID) { val kind = "Unbound Identifier" val msg = em"not found: $treeKind$name" @@ -212,7 +213,7 @@ object messages { } case class TypeMismatch(found: Type, expected: Type, whyNoMatch: String = "", implicitFailure: String = "")(implicit ctx: Context) - extends Message(7) { + extends Message(TypeMismatchID) { val kind = "Type Mismatch" val msg = { val (where, printCtx) = Formatting.disambiguateTypes(found, expected) @@ -227,7 +228,7 @@ object messages { } case class NotAMember(site: Type, name: Name, selected: String)(implicit ctx: Context) - extends Message(8) { + extends Message(NotAMemberID) { val kind = "Member Not Found" //println(i"site = $site, decls = ${site.decls}, source = ${site.widen.typeSymbol.sourceFile}") //DEBUG @@ -293,7 +294,7 @@ object messages { } case class EarlyDefinitionsNotSupported()(implicit ctx: Context) - extends Message(9) { + extends Message(EarlyDefinitionsNotSupportedID) { val kind = "Syntax" val msg = "early definitions are not supported; use trait parameters instead" @@ -339,7 +340,7 @@ object messages { } case class TopLevelImplicitClass(cdef: untpd.TypeDef)(implicit ctx: Context) - extends Message(10) { + extends Message(TopLevelImplicitClassID) { val kind = "Syntax" val msg = hl"""An ${"implicit class"} may not be top-level""" @@ -369,7 +370,7 @@ object messages { } case class ImplicitCaseClass(cdef: untpd.TypeDef)(implicit ctx: Context) - extends Message(11) { + extends Message(ImplicitCaseClassID) { val kind = "Syntax" val msg = hl"""A ${"case class"} may not be defined as ${"implicit"}""" @@ -382,7 +383,7 @@ object messages { } case class ObjectMayNotHaveSelfType(mdef: untpd.ModuleDef)(implicit ctx: Context) - extends Message(12) { + extends Message(ObjectMayNotHaveSelfTypeID) { val kind = "Syntax" val msg = hl"""${"object"}s must not have a self ${"type"}""" @@ -400,7 +401,7 @@ object messages { } case class TupleTooLong(ts: List[untpd.Tree])(implicit ctx: Context) - extends Message(13) { + extends Message(TupleTooLongID) { import Definitions.MaxTupleArity val kind = "Syntax" val msg = hl"""A ${"tuple"} cannot have more than ${MaxTupleArity} members""" @@ -416,7 +417,7 @@ object messages { } case class RepeatedModifier(modifier: String)(implicit ctx:Context) - extends Message(14) { + extends Message(RepeatedModifierID) { val kind = "Syntax" val msg = hl"""repeated modifier $modifier""" @@ -438,7 +439,7 @@ object messages { } case class InterpolatedStringError()(implicit ctx:Context) - extends Message(15) { + extends Message(InterpolatedStringErrorID) { val kind = "Syntax" val msg = "error in interpolated string: identifier or block expected" val explanation = { @@ -456,7 +457,7 @@ object messages { } case class UnboundPlaceholderParameter()(implicit ctx:Context) - extends Message(16) { + extends Message(UnboundPlaceholderParameterID) { val kind = "Syntax" val msg = "unbound placeholder parameter; incorrect use of `_`" val explanation = @@ -489,7 +490,7 @@ object messages { } case class IllegalStartSimpleExpr(illegalToken: String)(implicit ctx: Context) - extends Message(17) { + extends Message(IllegalStartSimpleExprID) { val kind = "Syntax" val msg = "illegal start of simple expression" val explanation = { @@ -507,7 +508,8 @@ object messages { } } - case class MissingReturnType()(implicit ctx:Context) extends Message(18) { + case class MissingReturnType()(implicit ctx:Context) + extends Message(MissingReturnTypeID) { val kind = "Syntax" val msg = "missing return type" val explanation = @@ -519,7 +521,7 @@ object messages { } case class YieldOrDoExpectedInForComprehension()(implicit ctx: Context) - extends Message(19) { + extends Message(YieldOrDoExpectedInForComprehensionID) { val kind = "Syntax" val msg = hl"${"yield"} or ${"do"} expected" @@ -552,7 +554,7 @@ object messages { } case class ProperDefinitionNotFound()(implicit ctx: Context) - extends Message(20) { + extends Message(ProperDefinitionNotFoundID) { val kind = "Definition Not Found" val msg = hl"""Proper definition was not found in ${"@usecase"}""" @@ -591,7 +593,7 @@ object messages { } case class ByNameParameterNotSupported()(implicit ctx: Context) - extends Message(21) { + extends Message(ByNameParameterNotSupportedID) { val kind = "Syntax" val msg = "By-name parameter type not allowed here." @@ -615,7 +617,7 @@ object messages { } case class WrongNumberOfTypeArgs(fntpe: Type, expectedArgs: List[TypeParamInfo], actual: List[untpd.Tree])(implicit ctx: Context) - extends Message(22) { + extends Message(WrongNumberOfTypeArgsID) { val kind = "Syntax" private val expectedCount = expectedArgs.length @@ -661,7 +663,7 @@ object messages { } case class IllegalVariableInPatternAlternative()(implicit ctx: Context) - extends Message(23) { + extends Message(IllegalVariableInPatternAlternativeID) { val kind = "Syntax" val msg = "Variables are not allowed in alternative patterns" val explanation = { @@ -690,7 +692,7 @@ object messages { } case class TypeParamsTypeExpected(mods: untpd.Modifiers, identifier: TermName)(implicit ctx: Context) - extends Message(24) { + extends Message(TypeParamsTypeExpectedID) { val kind = "Syntax" val msg = hl"""Expected ${"type"} keyword for type parameter $identifier""" val explanation = @@ -703,7 +705,7 @@ object messages { } case class IdentifierExpected(identifier: String)(implicit ctx: Context) - extends Message(25) { + extends Message(IdentifierExpectedID) { val kind = "Syntax" val msg = "identifier expected" val explanation = { @@ -724,7 +726,7 @@ object messages { } case class AuxConstructorNeedsNonImplicitParameter()(implicit ctx:Context) - extends Message(26) { + extends Message(AuxConstructorNeedsNonImplicitParameterID) { val kind = "Syntax" val msg = "auxiliary constructor needs non-implicit parameter list" val explanation = @@ -739,7 +741,8 @@ object messages { |""" } - case class IncorrectRepeatedParameterSyntax()(implicit ctx: Context) extends Message(27) { + case class IncorrectRepeatedParameterSyntax()(implicit ctx: Context) + extends Message(IncorrectRepeatedParameterSyntaxID) { val kind = "Syntax" val msg = "'*' expected" val explanation = @@ -765,7 +768,8 @@ object messages { |""".stripMargin } - case class IllegalLiteral()(implicit ctx: Context) extends Message(28) { + case class IllegalLiteral()(implicit ctx: Context) + extends Message(IllegalLiteralID) { val kind = "Syntax" val msg = "illegal literal" val explanation = @@ -780,7 +784,7 @@ object messages { } case class PatternMatchExhaustivity(uncovered: String)(implicit ctx: Context) - extends Message(29) { + extends Message(PatternMatchExhaustivityID) { val kind = "Pattern Match Exhaustivity" val msg = hl"""|match may not be exhaustive. @@ -792,14 +796,14 @@ object messages { } case class MatchCaseUnreachable()(implicit ctx: Context) - extends Message(30) { + extends Message(MatchCaseUnreachableID) { val kind = s"""Match ${hl"case"} Unreachable""" val msg = "unreachable code" val explanation = "" } case class SeqWildcardPatternPos()(implicit ctx: Context) - extends Message(31) { + extends Message(SeqWildcardPatternPosID) { val kind = "Syntax" val msg = "`_*' can be used only for last argument" val explanation = { @@ -822,7 +826,8 @@ object messages { } } - case class IllegalStartOfSimplePattern()(implicit ctx: Context) extends Message(32) { + case class IllegalStartOfSimplePattern()(implicit ctx: Context) + extends Message(IllegalStartOfSimplePatternID) { val kind = "Syntax" val msg = "illegal start of simple pattern" val explanation = { @@ -902,13 +907,14 @@ object messages { } case class PkgDuplicateSymbol(existing: Symbol)(implicit ctx: Context) - extends Message(33) { + extends Message(PkgDuplicateSymbolID) { val kind = "Duplicate Symbol" val msg = hl"trying to define package with same name as `$existing`" val explanation = "" } - case class ExistentialTypesNoLongerSupported()(implicit ctx: Context) extends Message(34) { + case class ExistentialTypesNoLongerSupported()(implicit ctx: Context) + extends Message(ExistentialTypesNoLongerSupportedID) { val kind = "Syntax" val msg = hl"""|Existential types are no longer supported - @@ -930,7 +936,8 @@ object messages { |""" } - case class UnboundWildcardType()(implicit ctx: Context) extends Message(35) { + case class UnboundWildcardType()(implicit ctx: Context) + extends Message(UnboundWildcardTypeID) { val kind = "Syntax" val msg = "Unbound wildcard type" val explanation = @@ -974,7 +981,7 @@ object messages { |""" } - case class DanglingThisInPath()(implicit ctx: Context) extends Message(36) { + case class DanglingThisInPath()(implicit ctx: Context) extends Message(DanglingThisInPathID) { val kind = "Syntax" val msg = hl"""Expected an additional member selection after the keyword ${"this"}""" @@ -1011,7 +1018,7 @@ object messages { } case class OverridesNothing(member: Symbol)(implicit ctx: Context) - extends Message(37) { + extends Message(OverridesNothingID) { val kind = "Reference" val msg = hl"""${member} overrides nothing""" @@ -1023,7 +1030,7 @@ object messages { } case class OverridesNothingButNameExists(member: Symbol, existing: List[Denotations.SingleDenotation])(implicit ctx: Context) - extends Message(38) { + extends Message(OverridesNothingButNameExistsID) { val kind = "Reference" val msg = hl"""${member} has a different signature than the overridden declaration""" @@ -1042,7 +1049,7 @@ object messages { } case class ForwardReferenceExtendsOverDefinition(value: Symbol, definition: Symbol)(implicit ctx: Context) - extends Message(39) { + extends Message(ForwardReferenceExtendsOverDefinitionID) { val kind = "Reference" val msg = hl"`${definition.name}` is a forward reference extending over the definition of `${value.name}`" @@ -1061,7 +1068,7 @@ object messages { } case class ExpectedTokenButFound(expected: Token, found: Token, foundName: TermName)(implicit ctx: Context) - extends Message(40) { + extends Message(ExpectedTokenButFoundID) { val kind = "Syntax" private val expectedText = diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 42c24ffb7..0ed6ed6b4 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -916,7 +916,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => val result = assignType(cpy.UnApply(tree)(unapplyFn, unapplyImplicits, unapplyPatterns), ownType) unapp.println(s"unapply patterns = $unapplyPatterns") if ((ownType eq selType) || ownType.isError) result - else Typed(result, TypeTree(ownType)) + else tryWithClassTag(Typed(result, TypeTree(ownType)), selType) case tp => val unapplyErr = if (tp.isError) unapplyFn else notAnExtractor(unapplyFn) val typedArgsErr = args mapconserve (typed(_, defn.AnyType)) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 27b0f28ca..fb0497c2b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -356,8 +356,7 @@ object Checking { */ def checkNoPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type = { class NotPrivate extends TypeMap { - type Errors = List[(String, Position)] - var errors: Errors = Nil + var errors: List[String] = Nil def accessBoundary(sym: Symbol): Symbol = if (sym.is(Private) || !sym.owner.isClass) sym.owner @@ -383,8 +382,8 @@ object Checking { val prevErrors = errors var tp1 = if (isLeaked(tp.symbol)) { - errors = (em"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}", - sym.pos) :: errors + errors = + em"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}" :: errors tp } else mapOver(tp) @@ -408,7 +407,7 @@ object Checking { } val notPrivate = new NotPrivate val info = notPrivate(sym.info) - notPrivate.errors.foreach { case (msg, pos) => ctx.errorOrMigrationWarning(msg, pos) } + notPrivate.errors.foreach(ctx.errorOrMigrationWarning(_, pos)) info } diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 2b57cf778..498fd001b 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -523,18 +523,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def handlePattern: Tree = { val tpt1 = typedTpt // special case for an abstract type that comes with a class tag - tpt1.tpe.dealias match { - case tref: TypeRef if !tref.symbol.isClass && !ctx.isAfterTyper => - inferImplicit(defn.ClassTagType.appliedTo(tref), - EmptyTree, tpt1.pos)(ctx.retractMode(Mode.Pattern)) match { - case SearchSuccess(arg, _, _, _) => - return typed(untpd.Apply(untpd.TypedSplice(arg), tree.expr), pt) - case _ => - } - case _ => - if (!ctx.isAfterTyper) tpt1.tpe.<:<(pt)(ctx.addMode(Mode.GADTflexible)) - } - ascription(tpt1, isWildcard = true) + if (!ctx.isAfterTyper) tpt1.tpe.<:<(pt)(ctx.addMode(Mode.GADTflexible)) + tryWithClassTag(ascription(tpt1, isWildcard = true), pt) } cases( ifPat = handlePattern, @@ -543,6 +533,23 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } } + /** For a typed tree `e: T`, if `T` is an abstract type for which an implicit class tag `ctag` + * exists, rewrite to `ctag(e)`. + * @pre We are in pattern-matching mode (Mode.Pattern) + */ + def tryWithClassTag(tree: Typed, pt: Type)(implicit ctx: Context) = tree.tpt.tpe.dealias match { + case tref: TypeRef if !tref.symbol.isClass && !ctx.isAfterTyper => + require(ctx.mode.is(Mode.Pattern)) + inferImplicit(defn.ClassTagType.appliedTo(tref), + EmptyTree, tree.tpt.pos)(ctx.retractMode(Mode.Pattern)) match { + case SearchSuccess(clsTag, _, _, _) => + typed(untpd.Apply(untpd.TypedSplice(clsTag), untpd.TypedSplice(tree.expr)), pt) + case _ => + tree + } + case _ => tree + } + def typedNamedArg(tree: untpd.NamedArg, pt: Type)(implicit ctx: Context) = track("typedNamedArg") { val arg1 = typed(tree.arg, pt) assignType(cpy.NamedArg(tree)(tree.name, arg1), arg1) @@ -1121,15 +1128,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit def typedBind(tree: untpd.Bind, pt: Type)(implicit ctx: Context): Tree = track("typedBind") { val pt1 = fullyDefinedType(pt, "pattern variable", tree.pos) val body1 = typed(tree.body, pt1) - typr.println(i"typed bind $tree pt = $pt1 bodytpe = ${body1.tpe}") body1 match { - case UnApply(fn, Nil, arg :: Nil) if tree.body.isInstanceOf[untpd.Typed] => - // A typed pattern `x @ (_: T)` with an implicit `ctag: ClassTag[T]` - // was rewritten to `x @ ctag(_)`. - // Rewrite further to `ctag(x @ _)` - assert(fn.symbol.owner == defn.ClassTagClass) + case UnApply(fn, Nil, arg :: Nil) if fn.symbol.owner == defn.ClassTagClass && !body1.tpe.isError => + // A typed pattern `x @ (e: T)` with an implicit `ctag: ClassTag[T]` + // was rewritten to `x @ ctag(e)` by `tryWithClassTag`. + // Rewrite further to `ctag(x @ e)` tpd.cpy.UnApply(body1)(fn, Nil, - typed(untpd.Bind(tree.name, arg).withPos(tree.pos), arg.tpe) :: Nil) + typed(untpd.Bind(tree.name, untpd.TypedSplice(arg)).withPos(tree.pos), arg.tpe) :: Nil) case _ => val sym = newPatternBoundSym(tree.name, body1.tpe, tree.pos) assignType(cpy.Bind(tree)(tree.name, body1), sym) diff --git a/compiler/test/dotc/tests.scala b/compiler/test/dotc/tests.scala index fcd2d0982..7af903364 100644 --- a/compiler/test/dotc/tests.scala +++ b/compiler/test/dotc/tests.scala @@ -160,7 +160,6 @@ class tests extends CompilerTest { @Test def rewrites = compileFile(posScala2Dir, "rewrites", "-rewrite" :: scala2mode) - @Test def pos_859 = compileFile(posSpecialDir, "i859", scala2mode)(allowDeepSubtypes) @Test def pos_t8146a = compileFile(posSpecialDir, "t8146a")(allowDeepSubtypes) @Test def pos_t5545 = { diff --git a/compiler/test/dotty/tools/dotc/reporting/TestMessageLaziness.scala b/compiler/test/dotty/tools/dotc/reporting/TestMessageLaziness.scala index bf727d51a..858660075 100644 --- a/compiler/test/dotty/tools/dotc/reporting/TestMessageLaziness.scala +++ b/compiler/test/dotty/tools/dotc/reporting/TestMessageLaziness.scala @@ -4,10 +4,8 @@ package reporting import org.junit.Assert._ import org.junit.Test - import core.Contexts._ - -import diagnostic.{ Message, MessageContainer, ExtendMessage } +import diagnostic.{ErrorMessageID, ExtendMessage, Message, MessageContainer} class TestMessageLaziness extends DottyTest { ctx = ctx.fresh.setReporter(new NonchalantReporter) @@ -19,7 +17,7 @@ class TestMessageLaziness extends DottyTest { override def report(m: MessageContainer)(implicit ctx: Context) = () } - case class LazyError() extends Message(1000) { + case class LazyError() extends Message(ErrorMessageID.LazyErrorId) { throw new Error("Didn't stay lazy.") val kind = "Test" diff --git a/project/Build.scala b/project/Build.scala index cb00b5159..f03111f76 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -105,7 +105,12 @@ object DottyBuild extends Build { (dottyOrganization % "dotty-sbt-bridge" % scalaVersion.value % "component").sources(), // sbt gets very unhappy if two projects use the same target - target := baseDirectory.value / ".." / "out" / name.value + target := baseDirectory.value / ".." / "out" / name.value, + + // The non-bootstrapped dotty-library is not necessary when bootstrapping dotty + autoScalaLibrary := false, + // ...but scala-library is + libraryDependencies += "org.scala-lang" % "scala-library" % scalacVersion ) /** Projects -------------------------------------------------------------- */ diff --git a/tests/neg/selfreq.scala b/tests/disabled/scalac-dependent/neg/selfreq.scala index 1ca373b4b..1ca373b4b 100644 --- a/tests/neg/selfreq.scala +++ b/tests/disabled/scalac-dependent/neg/selfreq.scala diff --git a/tests/pos-special/i859.scala b/tests/disabled/scalac-dependent/pos-special/i859.scala index a9f6b51c9..a9f6b51c9 100644 --- a/tests/pos-special/i859.scala +++ b/tests/disabled/scalac-dependent/pos-special/i859.scala diff --git a/tests/pos/t5604/ReplConfig.scala b/tests/disabled/scalac-dependent/pos/t5604/ReplConfig.scala index 8c589eba6..8c589eba6 100644 --- a/tests/pos/t5604/ReplConfig.scala +++ b/tests/disabled/scalac-dependent/pos/t5604/ReplConfig.scala diff --git a/tests/pos/t5604/ReplReporter.scala b/tests/disabled/scalac-dependent/pos/t5604/ReplReporter.scala index 9423efd8a..9423efd8a 100644 --- a/tests/pos/t5604/ReplReporter.scala +++ b/tests/disabled/scalac-dependent/pos/t5604/ReplReporter.scala diff --git a/tests/pos/t5899.scala b/tests/disabled/scalac-dependent/pos/t5899.scala index 852b4e3e7..852b4e3e7 100644 --- a/tests/pos/t5899.scala +++ b/tests/disabled/scalac-dependent/pos/t5899.scala diff --git a/tests/pos/t7591.scala b/tests/disabled/scalac-dependent/pos/t7591.scala index dd127b881..dd127b881 100644 --- a/tests/pos/t7591.scala +++ b/tests/disabled/scalac-dependent/pos/t7591.scala diff --git a/tests/pos/trait-force-info.scala b/tests/disabled/scalac-dependent/pos/trait-force-info.scala index c2b33869c..c2b33869c 100644 --- a/tests/pos/trait-force-info.scala +++ b/tests/disabled/scalac-dependent/pos/trait-force-info.scala diff --git a/tests/run/t1618.scala b/tests/disabled/scalac-dependent/run/t1618.scala index 248af9b4f..248af9b4f 100644 --- a/tests/run/t1618.scala +++ b/tests/disabled/scalac-dependent/run/t1618.scala diff --git a/tests/run/t7775.scala b/tests/disabled/scalac-dependent/run/t7775.scala index bc6a67d0e..bc6a67d0e 100644 --- a/tests/run/t7775.scala +++ b/tests/disabled/scalac-dependent/run/t7775.scala diff --git a/tests/run/i1991.scala b/tests/run/i1991.scala new file mode 100644 index 000000000..cec1dec89 --- /dev/null +++ b/tests/run/i1991.scala @@ -0,0 +1,29 @@ +import scala.reflect.ClassTag + +class A[Foo](implicit tag: ClassTag[Foo]) { + object ExtractFoo { + def unapply(foo: Foo): Boolean = true + } + + def isFoo(x: Any) = x match { + case ExtractFoo() => true + //case foo: Foo => true + case _ => false + } + + def testBind(x: Any) = x match { + case foo0: Foo => + (foo0: Foo) + case foo1 @ (_: Foo) => + (foo1: Foo) + case foo2 @ ExtractFoo() => + (foo2: Foo) + } +} + +object Test { + def main(args: Array[String]): Unit = { + assert((new A[String]).isFoo("foo")) // OK + assert(!(new A[String]).isFoo(42)) // OK in scalac, fails in Dotty + } +} |