Skip to content

Commit

Permalink
Add a phase for recomputing and rechecking all types in a typed Scala…
Browse files Browse the repository at this point in the history
… program. This is useful for two reasons:

 = It gives us additional explanation and validation what constitutes a well-typed Scala 3 program. Recheck has less than 300 lines of code, which is a lot less than Typer and associated files.
 - It can be used as a basis for phases that refine the original types with new kinds of types and new rules.
  • Loading branch information
odersky committed Aug 8, 2021
1 parent 58d1b10 commit b12ac2a
Show file tree
Hide file tree
Showing 13 changed files with 427 additions and 5 deletions.
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class Compiler {
new TupleOptimizations, // Optimize generic operations on tuples
new LetOverApply, // Lift blocks from receivers of applications
new ArrayConstructors) :: // Intercept creation of (non-generic) arrays and intrinsify.
List(new PreRecheck) ::
List(new TestRecheck) ::
List(new Erasure) :: // Rewrite types to JVM model, erasing all type parameters, abstract types and refinements.
List(new ElimErasedValueType, // Expand erased value types to their underlying implmementation types
new PureStats, // Remove pure stats from blocks
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ object Printers {
val pickling = noPrinter
val quotePickling = noPrinter
val plugins = noPrinter
val recheckr = noPrinter
val refcheck = noPrinter
val simplify = noPrinter
val staging = noPrinter
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ private sealed trait YSettings:
val YexplicitNulls: Setting[Boolean] = BooleanSetting("-Yexplicit-nulls", "Make reference types non-nullable. Nullable types can be expressed with unions: e.g. String|Null.")
val YcheckInit: Setting[Boolean] = BooleanSetting("-Ysafe-init", "Ensure safe initialization of objects")
val YrequireTargetName: Setting[Boolean] = BooleanSetting("-Yrequire-targetName", "Warn if an operator is defined without a @targetName annotation")
val Yrecheck: Setting[Boolean] = BooleanSetting("-Yrecheck", "Run type rechecks (test only)")

/** Area-specific debug output */
val YexplainLowlevel: Setting[Boolean] = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.")
Expand Down
20 changes: 20 additions & 0 deletions compiler/src/dotty/tools/dotc/core/NamerOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -177,4 +177,24 @@ object NamerOps:
cls.registeredCompanion = modcls
modcls.registeredCompanion = cls

/** For secondary constructors, make it known in the context that their type parameters
* are aliases of the class type parameters. This is done by (ab?)-using GADT constraints.
* See pos/i941.scala
*/
def linkConstructorParams(sym: Symbol)(using Context): Context =
if sym.isConstructor && !sym.isPrimaryConstructor then
sym.rawParamss match
case (tparams @ (tparam :: _)) :: _ if tparam.isType =>
val rhsCtx = ctx.fresh.setFreshGADTBounds
rhsCtx.gadt.addToConstraint(tparams)
tparams.lazyZip(sym.owner.typeParams).foreach { (psym, tparam) =>
val tr = tparam.typeRef
rhsCtx.gadt.addBound(psym, tr, isUpper = false)
rhsCtx.gadt.addBound(psym, tr, isUpper = true)
}
rhsCtx
case _ =>
ctx
else ctx

end NamerOps
21 changes: 21 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/PreRecheck.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dotty.tools.dotc
package transform

import core.Phases.Phase
import core.DenotTransformers.IdentityDenotTransformer
import core.Contexts.{Context, ctx}

/** A phase that precedes the rechecker and that allows installing
* new types for local symbols.
*/
class PreRecheck extends Phase, IdentityDenotTransformer:

def phaseName: String = "preRecheck"

override def isEnabled(using Context) = next.isEnabled

override def changesBaseTypes: Boolean = true

def run(using Context): Unit = ()

override def isCheckable = false
Loading

0 comments on commit b12ac2a

Please sign in to comment.