From dcfebd88e42afb18d176748fb89f78199f57f8d4 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 12 Apr 2015 17:55:18 +0200 Subject: [PATCH 1/8] Better printing of anonymous classes. Now prints `C{...}` instead of `$anon`. --- src/dotty/tools/dotc/printing/PlainPrinter.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala index 2762d9b51151..0a7edd2aa779 100644 --- a/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -354,7 +354,8 @@ class PlainPrinter(_ctx: Context) extends Printer { def toText(sym: Symbol): Text = (kindString(sym) ~~ { - if (hasMeaninglessName(sym)) simpleNameString(sym.owner) + idString(sym) + if (sym.isAnonymousClass) toText(sym.info.parents, " with ") ~ "{...}" + else if (hasMeaninglessName(sym)) simpleNameString(sym.owner) + idString(sym) else nameString(sym) }).close From d4dc78c3ebe4e8b559c3a85b6b77c321b239bb90 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 12 Apr 2015 18:01:27 +0200 Subject: [PATCH 2/8] New method on types: givenSelfType The self type as given (or implied for module classes) in the source. Also defined and updated for normal types, not just ClassInfo types. Common functionality between this and baseTypeWithArgs has been pulled into RefinedType#wrapIfMember. --- .../tools/dotc/core/TypeApplications.scala | 6 +-- src/dotty/tools/dotc/core/Types.scala | 45 +++++++++++++------ 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index df18813b9280..de42b3e5fea5 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -268,9 +268,7 @@ class TypeApplications(val self: Type) extends AnyVal { case _ => default } case tp @ RefinedType(parent, name) if !tp.member(name).symbol.is(ExpandedTypeParam) => - val pbase = parent.baseTypeWithArgs(base) - if (pbase.member(name).exists) RefinedType(pbase, name, tp.refinedInfo) - else pbase + tp.wrapIfMember(parent.baseTypeWithArgs(base)) case tp: TermRef => tp.underlying.baseTypeWithArgs(base) case AndType(tp1, tp2) => @@ -281,7 +279,7 @@ class TypeApplications(val self: Type) extends AnyVal { default } } - + /** Translate a type of the form From[T] to To[T], keep other types as they are. * `from` and `to` must be static classes, both with one type parameter, and the same variance. */ diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index e6235695ed8e..fe95219b8415 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -858,6 +858,13 @@ object Types { case _ => defn.AnyClass.typeRef } + /** the self type of the underlying classtype */ + def givenSelfType(implicit ctx: Context): Type = this match { + case tp @ RefinedType(parent, name) => tp.wrapIfMember(parent.givenSelfType) + case tp: TypeProxy => tp.underlying.givenSelfType + case _ => NoType + } + /** The parameter types of a PolyType or MethodType, Empty list for others */ final def paramTypess(implicit ctx: Context): List[List[Type]] = this match { case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess @@ -1781,7 +1788,12 @@ object Types { if (false) RefinedType(parent, refinedName, refinedInfo) else RefinedType(parent, refinedName, rt => refinedInfo.substSkolem(this, SkolemType(rt))) } - + + /** Add this refinement to `parent`, provided If `refinedName` is a member of `parent`. */ + def wrapIfMember(parent: Type)(implicit ctx: Context): Type = + if (parent.member(refinedName).exists) derivedRefinedType(parent, refinedName, refinedInfo) + else parent + override def equals(that: Any) = that match { case that: RefinedType => this.parent == that.parent && @@ -2398,22 +2410,27 @@ object Types { * - the fully applied reference to the class itself. */ def selfType(implicit ctx: Context): Type = { - if (selfTypeCache == null) { - def fullRef = fullyAppliedRef(cls.typeRef, cls.typeParams) - def withFullRef(tp: Type): Type = - if (ctx.erasedTypes) fullRef else AndType(tp, fullRef) - selfTypeCache = selfInfo match { - case NoType => - fullRef - case tp: Type => - if (cls is Module) tp else withFullRef(tp) - case self: Symbol => - assert(!(cls is Module)) - withFullRef(self.info) + if (selfTypeCache == null) + selfTypeCache = { + def fullRef = fullyAppliedRef(cls.typeRef, cls.typeParams) + val given = givenSelfType + val raw = + if (!given.exists) fullRef + else if (cls is Module) given + else if (ctx.erasedTypes) fullRef + else AndType(given, fullRef) + raw//.asSeenFrom(prefix, cls.owner) } - } selfTypeCache } + + /** The explicitly given self type (self types of modules are assumed to be + * explcitly given here). + */ + override def givenSelfType(implicit ctx: Context): Type = selfInfo match { + case tp: Type => tp + case self: Symbol => self.info + } private var selfTypeCache: Type = null From 04eea24326c3a42ad908fe45e204af41b880f2cd Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 12 Apr 2015 18:05:11 +0200 Subject: [PATCH 3/8] Self type inheritance check Check that the self type of a class conforms to the self types of its parent classes. --- src/dotty/tools/dotc/typer/RefChecks.scala | 12 ++++++++++ test/dotc/tests.scala | 1 + tests/neg/selfInheritance.scala | 28 ++++++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 tests/neg/selfInheritance.scala diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala index 9b14fffc07d2..6a1f3652b444 100644 --- a/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/src/dotty/tools/dotc/typer/RefChecks.scala @@ -71,6 +71,17 @@ object RefChecks { } } + /** Check that self type of this class conforms to self types of parents */ + private def checkSelfType(clazz: Symbol)(implicit ctx: Context): Unit = clazz.info match { + case cinfo: ClassInfo => + for (parent <- cinfo.classParents) { + val pself = parent.givenSelfType.asSeenFrom(clazz.thisType, parent.classSymbol) + if (pself.exists && !(cinfo.selfType <:< pself)) + ctx.error(d"illegal inheritance: self type ${cinfo.selfType} of $clazz does not conform to self type $pself of parent ${parent.classSymbol}", clazz.pos) + } + case _ => + } + // Override checking ------------------------------------------------------------ /** 1. Check all members of class `clazz` for overriding conditions. @@ -770,6 +781,7 @@ class RefChecks extends MiniPhase with SymTransformer { thisTransformer => override def transformTemplate(tree: Template)(implicit ctx: Context, info: TransformerInfo) = { val cls = ctx.owner checkOverloadedRestrictions(cls) + checkSelfType(cls) checkAllOverrides(cls) checkAnyValSubclass(cls) tree diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index a015b9efec1b..c3f501a52cd6 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -126,6 +126,7 @@ class tests extends CompilerTest { @Test def neg_i0281 = compileFile(negDir, "i0281-null-primitive-conforms", xerrors = 3) @Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4) @Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2) + @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5) @Test def dotc = compileDir(dotcDir + "tools/dotc", failedOther)(allowDeepSubtypes ++ twice) // see dotc_core @Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast", failedOther ++ twice) diff --git a/tests/neg/selfInheritance.scala b/tests/neg/selfInheritance.scala new file mode 100644 index 000000000000..5f61c5bbbdb8 --- /dev/null +++ b/tests/neg/selfInheritance.scala @@ -0,0 +1,28 @@ +trait T { self: B => } + +abstract class A { self: B => + +} + +class B extends A with T { +} + +class C { self: B => + +} + +class D extends A // error + +class E extends T // error + +object Test { + + new B() {} + + new A() {} // error + + object O extends A // error + + object M extends C // error + +} From 046376e48bd3c4a294cef239a6cc77a61b62bc6e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Apr 2015 15:47:54 +0200 Subject: [PATCH 4/8] Added phase to check `New` nodes for instantiability. - Abstract classes cannot be instantiated (exceptions: parent news and Java annotations) - Instantiateed class must conform to its self type. --- src/dotty/tools/dotc/Compiler.scala | 3 +- .../tools/dotc/transform/FirstTransform.scala | 4 + src/dotty/tools/dotc/typer/InstChecks.scala | 89 +++++++++++++++++++ test/dotc/tests.scala | 1 + tests/neg/instantiateAbstract.scala | 38 ++++++++ 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 src/dotty/tools/dotc/typer/InstChecks.scala create mode 100644 tests/neg/instantiateAbstract.scala diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala index 25a4c578b859..c67fb124a710 100644 --- a/src/dotty/tools/dotc/Compiler.scala +++ b/src/dotty/tools/dotc/Compiler.scala @@ -6,7 +6,7 @@ import Contexts._ import Periods._ import Symbols._ import Scopes._ -import typer.{FrontEnd, Typer, Mode, ImportInfo, RefChecks} +import typer.{FrontEnd, Typer, Mode, ImportInfo, RefChecks, InstChecks} import reporting.ConsoleReporter import dotty.tools.dotc.core.Phases.Phase import dotty.tools.dotc.transform._ @@ -38,6 +38,7 @@ class Compiler { def phases: List[List[Phase]] = List( List(new FrontEnd), + List(new InstChecks), List(new FirstTransform, new SyntheticMethods), List(new SuperAccessors), diff --git a/src/dotty/tools/dotc/transform/FirstTransform.scala b/src/dotty/tools/dotc/transform/FirstTransform.scala index cfe650b99b1e..02d0bb2ba285 100644 --- a/src/dotty/tools/dotc/transform/FirstTransform.scala +++ b/src/dotty/tools/dotc/transform/FirstTransform.scala @@ -35,6 +35,10 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi import ast.tpd._ override def phaseName = "firstTransform" + + override def runsAfter = Set(classOf[typer.InstChecks]) + // This phase makes annotations disappear in types, so InstChecks should + // run before so that it can get at all annotations. def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = tp diff --git a/src/dotty/tools/dotc/typer/InstChecks.scala b/src/dotty/tools/dotc/typer/InstChecks.scala new file mode 100644 index 000000000000..91c109ce844b --- /dev/null +++ b/src/dotty/tools/dotc/typer/InstChecks.scala @@ -0,0 +1,89 @@ +package dotty.tools.dotc +package typer + +import core._ +import Contexts.Context +import Decorators._ +import Phases._ +import Types._, Symbols._, Flags._, StdNames._ +import util.Positions._ +import ast.Trees._ +import typer.ErrorReporting._ + +/** This checks `New` nodes, verifying that they can be instantiated. */ +class InstChecks extends Phase { + import ast.tpd._ + + override def phaseName: String = "instchecks" + + override def run(implicit ctx: Context): Unit = + instCheck.traverse(ctx.compilationUnit.tpdTree) + + /** Check that `tp` refers to a nonAbstract class + * and that the instance conforms to the self type of the created class. + */ + def checkInstantiatable(tp: Type, pos: Position)(implicit ctx: Context): Unit = + tp.underlyingClassRef(refinementOK = false) match { + case tref: TypeRef => + val cls = tref.symbol + if (cls.is(AbstractOrTrait)) + ctx.error(d"$cls is abstract; cannot be instantiated", pos) + if (!cls.is(Module)) { + val selfType = tp.givenSelfType.asSeenFrom(tref.prefix, cls.owner) + if (selfType.exists && !(tp <:< selfType)) + ctx.error(d"$tp does not conform to its self type $selfType; cannot be instantiated") + } + case _ => + } + + def checkValidJavaAnnotation(annot: Tree)(implicit ctx: Context): Unit = { + // TODO fill in + } + + val instCheck = new TreeTraverser { + + def checkAnnot(annot: Tree)(implicit ctx: Context): Unit = + if (annot.symbol.is(JavaDefined)) checkValidJavaAnnotation(annot) + else traverse(annot) + + def traverseNoCheck(tree: Tree)(implicit ctx: Context): Unit = tree match { + case Apply(fn, args) => + traverseNoCheck(fn) + args.foreach(traverse) + case TypeApply(fn, args) => + traverseNoCheck(fn) + args.foreach(traverse) + case Select(qual, nme.CONSTRUCTOR) => + traverseNoCheck(qual) + case New(tpt) => + traverse(tpt) + case _ => + traverse(tree) + } + + def traverse(tree: Tree)(implicit ctx: Context): Unit = tree match { + case tree: New => + checkInstantiatable(tree.tpe, tree.pos) + traverseChildren(tree) + case impl @ Template(constr, parents, self, _) => + traverse(constr) + parents.foreach(traverseNoCheck) + traverse(self) + impl.body.foreach(traverse) + case Annotated(annot, tree) => + checkAnnot(annot) + traverse(tree) + case TypeTree(original) => + tree.tpe match { + case AnnotatedType(annot, tpe) => checkAnnot(annot.tree) + case _ => + } + traverse(original) + case tree: MemberDef => + tree.symbol.annotations.foreach(annot => checkAnnot(annot.tree)) + traverseChildren(tree) + case _ => + traverseChildren(tree) + } + } +} diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index c3f501a52cd6..b9ed6fb0311e 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -126,6 +126,7 @@ class tests extends CompilerTest { @Test def neg_i0281 = compileFile(negDir, "i0281-null-primitive-conforms", xerrors = 3) @Test def neg_moduleSubtyping = compileFile(negDir, "moduleSubtyping", xerrors = 4) @Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2) + @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5) @Test def dotc = compileDir(dotcDir + "tools/dotc", failedOther)(allowDeepSubtypes ++ twice) // see dotc_core diff --git a/tests/neg/instantiateAbstract.scala b/tests/neg/instantiateAbstract.scala new file mode 100644 index 000000000000..1e119a8b57e2 --- /dev/null +++ b/tests/neg/instantiateAbstract.scala @@ -0,0 +1,38 @@ +abstract class AA + +trait TT + +class A { self: B => + +} + +@scala.annotation.Annotation class C // error + +class B extends A() { +} + +object Test { + + @scala.annotation.Annotation type T = String // error + @scala.annotation.Annotation val x = 1 // error + @scala.annotation.Annotation def f = 1 //error + + (1: @scala.annotation.Annotation) // error + + + new AA // error + + new TT // error + + new A // error + +// the following are OK in Typer but would be caught later in RefChecks + + new A() {} + + new AA() {} + + object O extends A + + object OO extends AA +} From 6ca41d5721da042218c81c4851de8333584c54f1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Apr 2015 15:50:52 +0200 Subject: [PATCH 5/8] Drop Java compilation units after Typer Java compilation units should not be retained after typer, as no code will be generated for them. All we need from them are their symbols. --- src/dotty/tools/dotc/transform/Pickler.scala | 34 +++++++++----------- src/dotty/tools/dotc/typer/FrontEnd.scala | 2 +- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/dotty/tools/dotc/transform/Pickler.scala b/src/dotty/tools/dotc/transform/Pickler.scala index 445fed2c4741..515dad2aa490 100644 --- a/src/dotty/tools/dotc/transform/Pickler.scala +++ b/src/dotty/tools/dotc/transform/Pickler.scala @@ -27,26 +27,24 @@ class Pickler extends Phase { override def run(implicit ctx: Context): Unit = { val unit = ctx.compilationUnit - if (!unit.isJava) { - val tree = unit.tpdTree - pickling.println(i"unpickling in run ${ctx.runId}") - if (ctx.settings.YtestPickler.value) beforePickling(unit) = tree.show + val tree = unit.tpdTree + pickling.println(i"unpickling in run ${ctx.runId}") + if (ctx.settings.YtestPickler.value) beforePickling(unit) = tree.show - val pickler = unit.pickler - val treePkl = new TreePickler(pickler) - treePkl.pickle(tree :: Nil) - unit.addrOfTree = treePkl.buf.addrOfTree - unit.addrOfSym = treePkl.addrOfSym - if (tree.pos.exists) - new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree :: Nil, tree.pos) + val pickler = unit.pickler + val treePkl = new TreePickler(pickler) + treePkl.pickle(tree :: Nil) + unit.addrOfTree = treePkl.buf.addrOfTree + unit.addrOfSym = treePkl.addrOfSym + if (tree.pos.exists) + new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree :: Nil, tree.pos) - def rawBytes = // not needed right now, but useful to print raw format. - unit.pickler.assembleParts().iterator.grouped(10).toList.zipWithIndex.map { - case (row, i) => s"${i}0: ${row.mkString(" ")}" - } - // println(i"rawBytes = \n$rawBytes%\n%") // DEBUG - if (pickling ne noPrinter) new TastyPrinter(pickler.assembleParts()).printContents() - } + def rawBytes = // not needed right now, but useful to print raw format. + unit.pickler.assembleParts().iterator.grouped(10).toList.zipWithIndex.map { + case (row, i) => s"${i}0: ${row.mkString(" ")}" + } + // println(i"rawBytes = \n$rawBytes%\n%") // DEBUG + if (pickling ne noPrinter) new TastyPrinter(pickler.assembleParts()).printContents() } override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = { diff --git a/src/dotty/tools/dotc/typer/FrontEnd.scala b/src/dotty/tools/dotc/typer/FrontEnd.scala index bb313501d9a6..ceb806e523d8 100644 --- a/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -51,7 +51,7 @@ class FrontEnd extends Phase { unitContexts foreach (enterSyms(_)) unitContexts foreach (typeCheck(_)) record("totalTrees", ast.Trees.ntrees) - unitContexts.map(_.compilationUnit) + unitContexts.map(_.compilationUnit).filter(!_.isJava) } override def run(implicit ctx: Context): Unit = { From abba939a71423070e29c6035fa973b3291423106 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 12 Apr 2015 18:24:26 +0200 Subject: [PATCH 6/8] Print supressed error message if it comes first. An error message might be suppressed because it contains internal code. But if it is the first one, we should still print it. Otherwise, we risk a scenario where we see "2 errors" but none is printed. --- src/dotty/tools/dotc/reporting/ConsoleReporter.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala index a7f7f70bb21a..f07f43a63675 100644 --- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala +++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala @@ -41,7 +41,7 @@ class ConsoleReporter( } override def doReport(d: Diagnostic)(implicit ctx: Context): Unit = - if (!d.isSuppressed) d match { + if (!d.isSuppressed || !hasErrors) d match { case d: Error => printMessageAndPos(s"error: ${d.msg}", d.pos) if (ctx.settings.prompt.value) displayPrompt() From 6571efa7ea1a5bd973ff010de6e38901cc77387b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 12 Apr 2015 18:28:31 +0200 Subject: [PATCH 7/8] Tweaks relative to error reporting --- src/dotty/tools/dotc/ast/Desugar.scala | 2 +- src/dotty/tools/dotc/typer/Checking.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index 165f4f53548d..0c13d1ecc2d4 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -786,7 +786,7 @@ object desugar { New(ref(defn.RepeatedAnnot.typeRef), Nil :: Nil), AppliedTypeTree(ref(seqClass.typeRef), t)) } else { - assert(ctx.mode.isExpr, ctx.mode) + assert(ctx.mode.isExpr || ctx.reporter.hasErrors, ctx.mode) Select(t, op) } case PrefixOp(op, t) => diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index 9303572d2a7c..b28afa6f2cfd 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -232,7 +232,7 @@ trait Checking { /** Check that type `tp` is stable. */ def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit = - if (!tp.isStable) + if (!tp.isStable && !tp.isErroneous) ctx.error(d"$tp is not stable", pos) /** Check that type `tp` is a legal prefix for '#'. From 35717b7d3029a87a4ec7c9b45d18644b33b560e8 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 13 Apr 2015 16:43:49 +0200 Subject: [PATCH 8/8] Allow future defs when printing with i"...". We saw a failure of accessing a denotation outside its defined interval, which got triggered by i"...". This should never be the case. We should be more interested in what i"..." has to print. (V2, to see whether this builds with Travis now) --- src/dotty/tools/dotc/core/Decorators.scala | 3 ++- src/dotty/tools/dotc/typer/InstChecks.scala | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index 1ce83442880c..4e672ef40287 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -7,6 +7,7 @@ import Contexts._, Names._, Phases._, printing.Texts._, printing.Printer, printi import util.Positions.Position, util.SourcePosition import collection.mutable.ListBuffer import dotty.tools.dotc.transform.TreeTransforms._ +import typer.Mode import scala.language.implicitConversions /** This object provides useful implicit decorators for types defined elsewhere */ @@ -172,7 +173,7 @@ object Decorators { def treatSingleArg(arg: Any) : Any = try arg match { - case arg: Showable => arg.show + case arg: Showable => arg.show(ctx.fresh.addMode(Mode.FutureDefsOK)) case _ => arg } catch { diff --git a/src/dotty/tools/dotc/typer/InstChecks.scala b/src/dotty/tools/dotc/typer/InstChecks.scala index 91c109ce844b..7148a6e6845d 100644 --- a/src/dotty/tools/dotc/typer/InstChecks.scala +++ b/src/dotty/tools/dotc/typer/InstChecks.scala @@ -9,9 +9,10 @@ import Types._, Symbols._, Flags._, StdNames._ import util.Positions._ import ast.Trees._ import typer.ErrorReporting._ +import DenotTransformers._ /** This checks `New` nodes, verifying that they can be instantiated. */ -class InstChecks extends Phase { +class InstChecks extends Phase with IdentityDenotTransformer { import ast.tpd._ override def phaseName: String = "instchecks"