From 8fff72284045f78d6ad99178dea618a72e148d7c Mon Sep 17 00:00:00 2001 From: Matt Bovel Date: Tue, 30 May 2023 18:34:19 +0200 Subject: [PATCH] Detail "not a constant type" message --- .../src/dotty/tools/dotc/inlines/Inlines.scala | 4 ++-- .../tools/dotc/reporting/ErrorMessageID.scala | 1 + .../src/dotty/tools/dotc/reporting/messages.scala | 7 +++++++ tests/neg/17211.check | 14 ++++++++++++++ tests/neg/17211.scala | 14 ++++++++++++++ 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 tests/neg/17211.check create mode 100644 tests/neg/17211.scala diff --git a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala index 36dc8a642afc..bcc10ffa6db8 100644 --- a/compiler/src/dotty/tools/dotc/inlines/Inlines.scala +++ b/compiler/src/dotty/tools/dotc/inlines/Inlines.scala @@ -17,7 +17,7 @@ import transform.{PostTyper, Inlining, CrossVersionChecks} import staging.StagingLevel import collection.mutable -import reporting.trace +import reporting.{NotConstant, trace} import util.Spans.Span /** Support for querying inlineable methods and for inlining calls to such methods */ @@ -413,7 +413,7 @@ object Inlines: if (inlinedMethod == defn.Compiletime_constValue) { val constVal = tryConstValue if constVal.isEmpty then - val msg = em"not a constant type: ${callTypeArgs.head}; cannot take constValue" + val msg = NotConstant("cannot take constValue", callTypeArgs.head.tpe) return ref(defn.Predef_undefined).withSpan(call.span).withType(ErrorType(msg)) else return constVal diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index fc679210db17..ad56f29287fc 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -195,6 +195,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case MatchTypeScrutineeCannotBeHigherKindedID // errorNumber: 179 case AmbiguousExtensionMethodID // errorNumber 180 case UnqualifiedCallToAnyRefMethodID // errorNumber: 181 + case NotConstantID // errorNumber: 182 def errorNumber = ordinal - 1 diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index d205b816214c..0218d8a9c915 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -2624,6 +2624,13 @@ extends TypeMsg(NotClassTypeID), ShowMatchTrace(tp): def msg(using Context) = i"$tp is not a class type" def explain(using Context) = "" +class NotConstant(suffix: String, tp: Type)(using Context) +extends TypeMsg(NotConstantID), ShowMatchTrace(tp): + def msg(using Context) = + i"$tp is not a constant type" + + (if suffix.isEmpty then "" else i"; $suffix") + def explain(using Context) = "" + class MissingImplicitArgument( arg: tpd.Tree, pt: Type, diff --git a/tests/neg/17211.check b/tests/neg/17211.check new file mode 100644 index 000000000000..3c2f10a61957 --- /dev/null +++ b/tests/neg/17211.check @@ -0,0 +1,14 @@ +-- [E182] Type Error: tests/neg/17211.scala:14:12 ---------------------------------------------------------------------- +14 | constValue[IsInt[Foo.Foo]] // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | IsInt[Foo.Foo] is not a constant type; cannot take constValue + | + | Note: a match type could not be fully reduced: + | + | trying to reduce IsInt[Foo.Foo] + | failed since selector Foo.Foo + | does not match case Int => (true : Boolean) + | and cannot be shown to be disjoint from it either. + | Therefore, reduction cannot advance to the remaining case + | + | case _ => (false : Boolean) diff --git a/tests/neg/17211.scala b/tests/neg/17211.scala new file mode 100644 index 000000000000..3e59e657c4a7 --- /dev/null +++ b/tests/neg/17211.scala @@ -0,0 +1,14 @@ +import scala.compiletime.constValue + +type IsInt[A] = A match + case Int => true + case _ => false + +def test = + val x = constValue[IsInt[Int]] // val res2: Boolean = true; works + val y = constValue[IsInt[String]] // val res3: Boolean = false; works + + object Foo: + opaque type Foo = Int + + constValue[IsInt[Foo.Foo]] // error