Skip to content

Commit

Permalink
Add non-infering completers for infering tracked
Browse files Browse the repository at this point in the history
  • Loading branch information
KacperFKorban committed Oct 24, 2024
1 parent 212fb2f commit a6d3770
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 18 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/Feature.scala
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ object Feature:
* feature is defined.
*/
def enabled(feature: TermName)(using Context): Boolean =
enabledBySetting(feature) || enabledByImport(feature) || feature == modularity
enabledBySetting(feature) || enabledByImport(feature)

/** Is auto-tupling enabled? */
def autoTuplingEnabled(using Context): Boolean = !enabled(nme.noAutoTupling)
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2756,6 +2756,9 @@ object SymDenotations {
/** Sets all missing fields of given denotation */
def complete(denot: SymDenotation)(using Context): Unit

/** Is this a completer for an explicit type tree */
def isNonInfering: Boolean = false

def apply(sym: Symbol): LazyType = this
def apply(module: TermSymbol, modcls: ClassSymbol): LazyType = this

Expand Down
36 changes: 19 additions & 17 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ class Namer { typer: Typer =>
if rhs.isEmpty || flags.is(Opaque) then flags |= Deferred
if flags.is(Param) then tree.rhs else analyzeRHS(tree.rhs)

def isNonInferingTree(tree: ValOrDefDef): Boolean =
!tree.tpt.isEmpty || tree.mods.isOneOf(TermParamOrAccessor)

// to complete a constructor, move one context further out -- this
// is the context enclosing the class. Note that the context in which a
// constructor is recorded and the context in which it is completed are
Expand All @@ -291,6 +294,7 @@ class Namer { typer: Typer =>

val completer = tree match
case tree: TypeDef => TypeDefCompleter(tree)(cctx)
case tree: ValOrDefDef if isNonInferingTree(tree) => NonInferingCompleter(tree)(cctx)
case _ => Completer(tree)(cctx)
val info = adjustIfModule(completer, tree)
createOrRefine[Symbol](tree, name, flags, ctx.owner, _ => info,
Expand Down Expand Up @@ -1736,6 +1740,10 @@ class Namer { typer: Typer =>
}
}

class NonInferingCompleter(original: ValOrDefDef)(ictx: Context) extends Completer(original)(ictx) {
override def isNonInfering: Boolean = true
}

/** Possible actions to perform when deciding on a forwarder for a member */
private enum CanForward:
case Yes
Expand Down Expand Up @@ -1994,14 +2002,13 @@ class Namer { typer: Typer =>
def needsTracked(sym: Symbol, param: ValDef)(using Context) =
!sym.is(Tracked)
&& sym.isTerm
&& sym.maybeOwner.isPrimaryConstructor
// && !sym.flags.is(Synthetic)
// && !sym.maybeOwner.flags.is(Synthetic)
&& !sym.maybeOwner.maybeOwner.flags.is(Synthetic)
&& (
isContextBoundWitnessWithAbstractMembers(sym, param)
|| isReferencedInPublicSignatures(sym)
|| isPassedToTrackedParentParameter(sym, param)
|| sym.maybeOwner.isPrimaryConstructor
// && !sym.flags.is(Synthetic)
// && !sym.maybeOwner.flags.is(Synthetic)
// && !sym.maybeOwner.maybeOwner.flags.is(Synthetic)
&& isReferencedInPublicSignatures(sym)
)

/** Under x.modularity, we add `tracked` to context bound witnesses
Expand All @@ -2011,6 +2018,11 @@ class Namer { typer: Typer =>
param.hasAttachment(ContextBoundParam)
&& sym.info.memberNames(abstractTypeNameFilter).nonEmpty

extension (sym: Symbol)
def infoWithForceNonInferingCompleter(using Context): Type = sym.infoOrCompleter match
case tpe: LazyType if tpe.isNonInfering => sym.info
case info => info

/** Under x.modularity, we add `tracked` to term parameters whose types are referenced
* in public signatures of the defining class
*/
Expand All @@ -2022,20 +2034,10 @@ class Namer { typer: Typer =>
case info: ClassInfo =>
info.decls.filter(_.isTerm).filter(_.isPublic)
.filter(_ != sym.maybeOwner)
.exists(d => tpeContainsSymbolRef(d.info, accessorSyms))
.exists(d => tpeContainsSymbolRef(d.infoWithForceNonInferingCompleter, accessorSyms))
case _ => false
checkOwnerMemberSignatures(owner)

def isPassedToTrackedParentParameter(sym: Symbol, param: ValDef)(using Context): Boolean =
// TODO(kπ) Add tracked if the param is passed as a tracked arg in parent. Can we touch the inheritance terms?
val owner = sym.maybeOwner.maybeOwner
val accessorSyms = maybeParamAccessors(owner, sym)
owner.infoOrCompleter match
// case info: ClassInfo =>
// info.parents.foreach(println)
// info.parents.exists(tpeContainsSymbolRef(_, accessorSyms))
case _ => false

private def namedTypeWithPrefixContainsSymbolRef(tpe: Type, syms: List[Symbol])(using Context): Boolean = tpe match
case tpe: NamedType => tpe.prefix.exists && tpeContainsSymbolRef(tpe.prefix, syms)
case _ => false
Expand Down

0 comments on commit a6d3770

Please sign in to comment.