Skip to content

Commit 2e1428d

Browse files
authored
Merge branch 'master' into topic/i6014
2 parents b9165fe + b6e4acf commit 2e1428d

File tree

25 files changed

+268
-31
lines changed

25 files changed

+268
-31
lines changed

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,15 +2076,14 @@ object TypeComparer {
20762076
/** Show trace of comparison operations when performing `op` as result string */
20772077
def explaining[T](say: String => Unit)(op: Context => T)(implicit ctx: Context): T = {
20782078
val nestedCtx = ctx.fresh.setTypeComparerFn(new ExplainingTypeComparer(_))
2079-
val res = op(nestedCtx)
2080-
say(nestedCtx.typeComparer.lastTrace())
2079+
val res = try { op(nestedCtx) } finally { say(nestedCtx.typeComparer.lastTrace()) }
20812080
res
20822081
}
20832082

20842083
/** Like [[explaining]], but returns the trace instead */
20852084
def explained[T](op: Context => T)(implicit ctx: Context): String = {
20862085
var trace: String = null
2087-
explaining(trace = _)(op)
2086+
try { explaining(trace = _)(op) } catch { case ex: Throwable => ex.printStackTrace }
20882087
trace
20892088
}
20902089
}

compiler/src/dotty/tools/dotc/tastyreflect/KernelImpl.scala

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ package tastyreflect
33

44
import dotty.tools.dotc.ast.{Trees, tpd, untpd}
55
import dotty.tools.dotc.ast.tpd.TreeOps
6+
import dotty.tools.dotc.typer.Typer
67
import dotty.tools.dotc.core._
78
import dotty.tools.dotc.core.Flags._
89
import dotty.tools.dotc.core.StdNames.nme
910
import dotty.tools.dotc.core.quoted.PickledQuotes
1011
import dotty.tools.dotc.core.Symbols._
1112
import dotty.tools.dotc.core.Decorators._
1213
import dotty.tools.dotc.tastyreflect.FromSymbol.{definitionFromSym, packageDefFromSym}
14+
import dotty.tools.dotc.parsing.Parsers.Parser
15+
import dotty.tools.dotc.util.SourceFile
1316

1417
import scala.tasty.reflect.Kernel
1518

@@ -36,9 +39,15 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
3639
def error(msg: => String, pos: Position)(implicit ctx: Context): Unit =
3740
ctx.error(msg, pos)
3841

42+
def error(msg: => String, sourceFile: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit =
43+
ctx.error(msg, util.SourcePosition(sourceFile, util.Spans.Span(start, end)))
44+
3945
def warning(msg: => String, pos: Position)(implicit ctx: Context): Unit =
4046
ctx.warning(msg, pos)
4147

48+
def warning(msg: => String, sourceFile: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit =
49+
ctx.error(msg, util.SourcePosition(sourceFile, util.Spans.Span(start, end)))
50+
4251
//
4352
// Settings
4453
//
@@ -47,6 +56,26 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
4756

4857
def Settings_color(self: Settings): Boolean = self.color.value(rootContext) == "always"
4958

59+
//
60+
// MISC
61+
//
62+
/** Whether the code type checks in the given context?
63+
*
64+
* @param code The code to be type checked
65+
*
66+
* The code should be a sequence of expressions or statements that may appear in a block.
67+
*/
68+
def typeChecks(code: String)(implicit ctx: Context): Boolean = {
69+
val ctx2 = ctx.fresh.setNewTyperState().setTyper(new Typer)
70+
val tree = new Parser(SourceFile.virtual("tasty-reflect", code))(ctx2).block()
71+
72+
if (ctx2.reporter.hasErrors) false
73+
else {
74+
ctx2.typer.typed(tree)(ctx2)
75+
!ctx2.reporter.hasErrors
76+
}
77+
}
78+
5079
//
5180
// TREES
5281
//
@@ -493,7 +522,7 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
493522
type Match = tpd.Match
494523

495524
def matchMatch(x: Term)(implicit ctx: Context): Option[Match] = x match {
496-
case x: tpd.Match => Some(x)
525+
case x: tpd.Match if !x.selector.isEmpty => Some(x)
497526
case _ => None
498527
}
499528

@@ -506,6 +535,21 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
506535
def Match_copy(original: Tree)(selector: Term, cases: List[CaseDef])(implicit ctx: Context): Match =
507536
tpd.cpy.Match(original)(selector, cases)
508537

538+
type ImplicitMatch = tpd.Match
539+
540+
def matchImplicitMatch(x: Term)(implicit ctx: Context): Option[Match] = x match {
541+
case x: tpd.Match if x.selector.isEmpty => Some(x)
542+
case _ => None
543+
}
544+
545+
def ImplicitMatch_cases(self: Match)(implicit ctx: Context): List[CaseDef] = self.cases
546+
547+
def ImplicitMatch_apply(cases: List[CaseDef])(implicit ctx: Context): ImplicitMatch =
548+
withDefaultPos(ctx => tpd.Match(tpd.EmptyTree, cases)(ctx))
549+
550+
def ImplicitMatch_copy(original: Tree)(cases: List[CaseDef])(implicit ctx: Context): ImplicitMatch =
551+
tpd.cpy.Match(original)(tpd.EmptyTree, cases)
552+
509553
type Try = tpd.Try
510554

511555
def matchTry(x: Term)(implicit ctx: Context): Option[Try] = x match {
@@ -1297,7 +1341,7 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
12971341

12981342
def Position_exists(self: Position): Boolean = self.exists
12991343

1300-
def Position_sourceFile(self: Position): java.nio.file.Path = self.source.file.jpath
1344+
def Position_sourceFile(self: Position): SourceFile = self.source
13011345

13021346
def Position_startLine(self: Position): Int = self.startLine
13031347

@@ -1310,6 +1354,16 @@ class KernelImpl(val rootContext: core.Contexts.Context, val rootPosition: util.
13101354
def Position_sourceCode(self: Position): String =
13111355
new String(self.source.content(), self.start, self.end - self.start)
13121356

1357+
//
1358+
// SOURCE FILES
1359+
//
1360+
1361+
type SourceFile = util.SourceFile
1362+
1363+
def SourceFile_jpath(self: SourceFile): java.nio.file.Path = self.file.jpath
1364+
1365+
def SourceFile_content(self: SourceFile): String = new String(self.content())
1366+
13131367
//
13141368
// COMMENTS
13151369
//

compiler/src/dotty/tools/dotc/transform/Pickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class Pickler extends Phase {
7878
// println(i"rawBytes = \n$rawBytes%\n%") // DEBUG
7979
if (pickling ne noPrinter) {
8080
println(i"**** pickled info of $cls")
81-
println(new TastyPrinter(pickler.assembleParts()).printContents())
81+
println(new TastyPrinter(pickled).printContents())
8282
}
8383
}
8484
}

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,8 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
405405

406406
/** Is `tp1` a subtype of `tp2`? */
407407
def isSubType(tp1: Type, tp2: Type): Boolean = {
408+
debug.println(TypeComparer.explained(implicit ctx => tp1 <:< tp2))
408409
val res = (tp1 != nullType || tp2 == nullType) && tp1 <:< tp2
409-
debug.println(s"${tp1} <:< ${tp2} = $res")
410410
res
411411
}
412412

compiler/src/dotty/tools/dotc/typer/Implicits.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,7 +1382,7 @@ abstract class SearchHistory { outer =>
13821382
val wideTp = tp.widenExpr
13831383
lazy val wildTp = wildApprox(wideTp)
13841384
if (belowByname && (wildTp <:< wildPt)) false
1385-
else if ((wideTp.typeSize < ptSize && wideTp.coveringSet == ptCoveringSet) || (wildTp == wildPt)) true
1385+
else if ((wideTp.typeSize < ptSize && wideTp.coveringSet == ptCoveringSet) || (wildTp =:= wildPt)) true
13861386
else loop(tl, isByname(tp) || belowByname)
13871387
}
13881388
else loop(tl, isByname(tp) || belowByname)

compiler/test/dotc/pos-from-tasty.blacklist

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,4 @@ i4006c.scala
2323

2424
# Not sure what's wring here
2525
i4203.scala
26-
t6278-synth-def.scala
27-
28-
# Need to print empty tree for implicit match
29-
i5938.scala
30-
i6014-gadt.scala
26+
t6278-synth-def.scala

compiler/test/dotc/run-from-tasty.blacklist

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,3 @@ eff-dependent.scala
33

44
# It seems we still harmonize types in fromTasty. Not sure where this happens
55
puzzle.scala
6-
7-
# Need to print empty tree for implicit match
8-
implicitMatch.scala
9-
typeclass-derivation1.scala
10-
typeclass-derivation2.scala
11-
typeclass-derivation2a.scala
12-
typeclass-derivation3.scala
13-
derive-generic.scala
14-
deriving-interesting-prefixes.scala
15-
companion-loading.scala

docs/docs/reference/other-new-features/tasty-reflect.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ TASTy Reflect provides the following types:
108108
| +- Lambda
109109
| +- If
110110
| +- Match
111+
| +- ImplicitMatch
111112
| +- Try
112113
| +- Return
113114
| +- Repeated

library/src/scala/tasty/Reflection.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ abstract class Reflection
2727
def typeOf[T: scala.quoted.Type]: Type =
2828
implicitly[scala.quoted.Type[T]].unseal.tpe
2929

30+
object typing {
31+
/** Whether the code type checks in the given context?
32+
*
33+
* @param code The code to be type checked
34+
*
35+
* @return false if the code has syntax error or type error in the given context, otherwise returns true.
36+
*
37+
* The code should be a sequence of expressions or statements that may appear in a block.
38+
*/
39+
def typeChecks(code: String)(implicit ctx: Context): Boolean = kernel.typeChecks(code)(ctx)
40+
}
41+
3042
val util: reflect.utils.TreeUtils { val reflect: self.type } = new reflect.utils.TreeUtils {
3143
val reflect: self.type = self
3244
}

library/src/scala/tasty/reflect/Core.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ package scala.tasty.reflect
2929
* | +- Lambda
3030
* | +- If
3131
* | +- Match
32+
* | +- ImplicitMatch
3233
* | +- Try
3334
* | +- Return
3435
* | +- Repeated
@@ -213,6 +214,9 @@ trait Core {
213214
/** Tree representing a pattern match `x match { ... }` in the source code */
214215
type Match = kernel.Match
215216

217+
/** Tree representing a pattern match `implicit match { ... }` in the source code */
218+
type ImplicitMatch = kernel.ImplicitMatch
219+
216220
/** Tree representing a tyr catch `try x catch { ... } finally { ... }` in the source code */
217221
type Try = kernel.Try
218222

@@ -407,9 +411,12 @@ trait Core {
407411
/** JVM signature of a method */
408412
type Signature = kernel.Signature
409413

410-
/** Source position */
414+
/** Position in a source file */
411415
type Position = kernel.Position
412416

417+
/** Scala source file */
418+
type SourceFile = kernel.SourceFile
419+
413420
/** Comment */
414421
type Comment = kernel.Comment
415422

library/src/scala/tasty/reflect/Kernel.scala

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ package scala.tasty.reflect
2828
* | +- Lambda
2929
* | +- If
3030
* | +- Match
31+
* | +- ImplicitMatch
3132
* | +- Try
3233
* | +- Return
3334
* | +- Repeated
@@ -145,9 +146,15 @@ trait Kernel {
145146
/** Report a compilation error with the given message at the given position */
146147
def error(msg: => String, pos: Position)(implicit ctx: Context): Unit
147148

149+
/** Report a compilation error with the given message at the given position range */
150+
def error(msg: => String, source: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit
151+
148152
/** Report a compilation warning with the given message at the given position */
149153
def warning(msg: => String, pos: Position)(implicit ctx: Context): Unit
150154

155+
/** Report a compilation warning with the given message at the given position range */
156+
def warning(msg: => String, source: SourceFile, start: Int, end: Int)(implicit ctx: Context): Unit
157+
151158
//
152159
// Settings
153160
//
@@ -157,6 +164,17 @@ trait Kernel {
157164

158165
def Settings_color(self: Settings): Boolean
159166

167+
//
168+
// MISC
169+
//
170+
/** Whether the code type checks in the given context?
171+
*
172+
* @param code The code to be type checked
173+
*
174+
* The code should be a sequence of expressions or statements that may appear in a block.
175+
*/
176+
def typeChecks(code: String)(implicit ctx: Context): Boolean
177+
160178
//
161179
// TREES
162180
//
@@ -444,6 +462,16 @@ trait Kernel {
444462
def Match_apply(selector: Term, cases: List[CaseDef])(implicit ctx: Context): Match
445463
def Match_copy(original: Tree)(selector: Term, cases: List[CaseDef])(implicit ctx: Context): Match
446464

465+
/** Tree representing a pattern match `implicit match { ... }` in the source code */
466+
type ImplicitMatch <: Term
467+
468+
def matchImplicitMatch(tree: Tree)(implicit ctx: Context): Option[ImplicitMatch]
469+
470+
def ImplicitMatch_cases(self: ImplicitMatch)(implicit ctx: Context): List[CaseDef]
471+
472+
def ImplicitMatch_apply(cases: List[CaseDef])(implicit ctx: Context): ImplicitMatch
473+
def ImplicitMatch_copy(original: Tree)(cases: List[CaseDef])(implicit ctx: Context): ImplicitMatch
474+
447475
/** Tree representing a tyr catch `try x catch { ... } finally { ... }` in the source code */
448476
type Try <: Term
449477

@@ -1037,7 +1065,7 @@ trait Kernel {
10371065
// POSITIONS
10381066
//
10391067

1040-
/** Source position */
1068+
/** Position in a source file */
10411069
type Position <: AnyRef
10421070

10431071
/** The start offset in the source file */
@@ -1050,7 +1078,7 @@ trait Kernel {
10501078
def Position_exists(self: Position): Boolean
10511079

10521080
/** Source file in which this position is located */
1053-
def Position_sourceFile(self: Position): java.nio.file.Path
1081+
def Position_sourceFile(self: Position): SourceFile
10541082

10551083
/** The start line in the source file */
10561084
def Position_startLine(self: Position): Int
@@ -1067,6 +1095,19 @@ trait Kernel {
10671095
/** Source code within the position */
10681096
def Position_sourceCode(self: Position): String
10691097

1098+
//
1099+
// SOURCE FILE
1100+
//
1101+
1102+
/** Scala source file */
1103+
type SourceFile <: AnyRef
1104+
1105+
/** Path to a source file */
1106+
def SourceFile_jpath(self: SourceFile): java.nio.file.Path
1107+
1108+
/** Content of a source file */
1109+
def SourceFile_content(self: SourceFile): String
1110+
10701111
//
10711112
// COMMENTS
10721113
//

library/src/scala/tasty/reflect/PositionOps.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ trait PositionOps extends Core {
1414
def exists: Boolean = kernel.Position_exists(pos)
1515

1616
/** Source file in which this position is located */
17-
def sourceFile: java.nio.file.Path = kernel.Position_sourceFile(pos)
17+
def sourceFile: SourceFile = kernel.Position_sourceFile(pos)
1818

1919
/** The start line in the source file */
2020
def startLine: Int = kernel.Position_startLine(pos)
@@ -33,4 +33,14 @@ trait PositionOps extends Core {
3333

3434
}
3535

36+
implicit class SourceFileAPI(sourceFile: SourceFile) {
37+
38+
/** Path to this source file */
39+
def jpath: java.nio.file.Path = kernel.SourceFile_jpath(sourceFile)
40+
41+
/** Content of this source file */
42+
def content: String = kernel.SourceFile_content(sourceFile)
43+
44+
}
45+
3646
}

library/src/scala/tasty/reflect/Printers.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,8 @@ trait Printers
177177
this += "Term.Lambda(" += meth += ", " += tpt += ")"
178178
case Term.Match(selector, cases) =>
179179
this += "Term.Match(" += selector += ", " ++= cases += ")"
180+
case Term.ImplicitMatch(cases) =>
181+
this += "Term.ImplicitMatch(" ++= cases += ")"
180182
case Term.Return(expr) =>
181183
this += "Term.Return(" += expr += ")"
182184
case Term.While(cond, body) =>
@@ -896,6 +898,10 @@ trait Printers
896898
this += highlightKeyword(" match", color)
897899
inBlock(printCases(cases, lineBreak()))
898900

901+
case Term.ImplicitMatch(cases) =>
902+
this += highlightKeyword("implicit match", color)
903+
inBlock(printCases(cases, lineBreak()))
904+
899905
case Term.Try(body, cases, finallyOpt) =>
900906
this += highlightKeyword("try ", color)
901907
printTree(body)

0 commit comments

Comments
 (0)