Skip to content

Commit 325262f

Browse files
committed
Use a general criterion for when to refer to symbols symbolically
Also - rename Fresh flag to NonMember - update criterion for phases where refs are symbolic. This used to be just before erasure (at resolveSuper) but then other phases were inserted after resolveSuper and the test became outdated. It's more robust now.
1 parent c0dc919 commit 325262f

File tree

6 files changed

+38
-19
lines changed

6 files changed

+38
-19
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,8 +359,8 @@ object Flags {
359359

360360
// Flags following this one are not pickled
361361

362-
/** Symbol always defines a fresh named type */
363-
final val Fresh = commonFlag(45, "<fresh>")
362+
/** Symbol is not a member of its owner */
363+
final val NonMember = commonFlag(45, "<non-member>")
364364

365365
/** Denotation is in train of being loaded and completed, used to catch cyclic dependencies */
366366
final val Touched = commonFlag(48, "<touched>")
@@ -446,7 +446,7 @@ object Flags {
446446
Module | Package | Deferred | MethodOrHKCommon | Param | ParamAccessor.toCommonFlags |
447447
Scala2ExistentialCommon | Mutable.toCommonFlags | Touched | JavaStatic |
448448
CovariantOrOuter | ContravariantOrLabel | CaseAccessor.toCommonFlags |
449-
Fresh | Erroneous | ImplicitCommon | Permanent | Synthetic |
449+
NonMember | Erroneous | ImplicitCommon | Permanent | Synthetic |
450450
SuperAccessorOrScala2x | Inline
451451

452452
/** Flags guaranteed to be set upon symbol creation, or, if symbol is a top-level

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ object Phases {
359359
myErasedTypes = prev.getClass == classOf[Erasure] || prev.erasedTypes
360360
myFlatClasses = prev.getClass == classOf[Flatten] || prev.flatClasses
361361
myRefChecked = prev.getClass == classOf[RefChecks] || prev.refChecked
362-
mySymbolicRefs = prev.getClass == classOf[ResolveSuper] || prev.symbolicRefs
362+
mySymbolicRefs = getClass == classOf[Erasure] || prev.symbolicRefs
363363
myLabelsReordered = prev.getClass == classOf[LabelDefs] || prev.labelsReordered
364364
mySameMembersStartId = if (changesMembers) id else prev.sameMembersStartId
365365
mySameParentsStartId = if (changesParents) id else prev.sameMembersStartId

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -245,11 +245,15 @@ trait Symbols { this: Context =>
245245
* would be `fld2`. There is a single local dummy per template.
246246
*/
247247
def newLocalDummy(cls: Symbol, coord: Coord = NoCoord) =
248-
newSymbol(cls, nme.localDummyName(cls), EmptyFlags, NoType)
248+
newSymbol(cls, nme.localDummyName(cls), NonMember, NoType)
249249

250250
/** Create an import symbol pointing back to given qualifier `expr`. */
251-
def newImportSymbol(owner: Symbol, expr: Tree, coord: Coord = NoCoord) =
252-
newSymbol(owner, nme.IMPORT, EmptyFlags, ImportType(expr), coord = coord)
251+
def newImportSymbol(owner: Symbol, expr: Tree, coord: Coord = NoCoord): TermSymbol =
252+
newImportSymbol(owner, ImportType(expr), coord = coord)
253+
254+
/** Create an import symbol with given `info`. */
255+
def newImportSymbol(owner: Symbol, info: Type, coord: Coord): TermSymbol =
256+
newSymbol(owner, nme.IMPORT, Synthetic | NonMember, info, coord = coord)
253257

254258
/** Create a class constructor symbol for given class `cls`. */
255259
def newConstructor(cls: ClassSymbol, flags: FlagSet, paramNames: List[TermName], paramTypes: List[Type], privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) =
@@ -343,7 +347,7 @@ trait Symbols { this: Context =>
343347
copy.denot = odenot.copySymDenotation(
344348
symbol = copy,
345349
owner = ttmap1.mapOwner(odenot.owner),
346-
initFlags = odenot.flags &~ Touched | Fresh,
350+
initFlags = odenot.flags &~ Touched,
347351
info = completer,
348352
privateWithin = ttmap1.mapOwner(odenot.privateWithin), // since this refers to outer symbols, need not include copies (from->to) in ownermap here.
349353
annotations = odenot.annotations)
@@ -436,8 +440,10 @@ object Symbols {
436440
final def asType(implicit ctx: Context): TypeSymbol = { assert(isType, s"isType called on not-a-Type $this"); asInstanceOf[TypeSymbol] }
437441
final def asClass: ClassSymbol = asInstanceOf[ClassSymbol]
438442

439-
final def isFresh(implicit ctx: Context) =
440-
lastDenot != null && (lastDenot is Fresh)
443+
final def isReferencedSymbolically(implicit ctx: Context) = {
444+
val sym = lastDenot
445+
sym != null && ((sym is NonMember) || sym.isTerm && ctx.phase.symbolicRefs)
446+
}
441447

442448
/** Special cased here, because it may be used on naked symbols in substituters */
443449
final def isStatic(implicit ctx: Context): Boolean =

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,8 +2054,6 @@ object Types {
20542054

20552055
object TermRef {
20562056

2057-
private def symbolicRefs(implicit ctx: Context) = ctx.phase.symbolicRefs
2058-
20592057
/** Create term ref with given name, without specifying a signature.
20602058
* Its meaning is the (potentially multi-) denotation of the member(s)
20612059
* of prefix with given name.
@@ -2076,7 +2074,7 @@ object Types {
20762074
* signature, if denotation is not yet completed.
20772075
*/
20782076
def apply(prefix: Type, name: TermName, denot: Denotation)(implicit ctx: Context): TermRef = {
2079-
if ((prefix eq NoPrefix) || denot.symbol.isFresh || symbolicRefs)
2077+
if ((prefix eq NoPrefix) || denot.symbol.isReferencedSymbolically)
20802078
apply(prefix, denot.symbol.asTerm)
20812079
else denot match {
20822080
case denot: SymDenotation if denot.isCompleted => withSig(prefix, name, denot.signature)
@@ -2098,7 +2096,7 @@ object Types {
20982096
* (2) The name in the term ref need not be the same as the name of the Symbol.
20992097
*/
21002098
def withSymAndName(prefix: Type, sym: TermSymbol, name: TermName)(implicit ctx: Context): TermRef =
2101-
if ((prefix eq NoPrefix) || sym.isFresh || symbolicRefs)
2099+
if ((prefix eq NoPrefix) || sym.isReferencedSymbolically)
21022100
withFixedSym(prefix, name, sym)
21032101
else if (sym.defRunId != NoRunId && sym.isCompleted)
21042102
withSig(prefix, name, sym.signature) withSym (sym, sym.signature)
@@ -2113,7 +2111,7 @@ object Types {
21132111
* (which must be completed).
21142112
*/
21152113
def withSig(prefix: Type, sym: TermSymbol)(implicit ctx: Context): TermRef =
2116-
if ((prefix eq NoPrefix) || sym.isFresh || symbolicRefs) withFixedSym(prefix, sym.name, sym)
2114+
if ((prefix eq NoPrefix) || sym.isReferencedSymbolically) withFixedSym(prefix, sym.name, sym)
21172115
else withSig(prefix, sym.name, sym.signature).withSym(sym, sym.signature)
21182116

21192117
/** Create a term ref with given prefix, name and signature */
@@ -2122,7 +2120,7 @@ object Types {
21222120

21232121
/** Create a term ref with given prefix, name, signature, and initial denotation */
21242122
def withSigAndDenot(prefix: Type, name: TermName, sig: Signature, denot: Denotation)(implicit ctx: Context): TermRef = {
2125-
if ((prefix eq NoPrefix) || denot.symbol.isFresh || symbolicRefs)
2123+
if ((prefix eq NoPrefix) || denot.symbol.isReferencedSymbolically)
21262124
withFixedSym(prefix, denot.symbol.asTerm.name, denot.symbol.asTerm)
21272125
else
21282126
withSig(prefix, name, sig)
@@ -2151,12 +2149,12 @@ object Types {
21512149
* (2) The name in the type ref need not be the same as the name of the Symbol.
21522150
*/
21532151
def withSymAndName(prefix: Type, sym: TypeSymbol, name: TypeName)(implicit ctx: Context): TypeRef =
2154-
if ((prefix eq NoPrefix) || sym.isFresh) withFixedSym(prefix, name, sym)
2152+
if ((prefix eq NoPrefix) || sym.isReferencedSymbolically) withFixedSym(prefix, name, sym)
21552153
else apply(prefix, name).withSym(sym, Signature.NotAMethod)
21562154

21572155
/** Create a type ref with given name and initial denotation */
21582156
def apply(prefix: Type, name: TypeName, denot: Denotation)(implicit ctx: Context): TypeRef = {
2159-
if ((prefix eq NoPrefix) || denot.symbol.isFresh) apply(prefix, denot.symbol.asType)
2157+
if ((prefix eq NoPrefix) || denot.symbol.isReferencedSymbolically) apply(prefix, denot.symbol.asType)
21602158
else apply(prefix, name)
21612159
} withDenot denot
21622160
}

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi
983983
UnApply(fn, implicitArgs, argPats, patType)
984984
case REFINEDtpt =>
985985
val refineCls = ctx.newCompleteClassSymbol(
986-
ctx.owner, tpnme.REFINE_CLASS, Fresh, parents = Nil)
986+
ctx.owner, tpnme.REFINE_CLASS, NonMember, parents = Nil)
987987
typeAtAddr(start) = refineCls.typeRef
988988
val parent = readTpt()
989989
val refinements = readStats(refineCls, end)(localContext(refineCls))
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
### Subtyping Rules
3+
4+
An intesection type `A & B` is a subtype of its constituents `A`, and `B`
5+
6+
A & B <: A
7+
A & B <: B
8+
9+
T <: A & B provided T <: A and T <: B
10+
11+
If `C` is a covariant type constructor,
12+
13+
C[A & B] =:= C[A] & C[B]
14+
C[A & B] <: C[B]
15+

0 commit comments

Comments
 (0)