diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala index b435baba23f1..4c252d572d86 100644 --- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala @@ -325,7 +325,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase // Check the constructor type as well; it could be an illegal singleton type // which would not be reflected as `tree.tpe` ctx.typer.checkClassType(nu.tpe, tree.srcPos, traitReq = false, stablePrefixReq = false) - Checking.checkInstantiable(tree.tpe, nu.srcPos) + Checking.checkInstantiable(tree.tpe, nu.tpe, nu.srcPos) withNoCheckNews(nu :: Nil)(app1) case _ => app1 @@ -413,7 +413,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase Checking.checkGoodBounds(tree.symbol) super.transform(tree) case tree: New if isCheckable(tree) => - Checking.checkInstantiable(tree.tpe, tree.srcPos) + Checking.checkInstantiable(tree.tpe, tree.tpe, tree.srcPos) super.transform(tree) case tree: Closure if !tree.tpt.isEmpty => Checking.checkRealizable(tree.tpt.tpe, tree.srcPos, "SAM type") diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index a1ee2c539622..4c3819e9872c 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -185,12 +185,14 @@ object Checking { /** Check that `tp` refers to a nonAbstract class * and that the instance conforms to the self type of the created class. */ - def checkInstantiable(tp: Type, pos: SrcPos)(using Context): Unit = + def checkInstantiable(tp: Type, srcTp: Type, pos: SrcPos)(using Context): Unit = tp.underlyingClassRef(refinementOK = false) match case tref: TypeRef => val cls = tref.symbol - if (cls.isOneOf(AbstractOrTrait)) - report.error(CantInstantiateAbstractClassOrTrait(cls, isTrait = cls.is(Trait)), pos) + if (cls.isOneOf(AbstractOrTrait)) { + val srcCls = srcTp.underlyingClassRef(refinementOK = false).typeSymbol + report.error(CantInstantiateAbstractClassOrTrait(srcCls, isTrait = srcCls.is(Trait)), pos) + } if !cls.is(Module) then // 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/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 20daa2d24406..decc22ecfda9 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -159,6 +159,7 @@ class CompilationTests { compileFile("tests/neg-custom-args/i9517.scala", defaultOptions.and("-Xprint-types")), compileFile("tests/neg-custom-args/i11637.scala", defaultOptions.and("-explain")), compileFile("tests/neg-custom-args/i15575.scala", defaultOptions.and("-explain")), + compileFile("tests/neg-custom-args/i16601a.scala", defaultOptions.and("-explain")), compileFile("tests/neg-custom-args/interop-polytypes.scala", allowDeepSubtypes.and("-Yexplicit-nulls")), compileFile("tests/neg-custom-args/conditionalWarnings.scala", allowDeepSubtypes.and("-deprecation").and("-Xfatal-warnings")), compileFilesInDir("tests/neg-custom-args/isInstanceOf", allowDeepSubtypes and "-Xfatal-warnings"), diff --git a/tests/neg-custom-args/i16601a.check b/tests/neg-custom-args/i16601a.check new file mode 100644 index 000000000000..604f71993ada --- /dev/null +++ b/tests/neg-custom-args/i16601a.check @@ -0,0 +1,18 @@ +-- [E042] Type Error: tests/neg-custom-args/i16601a.scala:1:27 --------------------------------------------------------- +1 |@main def Test: Unit = new concurrent.ExecutionContext // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ExecutionContext is a trait; it cannot be instantiated + |--------------------------------------------------------------------------------------------------------------------- + | Explanation (enabled by `-explain`) + |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | 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 ExecutionContext with + | class ExecutionContext { } + | + | or add a companion object with + | object ExecutionContext extends ExecutionContext + | + | You need to implement any abstract members in both cases. + --------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg-custom-args/i16601a.scala b/tests/neg-custom-args/i16601a.scala new file mode 100644 index 000000000000..2e058db0093c --- /dev/null +++ b/tests/neg-custom-args/i16601a.scala @@ -0,0 +1 @@ +@main def Test: Unit = new concurrent.ExecutionContext // error \ No newline at end of file diff --git a/tests/neg/i16601.check b/tests/neg/i16601.check new file mode 100644 index 000000000000..25baef04e479 --- /dev/null +++ b/tests/neg/i16601.check @@ -0,0 +1,6 @@ +-- [E042] Type Error: tests/neg/i16601.scala:1:27 ---------------------------------------------------------------------- +1 |@main def Test: Unit = new concurrent.ExecutionContext // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ExecutionContext is a trait; it cannot be instantiated + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i16601.scala b/tests/neg/i16601.scala new file mode 100644 index 000000000000..2e058db0093c --- /dev/null +++ b/tests/neg/i16601.scala @@ -0,0 +1 @@ +@main def Test: Unit = new concurrent.ExecutionContext // error \ No newline at end of file