Skip to content

Track type variable dependencies to guide instantiation decisions #16042

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Oct 31, 2022
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions compiler/src/dotty/tools/dotc/config/Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ object Config {
*/
inline val checkConstraintsNonCyclic = false

/** Check that reverse dependencies in constraints are correct and complete.
* Can also be enabled using -Ycheck-constraint-deps.
*/
inline val checkConstraintDeps = false

/** Check that each constraint resulting from a subtype test
* is satisfiable. Also check that a type variable instantiation
* satisfies its constraints.
Expand Down Expand Up @@ -184,6 +189,9 @@ object Config {
/** If set, prints a trace of all symbol completions */
inline val showCompletions = false

/** If set, show variable/variable reverse dependencies when printing constraints. */
inline val showConstraintDeps = true

/** If set, method results that are context functions are flattened by adding
* the parameters of the context function results to the methods themselves.
* This is an optimization that reduces closure allocations.
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 @@ -309,6 +309,7 @@ private sealed trait YSettings:
val YforceSbtPhases: Setting[Boolean] = BooleanSetting("-Yforce-sbt-phases", "Run the phases used by sbt for incremental compilation (ExtractDependencies and ExtractAPI) even if the compiler is ran outside of sbt, for debugging.")
val YdumpSbtInc: Setting[Boolean] = BooleanSetting("-Ydump-sbt-inc", "For every compiled foo.scala, output the API representation and dependencies used for sbt incremental compilation in foo.inc, implies -Yforce-sbt-phases.")
val YcheckAllPatmat: Setting[Boolean] = BooleanSetting("-Ycheck-all-patmat", "Check exhaustivity and redundancy of all pattern matching (used for testing the algorithm).")
val YcheckConstraintDeps: Setting[Boolean] = BooleanSetting("-Ycheck-constraint-deps", "Check dependency tracking in constraints (used for testing the algorithm).")
val YretainTrees: Setting[Boolean] = BooleanSetting("-Yretain-trees", "Retain trees for top-level classes, accessible from ClassSymbol#tree")
val YshowTreeIds: Setting[Boolean] = BooleanSetting("-Yshow-tree-ids", "Uniquely tag all tree nodes in debugging output.")
val YfromTastyIgnoreList: Setting[List[String]] = MultiStringSetting("-Yfrom-tasty-ignore-list", "file", "List of `tasty` files in jar files that will not be loaded when using -from-tasty")
Expand Down
26 changes: 22 additions & 4 deletions compiler/src/dotty/tools/dotc/core/Constraint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package core

import Types._, Contexts._
import printing.Showable
import util.{SimpleIdentitySet, SimpleIdentityMap}

/** Constraint over undetermined type parameters. Constraints are built
* over values of the following types:
Expand Down Expand Up @@ -128,7 +129,7 @@ abstract class Constraint extends Showable {

/** Is `tv` marked as hard in the constraint? */
def isHard(tv: TypeVar): Boolean

/** The same as this constraint, but with `tv` marked as hard. */
def withHard(tv: TypeVar)(using Context): This

Expand Down Expand Up @@ -165,15 +166,32 @@ abstract class Constraint extends Showable {
*/
def hasConflictingTypeVarsFor(tl: TypeLambda, that: Constraint): Boolean

/** Check that no constrained parameter contains itself as a bound */
def checkNonCyclic()(using Context): this.type

/** Does `param` occur at the toplevel in `tp` ?
* Toplevel means: the type itself or a factor in some
* combination of `&` or `|` types.
*/
def occursAtToplevel(param: TypeParamRef, tp: Type)(using Context): Boolean

/** A string that shows the reverse dependencies maintained by this constraint
* (coDeps and contraDeps for OrderingConstraints).
*/
def depsToString(using Context): String

/** Does the constraint restricted to variables outside `except` depend on `tv`
* in the given direction `co`?
* @param `co` If true, test whether the constraint would change if the variable is made larger
* otherwise, test whether the constraint would change if the variable is made smaller.
*/
def dependsOn(tv: TypeVar, except: TypeVars, co: Boolean)(using Context): Boolean

/** Depending on Config settngs:
* - Under `checkConstraintsNonCyclic`, check that no constrained
* parameter contains itself as a bound.
* - Under `checkConstraintDeps`, check hat reverse dependencies in
* constraints are correct and complete.
*/
def checkWellFormed()(using Context): this.type

/** Check that constraint only refers to TypeParamRefs bound by itself */
def checkClosed()(using Context): Unit

Expand Down
Loading