Skip to content

Commit 52c07c1

Browse files
committed
More fixes to inline accessors
1. Fix inline accessors for static methods 2. Disable variance checks for inline accessors
1 parent e66ea81 commit 52c07c1

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed

compiler/src/dotty/tools/dotc/transform/AccessProxies.scala

+22-14
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ abstract class AccessProxies {
4747
if (passReceiverAsArg(accessor.name))
4848
(argss.head.head.select(accessed), tps.takeRight(numTypeParams), argss.tail)
4949
else
50-
(ref(TermRef(cls.thisType, accessed)), tps, argss)
50+
(if (accessed.isStatic) ref(accessed) else ref(TermRef(cls.thisType, accessed)),
51+
tps, argss)
5152
val rhs =
5253
if (accessor.name.isSetterName &&
5354
forwardedArgss.nonEmpty && forwardedArgss.head.nonEmpty) // defensive conditions
@@ -70,6 +71,11 @@ abstract class AccessProxies {
7071
def accessorNameKind: ClassifiedNameKind
7172
def needsAccessor(sym: Symbol)(implicit ctx: Context): Boolean
7273

74+
def ifNoHost(reference: RefTree)(implicit ctx: Context): Tree = {
75+
assert(false, "no host found for $reference with ${reference.symbol.showLocated} from ${ctx.owner}")
76+
reference
77+
}
78+
7379
/** A fresh accessor symbol */
7480
private def newAccessorSymbol(owner: Symbol, name: TermName, info: Type, pos: Position)(implicit ctx: Context): TermSymbol = {
7581
val sym = ctx.newSymbol(owner, name, Synthetic | Method, info, coord = pos).entered
@@ -125,18 +131,14 @@ abstract class AccessProxies {
125131
def useAccessor(reference: RefTree)(implicit ctx: Context): Tree = {
126132
val accessed = reference.symbol.asTerm
127133
var accessorClass = hostForAccessorOf(accessed: Symbol)
128-
if (!accessorClass.exists) {
129-
val curCls = ctx.owner.enclosingClass
130-
transforms.println(i"${curCls.ownersIterator.toList}%, %")
131-
ctx.error(i"illegal access to protected ${accessed.showLocated} from $curCls",
132-
reference.pos)
133-
accessorClass = curCls
134+
if (accessorClass.exists) {
135+
val accessorName = accessorNameKind(accessed.name)
136+
val accessorInfo =
137+
accessed.info.ensureMethodic.asSeenFrom(accessorClass.thisType, accessed.owner)
138+
val accessor = accessorSymbol(accessorClass, accessorName, accessorInfo, accessed)
139+
rewire(reference, accessor)
134140
}
135-
val accessorName = accessorNameKind(accessed.name)
136-
val accessorInfo =
137-
accessed.info.ensureMethodic.asSeenFrom(accessorClass.thisType, accessed.owner)
138-
val accessor = accessorSymbol(accessorClass, accessorName, accessorInfo, accessed)
139-
rewire(reference, accessor)
141+
else ifNoHost(reference)
140142
}
141143

142144
/** Replace tree with a reference to an accessor if needed */
@@ -156,6 +158,12 @@ object AccessProxies {
156158
/** Where an accessor for the `accessed` symbol should be placed.
157159
* This is the closest enclosing class that has `accessed` as a member.
158160
*/
159-
def hostForAccessorOf(accessed: Symbol)(implicit ctx: Context): Symbol =
160-
ctx.owner.ownersIterator.findSymbol(_.derivesFrom(accessed.owner))
161+
def hostForAccessorOf(accessed: Symbol)(implicit ctx: Context): Symbol = {
162+
def recur(cls: Symbol): Symbol =
163+
if (!cls.exists) NoSymbol
164+
else if (cls.derivesFrom(accessed.owner)) cls
165+
else if (cls.companionModule.moduleClass == accessed.owner) accessed.owner
166+
else recur(cls.owner)
167+
recur(ctx.owner)
168+
}
161169
}

compiler/src/dotty/tools/dotc/transform/ProtectedAccessors.scala

+9
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import core.Flags._
88
import core.Decorators._
99
import MegaPhase.MiniPhase
1010
import ast.Trees._
11+
import config.Printers.transforms
1112

1213
/** Add accessors for all protected accesses. An accessor is needed if
1314
* according to the rules of the JVM a protected class member is not accesissible
@@ -56,6 +57,14 @@ class ProtectedAccessors extends MiniPhase {
5657
val insert = new Insert {
5758
def accessorNameKind = ProtectedAccessorName
5859
def needsAccessor(sym: Symbol)(implicit ctx: Context) = ProtectedAccessors.needsAccessor(sym)
60+
61+
override def ifNoHost(reference: RefTree)(implicit ctx: Context): Tree = {
62+
val curCls = ctx.owner.enclosingClass
63+
transforms.println(i"${curCls.ownersIterator.toList}%, %")
64+
ctx.error(i"illegal access to protected ${reference.symbol.showLocated} from $curCls",
65+
reference.pos)
66+
reference
67+
}
5968
}
6069
}
6170

compiler/src/dotty/tools/dotc/typer/Inliner.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ object Inliner {
8181
ctx.error("Implementation restriction: cannot use private constructors in inline methods", tree.pos)
8282
tree // TODO: create a proper accessor for the private constructor
8383
}
84-
else if (AccessProxies.hostForAccessorOf(tree.symbol).exists) useAccessor(tree)
85-
else tree
84+
else useAccessor(tree)
8685
case _ =>
8786
tree
8887
}
88+
override def ifNoHost(reference: RefTree)(implicit ctx: Context): Tree = reference
8989
}
9090

9191
/** Fallback approach if the direct approach does not work: Place the accessor method
@@ -124,7 +124,7 @@ object Inliner {
124124
if needsAccessor(tree.symbol) && tree.isTerm && !tree.symbol.isConstructor =>
125125
val (refPart, targs, argss) = decomposeCall(tree)
126126
val qual = qualifier(refPart)
127-
inlining.println(i"adding receiver passing inline accessor for $tree -> (${qual.tpe}, $refPart: ${refPart.getClass}, [$targs%, %], ($argss%, %))")
127+
println(i"adding receiver passing inline accessor for $tree/$refPart -> (${qual.tpe}, $refPart: ${refPart.getClass}, [$targs%, %], ($argss%, %))")
128128

129129
// Need to dealias in order to cagtch all possible references to abstracted over types in
130130
// substitutions
@@ -142,7 +142,7 @@ object Inliner {
142142
def addQualType(tp: Type): Type = tp match {
143143
case tp: PolyType => tp.derivedLambdaType(tp.paramNames, tp.paramInfos, addQualType(tp.resultType))
144144
case tp: ExprType => addQualType(tp.resultType)
145-
case tp => MethodType(qualType :: Nil, tp)
145+
case tp => MethodType(qualType.simplified :: Nil, tp)
146146
}
147147

148148
// Abstract accessed type over local refs

compiler/src/dotty/tools/dotc/typer/VarianceChecker.scala

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import core._
66
import Types._, Contexts._, Flags._, Symbols._, Annotations._, Trees._, NameOps._
77
import Decorators._
88
import Variances._
9+
import NameKinds._
910
import util.Positions._
1011
import rewrite.Rewrites.patch
1112
import config.Printers.variances
@@ -134,6 +135,7 @@ class VarianceChecker()(implicit ctx: Context) {
134135
def skip =
135136
!sym.exists ||
136137
sym.is(PrivateLocal) ||
138+
sym.name.is(InlineAccessorName) || // TODO: should we exclude all synthetic members?
137139
sym.is(TypeParam) && sym.owner.isClass // already taken care of in primary constructor of class
138140
tree match {
139141
case defn: MemberDef if skip =>

0 commit comments

Comments
 (0)