aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/ast/TreeTypeMap.scala3
-rw-r--r--src/dotty/tools/dotc/config/ScalaSettings.scala12
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala2
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreePickler.scala21
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala10
-rw-r--r--src/dotty/tools/dotc/parsing/Tokens.scala4
-rw-r--r--src/dotty/tools/dotc/transform/Constructors.scala14
-rw-r--r--src/dotty/tools/dotc/transform/ExpandPrivate.scala5
-rw-r--r--src/dotty/tools/dotc/transform/ExplicitOuter.scala41
-rw-r--r--src/dotty/tools/dotc/transform/FirstTransform.scala2
-rw-r--r--src/dotty/tools/dotc/transform/Mixin.scala36
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala9
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala5
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala55
14 files changed, 130 insertions, 89 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
index d714a3d21..a35fe2e8f 100644
--- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala
+++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala
@@ -82,7 +82,8 @@ final class TreeTypeMap(
constr = tmap.transformSub(constr),
parents = parents mapconserve transform,
self = tmap.transformSub(self),
- body = impl.body mapconserve tmap.transform
+ body = impl.body mapconserve
+ (tmap.transform(_)(ctx.withOwner(mapOwner(impl.symbol.owner))))
).withType(tmap.mapType(impl.tpe))
case tree1 =>
tree1.withType(mapType(tree1.tpe)) match {
diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala
index a10165be2..07a23fdb6 100644
--- a/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -108,10 +108,10 @@ class ScalaSettings extends Settings.SettingGroup {
val YcheckMods = BooleanSetting("-Ycheck-mods", "Check that symbols and their defining trees have modifiers in sync")
val YcheckTypedTrees = BooleanSetting("-YcheckTypedTrees", "Check all constructured typed trees for type correctness")
val Yshow = PhasesSetting("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after")
- val Xcloselim = BooleanSetting("-Yclosure-elim", "Perform closure elimination.")
+ val Ycloselim = BooleanSetting("-Yclosure-elim", "Perform closure elimination.")
val Ycompacttrees = BooleanSetting("-Ycompact-trees", "Use compact tree printer when displaying trees.")
val noCompletion = BooleanSetting("-Yno-completion", "Disable tab-completion in the REPL.")
- val Xdce = BooleanSetting("-Ydead-code", "Perform dead code elimination.")
+ val Ydce = BooleanSetting("-Ydead-code", "Perform dead code elimination.")
val debug = BooleanSetting("-Ydebug", "Increase the quantity of debugging output.")
val debugNames = BooleanSetting("-YdebugNames", "Show name-space indicators when printing names")
val debugTrace = BooleanSetting("-Ydebug-trace", "Trace core operations")
@@ -122,7 +122,7 @@ class ScalaSettings extends Settings.SettingGroup {
val inline = BooleanSetting("-Yinline", "Perform inlining when possible.")
val inlineHandlers = BooleanSetting("-Yinline-handlers", "Perform exception handler inlining when possible.")
val YinlinerWarnings = BooleanSetting("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)")
- val Xlinearizer = ChoiceSetting("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
+ val Ylinearizer = ChoiceSetting("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
val log = PhasesSetting("-Ylog", "Log operations during")
val Ylogcp = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.")
val Ynogenericsig = BooleanSetting("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.")
@@ -130,9 +130,9 @@ class ScalaSettings extends Settings.SettingGroup {
val nopredef = BooleanSetting("-Yno-predef", "Compile without importing Predef.")
val noAdaptedArgs = BooleanSetting("-Yno-adapted-args", "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.")
val selfInAnnots = BooleanSetting("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.")
- val Xshowtrees = BooleanSetting("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs in formatted form.")
- val XshowtreesCompact = BooleanSetting("-Yshow-trees-compact", "(Requires -Xprint:) Print detailed ASTs in compact form.")
- val XshowtreesStringified = BooleanSetting("-Yshow-trees-stringified", "(Requires -Xprint:) Print stringifications along with detailed ASTs.")
+ val Yshowtrees = BooleanSetting("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs in formatted form.")
+ val YshowtreesCompact = BooleanSetting("-Yshow-trees-compact", "(Requires -Xprint:) Print detailed ASTs in compact form.")
+ val YshowtreesStringified = BooleanSetting("-Yshow-trees-stringified", "(Requires -Xprint:) Print stringifications along with detailed ASTs.")
val Yshowsyms = BooleanSetting("-Yshow-syms", "Print the AST symbol hierarchy after each phase.")
val Yshowsymkinds = BooleanSetting("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.")
val Yskip = PhasesSetting("-Yskip", "Skip")
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index ebf4c637a..f866621f2 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -448,7 +448,7 @@ object Flags {
final val FromStartFlags =
AccessFlags | Module | Package | Deferred | Final | MethodOrHKCommon | Param | ParamAccessor | Scala2ExistentialCommon |
InSuperCall | Touched | JavaStatic | CovariantOrOuter | ContravariantOrLabel | ExpandedName | AccessorOrSealed |
- CaseAccessorOrBaseTypeArg | Fresh | Frozen | Erroneous | ImplicitCommon | Permanent |
+ CaseAccessorOrBaseTypeArg | Fresh | Frozen | Erroneous | ImplicitCommon | Permanent | Synthetic |
LazyOrTrait | SuperAccessorOrScala2x | SelfNameOrImplClass
assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags)
diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index bb6c3cd2e..7f8e5cef3 100644
--- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -55,11 +55,22 @@ class TreePickler(pickler: TastyPickler) {
pickleName(TastyName.Signed(nameIndex(name), params.map(fullNameIndex), fullNameIndex(result)))
}
- private def pickleName(sym: Symbol)(implicit ctx: Context): Unit =
- if (sym is Flags.ExpandedName)
- pickleName(TastyName.Expanded(
- nameIndex(sym.name.expandedPrefix), nameIndex(sym.name.unexpandedName)))
- else pickleName(sym.name)
+ private def pickleName(sym: Symbol)(implicit ctx: Context): Unit = {
+ def encodeSuper(name: Name): TastyName.NameRef =
+ if (sym is Flags.SuperAccessor) {
+ val SuperAccessorName(n) = name
+ nameIndex(TastyName.SuperAccessor(nameIndex(n)))
+ }
+ else nameIndex(name)
+ val nameRef =
+ if (sym is Flags.ExpandedName)
+ nameIndex(
+ TastyName.Expanded(
+ nameIndex(sym.name.expandedPrefix),
+ encodeSuper(sym.name.unexpandedName)))
+ else encodeSuper(sym.name)
+ writeNat(nameRef.index)
+ }
private def pickleSymRef(sym: Symbol)(implicit ctx: Context) = symRefs.get(sym) match {
case Some(label) =>
diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 16caac02e..016aa41de 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -78,7 +78,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
case Shadowed(original) => toTermName(original).shadowedName
case Expanded(prefix, original) => toTermName(original).expandedName(toTermName(prefix))
case ModuleClass(original) => toTermName(original).moduleClassName.toTermName
- case SuperAccessor(accessed) => ???
+ case SuperAccessor(accessed) => toTermName(accessed).superName
case DefaultGetter(meth, num) => ???
}
@@ -378,9 +378,13 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) {
val rhsIsEmpty = noRhs(end)
if (!rhsIsEmpty) skipTree()
val (givenFlags, annots, privateWithin) = readModifiers(end)
- val expandedFlag = if (rawName.isInstanceOf[TastyName.Expanded]) ExpandedName else EmptyFlags
+ def nameFlags(tname: TastyName): FlagSet = tname match {
+ case TastyName.Expanded(_, original) => ExpandedName | nameFlags(tastyName(original))
+ case TastyName.SuperAccessor(_) => Flags.SuperAccessor
+ case _ => EmptyFlags
+ }
pickling.println(i"creating symbol $name at $start with flags $givenFlags")
- val flags = normalizeFlags(tag, givenFlags | expandedFlag, name, isAbstractType, rhsIsEmpty)
+ val flags = normalizeFlags(tag, givenFlags | nameFlags(rawName), name, isAbstractType, rhsIsEmpty)
def adjustIfModule(completer: LazyType) =
if (flags is Module) ctx.adjustModuleCompleter(completer, name) else completer
val sym =
diff --git a/src/dotty/tools/dotc/parsing/Tokens.scala b/src/dotty/tools/dotc/parsing/Tokens.scala
index 190226635..b490cd133 100644
--- a/src/dotty/tools/dotc/parsing/Tokens.scala
+++ b/src/dotty/tools/dotc/parsing/Tokens.scala
@@ -94,8 +94,8 @@ abstract class TokensCommon {
/** special symbols */
final val COMMA = 70; enter(COMMA, "','")
- final val SEMI = 71; enter(DOT, "'.'")
- final val DOT = 72; enter(SEMI, "';'")
+ final val SEMI = 71; enter(SEMI, "';'")
+ final val DOT = 72; enter(DOT, "'.'")
//final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
//final val NEWLINES = 79; enter(NEWLINES, "end of statement", "new lines")
diff --git a/src/dotty/tools/dotc/transform/Constructors.scala b/src/dotty/tools/dotc/transform/Constructors.scala
index b6ebd7d90..44638ce48 100644
--- a/src/dotty/tools/dotc/transform/Constructors.scala
+++ b/src/dotty/tools/dotc/transform/Constructors.scala
@@ -26,7 +26,7 @@ import collection.mutable
* - also moves private fields that are accessed only from constructor
* into the constructor if possible.
*/
-class Constructors extends MiniPhaseTransform with SymTransformer { thisTransform =>
+class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { thisTransform =>
import tpd._
override def phaseName: String = "constructors"
@@ -99,18 +99,6 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor
}
}
- /** Symbols that are owned by either <local dummy> or a class field move into the
- * primary constructor.
- */
- override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation = {
- def ownerBecomesConstructor(owner: Symbol): Boolean =
- (owner.isLocalDummy || owner.isTerm && !owner.is(MethodOrLazy)) &&
- owner.owner.isClass
- if (ownerBecomesConstructor(sym.owner))
- sym.copySymDenotation(owner = sym.owner.enclosingClass.primaryConstructor)
- else sym
- }
-
/** @return true if after ExplicitOuter, all references from this tree go via an
* outer link, so no parameter accessors need to be rewired to parameters
*/
diff --git a/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/src/dotty/tools/dotc/transform/ExpandPrivate.scala
index f44be3958..a6f203478 100644
--- a/src/dotty/tools/dotc/transform/ExpandPrivate.scala
+++ b/src/dotty/tools/dotc/transform/ExpandPrivate.scala
@@ -57,8 +57,11 @@ class ExpandPrivate extends MiniPhaseTransform with IdentityDenotTransformer { t
* static members of the companion class, we should tighten the condition below.
*/
private def ensurePrivateAccessible(d: SymDenotation)(implicit ctx: Context) =
- if (d.is(PrivateTerm) && d.owner != ctx.owner.enclosingClass)
+ if (d.is(PrivateTerm) && d.owner != ctx.owner.enclosingClass) {
+ assert(d.symbol.sourceFile == ctx.source.file,
+ i"private ${d.symbol.showLocated} in ${d.symbol.sourceFile} accessed from ${ctx.owner.showLocated} in ${ctx.source.file}")
d.ensureNotPrivate.installAfter(thisTransform)
+ }
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo) = {
ensurePrivateAccessible(tree.symbol)
diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala
index 90ce6eb01..7ec0739c1 100644
--- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala
+++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala
@@ -212,27 +212,34 @@ object ExplicitOuter {
/** Tree references an outer class of `cls` which is not a static owner.
*/
def referencesOuter(cls: Symbol, tree: Tree)(implicit ctx: Context): Boolean = {
- def isOuter(sym: Symbol) =
+ def isOuterSym(sym: Symbol) =
!sym.isStaticOwner && cls.isProperlyContainedIn(sym)
+ def isOuterRef(ref: Type): Boolean = ref match {
+ case ref: ThisType =>
+ isOuterSym(ref.cls)
+ case ref: TermRef =>
+ if (ref.prefix ne NoPrefix)
+ !ref.symbol.isStatic && isOuterRef(ref.prefix)
+ else if (ref.symbol is Hoistable)
+ // ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need
+ // an outer path then.
+ isOuterSym(ref.symbol.owner.enclosingClass)
+ else
+ // ref.symbol will get a proxy in immediately enclosing class. If this properly
+ // contains the current class, it needs an outer path.
+ ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner)
+ case _ => false
+ }
+ def hasOuterPrefix(tp: Type) = tp match {
+ case TypeRef(prefix, _) => isOuterRef(prefix)
+ case _ => false
+ }
tree match {
- case thisTree @ This(_) =>
- isOuter(thisTree.symbol)
- case id: Ident =>
- id.tpe match {
- case ref @ TermRef(NoPrefix, _) =>
- if (ref.symbol is Hoistable)
- // ref.symbol will be placed in enclosing class scope by LambdaLift, so it might need
- // an outer path then.
- isOuter(ref.symbol.owner.enclosingClass)
- else
- // ref.symbol will get a proxy in immediately enclosing class. If this properly
- // contains the current class, it needs an outer path.
- ctx.owner.enclosingClass.owner.enclosingClass.isContainedIn(ref.symbol.owner)
- case _ => false
- }
+ case _: This | _: Ident => isOuterRef(tree.tpe)
case nw: New =>
val newCls = nw.tpe.classSymbol
- isOuter(newCls.owner.enclosingClass) ||
+ isOuterSym(newCls.owner.enclosingClass) ||
+ hasOuterPrefix(nw.tpe) ||
newCls.owner.isTerm && cls.isProperlyContainedIn(newCls)
// newCls might get proxies for free variables. If current class is
// properly contained in newCls, it needs an outer path to newCls access the
diff --git a/src/dotty/tools/dotc/transform/FirstTransform.scala b/src/dotty/tools/dotc/transform/FirstTransform.scala
index 6b13d46b2..37ae1d94e 100644
--- a/src/dotty/tools/dotc/transform/FirstTransform.scala
+++ b/src/dotty/tools/dotc/transform/FirstTransform.scala
@@ -124,7 +124,7 @@ class FirstTransform extends MiniPhaseTransform with IdentityDenotTransformer wi
private def newCompanion(name: TermName, forClass: Symbol)(implicit ctx: Context) = {
val modul = ctx.newCompleteModuleSymbol(forClass.owner, name, Synthetic, Synthetic,
- defn.ObjectType :: Nil, Scopes.newScope)
+ defn.ObjectType :: Nil, Scopes.newScope, assocFile = forClass.asClass.assocFile)
val mc = modul.moduleClass
val mcComp = ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, forClass, mc)
diff --git a/src/dotty/tools/dotc/transform/Mixin.scala b/src/dotty/tools/dotc/transform/Mixin.scala
index 32b268fc7..b0d1e5c5f 100644
--- a/src/dotty/tools/dotc/transform/Mixin.scala
+++ b/src/dotty/tools/dotc/transform/Mixin.scala
@@ -98,8 +98,12 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[Erasure])
override def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation =
- if (sym.is(Accessor, butNot = Deferred | Lazy) && sym.owner.is(Trait))
- sym.copySymDenotation(initFlags = sym.flags &~ ParamAccessor | Deferred).ensureNotPrivate
+ if (sym.is(Accessor, butNot = Deferred) && sym.owner.is(Trait)) {
+ val sym1 =
+ if (sym is Lazy) sym
+ else sym.copySymDenotation(initFlags = sym.flags &~ ParamAccessor | Deferred)
+ sym1.ensureNotPrivate
+ }
else if (sym.isConstructor && sym.owner.is(Trait))
sym.copySymDenotation(
name = nme.TRAIT_CONSTRUCTOR,
@@ -108,17 +112,19 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
sym
private def initializer(sym: Symbol)(implicit ctx: Context): TermSymbol = {
- val initName = if(!sym.is(Lazy)) InitializerName(sym.name.asTermName) else sym.name.asTermName
- sym.owner.info.decl(initName).suchThat(_.is(Lazy) == sym.is(Lazy)).symbol
- .orElse(
- ctx.newSymbol(
- sym.owner,
- initName,
- Protected | Synthetic | Method,
- sym.info,
- coord = sym.symbol.coord).enteredAfter(thisTransform))
- .asTerm
- }
+ if (sym is Lazy) sym
+ else {
+ val initName = InitializerName(sym.name.asTermName)
+ sym.owner.info.decl(initName).symbol
+ .orElse(
+ ctx.newSymbol(
+ sym.owner,
+ initName,
+ Protected | Synthetic | Method,
+ sym.info,
+ coord = sym.symbol.coord).enteredAfter(thisTransform))
+ }
+ }.asTerm
override def transformTemplate(impl: Template)(implicit ctx: Context, info: TransformerInfo) = {
val cls = impl.symbol.owner.asClass
@@ -134,8 +140,8 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
val vsym = stat.symbol
val isym = initializer(vsym)
val rhs = Block(
- initBuf.toList.map(_.changeOwner(impl.symbol, isym)),
- stat.rhs.changeOwner(vsym, isym).wildcardToDefault)
+ initBuf.toList.map(_.changeOwnerAfter(impl.symbol, isym, thisTransform)),
+ stat.rhs.changeOwnerAfter(vsym, isym, thisTransform).wildcardToDefault)
initBuf.clear()
cpy.DefDef(stat)(rhs = EmptyTree) :: DefDef(isym, rhs) :: Nil
case stat: DefDef if stat.symbol.isSetter =>
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index ea5c28fb1..01f9f6317 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -131,8 +131,13 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
annot.derivedAnnotation(transformAnnot(annot.tree))
private def transformMemberDef(tree: MemberDef)(implicit ctx: Context): Unit = {
- tree.symbol.transformAnnotations(transformAnnot)
- Checking.checkNoPrivateLeaks(tree)
+ val sym = tree.symbol
+ sym.transformAnnotations(transformAnnot)
+ if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) {
+ val info1 = Checking.checkNoPrivateLeaks(sym, tree.pos)
+ if (info1 ne sym.info)
+ sym.copySymDenotation(info = info1).installAfter(thisTransformer)
+ }
}
private def transformSelect(tree: Select, targs: List[Tree])(implicit ctx: Context): Tree = {
diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala
index 150a632a1..a260963e9 100644
--- a/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -282,7 +282,10 @@ class TreeChecker extends Phase with SymTransformer {
val symbolsNotDefined = cls.classInfo.decls.toSet.filter(isNonMagicalMethod) -- impl.body.map(_.symbol) - constr.symbol
- assert(symbolsNotDefined.isEmpty, i" $cls tree does not define methods: $symbolsNotDefined")
+ assert(symbolsNotDefined.isEmpty,
+ i" $cls tree does not define methods: ${symbolsNotDefined.toList}%, %\n" +
+ i"expected: ${cls.classInfo.decls.toSet.filter(isNonMagicalMethod).toList}%, %\n" +
+ i"defined: ${impl.body.map(_.symbol)}%, %")
super.typedClassDef(cdef, cls)
}
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 0ca121925..9b1f756b7 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -327,40 +327,53 @@ object Checking {
* to a private type or value which is invisible at a point where `M` is still
* visible. As an exception, we allow references to type aliases if the underlying
* type of the alias is not a leak. So type aliases are transparent as far as
- * leak testing is concerned. See 997.scala for tests.
+ * leak testing is concerned.
+ * @return The `info` of `sym`, with problematic aliases expanded away.
+ * See i997.scala for tests, i1130.scala for a case where it matters that we
+ * transform leaky aliases away.
*/
- def checkNoPrivateLeaks(tree: MemberDef)(implicit ctx: Context): Unit = {
- type Errors = List[(String, Position)]
- val sym = tree.symbol
- val notPrivate = new TypeAccumulator[Errors] {
+ def checkNoPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type = {
+ class NotPrivate extends TypeMap {
+ type Errors = List[(String, Position)]
+ var errors: Errors = Nil
def accessBoundary(sym: Symbol): Symbol =
if (sym.is(Private)) sym.owner
else if (sym.privateWithin.exists) sym.privateWithin
else if (sym.is(Package)) sym
else accessBoundary(sym.owner)
- def apply(errors: Errors, tp: Type): Errors = tp match {
+ def apply(tp: Type): Type = tp match {
case tp: NamedType =>
- val errors1 =
+ val prevErrors = errors
+ var tp1 =
if (tp.symbol.is(Private) &&
- !accessBoundary(sym).isContainedIn(tp.symbol.owner)) {
- (d"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}", tree.pos) :: errors
- } else foldOver(errors, tp)
- if ((errors1 ne errors) && tp.info.isAlias) {
+ !accessBoundary(sym).isContainedIn(tp.symbol.owner)) {
+ errors = (d"non-private $sym refers to private ${tp.symbol}\n in its type signature ${sym.info}",
+ pos) :: errors
+ tp
+ }
+ else mapOver(tp)
+ if ((errors ne prevErrors) && tp.info.isAlias) {
// try to dealias to avoid a leak error
- val errors2 = apply(errors, tp.info.bounds.hi)
- if (errors2 eq errors) errors2
- else errors1
- } else errors1
+ val savedErrors = errors
+ errors = prevErrors
+ val tp2 = apply(tp.info.bounds.hi)
+ if (errors eq prevErrors) tp1 = tp2
+ else errors = savedErrors
+ }
+ tp1
case tp: ClassInfo =>
- (apply(errors, tp.prefix) /: tp.parentsWithArgs)(apply)
+ tp.derivedClassInfo(
+ prefix = apply(tp.prefix),
+ classParents = tp.parentsWithArgs.map(p =>
+ apply(p).underlyingClassRef(refinementOK = false).asInstanceOf[TypeRef]))
case _ =>
- foldOver(errors, tp)
+ mapOver(tp)
}
}
- if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) {
- val errors = notPrivate(Nil, sym.info)
- errors.foreach { case (msg, pos) => ctx.errorOrMigrationWarning(msg, pos) }
- }
+ val notPrivate = new NotPrivate
+ val info = notPrivate(sym.info)
+ notPrivate.errors.foreach { case (msg, pos) => ctx.errorOrMigrationWarning(msg, pos) }
+ info
}
}