@@ -67,7 +67,9 @@ object Inliner {
6767 * and body that replace it.
6868 */
6969 def inlineCall (tree : Tree )(implicit ctx : Context ): Tree = {
70- if (tree.symbol == defn.CompiletimeTesting_typeChecks ) return Intrinsics .typeChecks(tree)
70+ if tree.symbol.denot != SymDenotations .NoDenotation && tree.symbol.owner.companionModule == defn.CompiletimeTestingPackageObject
71+ if (tree.symbol == defn.CompiletimeTesting_typeChecks ) return Intrinsics .typeChecks(tree)
72+ if (tree.symbol == defn.CompiletimeTesting_typeCheckErrors ) return Intrinsics .typeCheckErrors(tree)
7173
7274 /** Set the position of all trees logically contained in the expansion of
7375 * inlined call `call` to the position of `call`. This transform is necessary
@@ -194,10 +196,12 @@ object Inliner {
194196 }
195197
196198 object Intrinsics {
199+ import dotty .tools .dotc .reporting .diagnostic .messages .Error
200+ private enum ErrorKind
201+ case Parser , Typer
197202
198- /** Expand call to scala.compiletime.testing.typeChecks */
199- def typeChecks (tree : Tree )(implicit ctx : Context ): Tree = {
200- assert(tree.symbol == defn.CompiletimeTesting_typeChecks )
203+ private def compileForErrors (tree : Tree , stopAfterParser : Boolean )(given ctx : Context ): List [(ErrorKind , Error )] =
204+ assert(tree.symbol == defn.CompiletimeTesting_typeChecks || tree.symbol == defn.CompiletimeTesting_typeCheckErrors )
201205 def stripTyped (t : Tree ): Tree = t match {
202206 case Typed (t2, _) => stripTyped(t2)
203207 case _ => t
@@ -206,20 +210,49 @@ object Inliner {
206210 val Apply (_, codeArg :: Nil ) = tree
207211 ConstFold (stripTyped(codeArg.underlyingArgument)).tpe.widenTermRefExpr match {
208212 case ConstantType (Constant (code : String )) =>
209- val ctx2 = ctx.fresh.setNewTyperState().setTyper(new Typer )
210- val tree2 = new Parser (SourceFile .virtual(" tasty-reflect" , code))(ctx2).block()
211- val res =
212- if (ctx2.reporter.hasErrors) false
213- else {
214- ctx2.typer.typed(tree2)(ctx2)
215- ! ctx2.reporter.hasErrors
216- }
217- Literal (Constant (res))
213+ val source2 = SourceFile .virtual(" tasty-reflect" , code)
214+ val ctx2 = ctx.fresh.setNewTyperState().setTyper(new Typer ).setSource(source2)
215+ val tree2 = new Parser (source2)(ctx2).block()
216+ val res = collection.mutable.ListBuffer .empty[(ErrorKind , Error )]
217+
218+ val parseErrors = ctx2.reporter.allErrors.toList
219+ res ++= parseErrors.map(e => ErrorKind .Parser -> e)
220+ if ! stopAfterParser || res.isEmpty
221+ ctx2.typer.typed(tree2)(ctx2)
222+ val typerErrors = ctx2.reporter.allErrors.filterNot(parseErrors.contains)
223+ res ++= typerErrors.map(e => ErrorKind .Typer -> e)
224+ res.toList
218225 case t =>
219226 assert(ctx.reporter.hasErrors) // at least: argument to inline parameter must be a known value
220- EmptyTree
227+ Nil
221228 }
222- }
229+
230+ private def packError (kind : ErrorKind , error : Error )(given Context ): Tree =
231+ def lit (x : Any ) = Literal (Constant (x))
232+ val constructor : Tree = ref(defn.CompiletimeTesting_Error_apply )
233+ val parserErrorKind : Tree = ref(defn.CompiletimeTesting_ErrorKind_Parser )
234+ val typerErrorKind : Tree = ref(defn.CompiletimeTesting_ErrorKind_Typer )
235+
236+ constructor.appliedTo(
237+ lit(error.message),
238+ lit(error.pos.lineContent.reverse.dropWhile(" \n " .contains).reverse),
239+ lit(error.pos.column),
240+ if kind == ErrorKind .Parser then parserErrorKind else typerErrorKind)
241+
242+ private def packErrors (errors : List [(ErrorKind , Error )])(given Context ): Tree =
243+ val individualErrors : List [Tree ] = errors.map(packError)
244+ val errorTpt = ref(defn.CompiletimeTesting_ErrorClass )
245+ mkList(individualErrors, errorTpt)
246+
247+ /** Expand call to scala.compiletime.testing.typeChecks */
248+ def typeChecks (tree : Tree )(given Context ): Tree =
249+ val errors = compileForErrors(tree, true )
250+ Literal (Constant (errors.isEmpty))
251+
252+ /** Expand call to scala.compiletime.testing.typeCheckErrors */
253+ def typeCheckErrors (tree : Tree )(given Context ): Tree =
254+ val errors = compileForErrors(tree, false )
255+ packErrors(errors)
223256 }
224257}
225258
0 commit comments