Skip to content

Commit b319440

Browse files
authored
Merge pull request #2080 from dotty-staging/fix#-2066
Fix #2066: Don't qualify private members in SelectionProto's...
2 parents e5e2f82 + 3261734 commit b319440

File tree

7 files changed

+72
-16
lines changed

7 files changed

+72
-16
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,10 @@ object SymDenotations {
957957
else
958958
companionNamed(name)(ctx.outersIterator.dropWhile(_.scope eq ctx.scope).next)
959959

960+
/** Is this symbol the same or a linked class of `sym`? */
961+
final def isLinkedWith(sym: Symbol)(implicit ctx: Context): Boolean =
962+
(symbol eq sym) || (linkedClass eq sym)
963+
960964
/** If this is a class, the module class of its companion object.
961965
* If this is a module class, its companion class.
962966
* NoSymbol otherwise.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,13 +215,13 @@ object TypeErasure {
215215
}
216216

217217
/** The erased least upper bound is computed as follows
218-
* - if both argument are arrays of objects, an array of the lub of the element types
218+
* - if both argument are arrays of objects, an array of the erased lub of the element types
219219
* - if both arguments are arrays of same primitives, an array of this primitive
220220
* - if one argument is array of primitives and the other is array of objects, Object
221221
* - if one argument is an array, Object
222222
* - otherwise a common superclass or trait S of the argument classes, with the
223223
* following two properties:
224-
* S is minimal: no other common superclass or trait derives from S]
224+
* S is minimal: no other common superclass or trait derives from S
225225
* S is last : in the linearization of the first argument type `tp1`
226226
* there are no minimal common superclasses or traits that
227227
* come after S.

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,15 +516,21 @@ trait Implicits { self: Typer =>
516516
|| (from.tpe isRef defn.NullClass)
517517
|| !(ctx.mode is Mode.ImplicitsEnabled)
518518
|| (from.tpe eq NoPrefix)) NoImplicitMatches
519-
else
520-
try inferImplicit(to.stripTypeVar.widenExpr, from, from.pos)
519+
else {
520+
def adjust(to: Type) = to.stripTypeVar.widenExpr match {
521+
case SelectionProto(name, memberProto, compat, true) =>
522+
SelectionProto(name, memberProto, compat, privateOK = false)
523+
case tp => tp
524+
}
525+
try inferImplicit(adjust(to), from, from.pos)
521526
catch {
522527
case ex: AssertionError =>
523528
implicits.println(s"view $from ==> $to")
524529
implicits.println(ctx.typerState.constraint.show)
525530
implicits.println(TypeComparer.explained(implicit ctx => from.tpe <:< to))
526531
throw ex
527532
}
533+
}
528534
}
529535

530536
/** Find an implicit argument for parameter `formal`.

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

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ object ProtoTypes {
9090
*
9191
* [ ].name: proto
9292
*/
93-
abstract case class SelectionProto(val name: Name, val memberProto: Type, val compat: Compatibility)
93+
abstract case class SelectionProto(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean)
9494
extends CachedProxyType with ProtoType with ValueTypeOrProto {
9595

9696
override def isMatchedBy(tp1: Type)(implicit ctx: Context) = {
9797
name == nme.WILDCARD || {
98-
val mbr = tp1.member(name)
98+
val mbr = if (privateOK) tp1.member(name) else tp1.nonPrivateMember(name)
9999
def qualifies(m: SingleDenotation) =
100100
memberProto.isRef(defn.UnitClass) ||
101101
compat.normalizedCompatible(m.info, memberProto)
@@ -110,11 +110,11 @@ object ProtoTypes {
110110

111111
def derivedSelectionProto(name: Name, memberProto: Type, compat: Compatibility)(implicit ctx: Context) =
112112
if ((name eq this.name) && (memberProto eq this.memberProto) && (compat eq this.compat)) this
113-
else SelectionProto(name, memberProto, compat)
113+
else SelectionProto(name, memberProto, compat, privateOK)
114114

115115
override def equals(that: Any): Boolean = that match {
116116
case that: SelectionProto =>
117-
(name eq that.name) && (memberProto == that.memberProto) && (compat eq that.compat)
117+
(name eq that.name) && (memberProto == that.memberProto) && (compat eq that.compat) && (privateOK == that.privateOK)
118118
case _ =>
119119
false
120120
}
@@ -124,14 +124,18 @@ object ProtoTypes {
124124

125125
override def deepenProto(implicit ctx: Context) = derivedSelectionProto(name, memberProto.deepenProto, compat)
126126

127-
override def computeHash = addDelta(doHash(name, memberProto), if (compat eq NoViewsAllowed) 1 else 0)
127+
override def computeHash = {
128+
val delta = (if (compat eq NoViewsAllowed) 1 else 0) | (if (privateOK) 2 else 0)
129+
addDelta(doHash(name, memberProto), delta)
130+
}
128131
}
129132

130-
class CachedSelectionProto(name: Name, memberProto: Type, compat: Compatibility) extends SelectionProto(name, memberProto, compat)
133+
class CachedSelectionProto(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean)
134+
extends SelectionProto(name, memberProto, compat, privateOK)
131135

132136
object SelectionProto {
133-
def apply(name: Name, memberProto: Type, compat: Compatibility)(implicit ctx: Context): SelectionProto = {
134-
val selproto = new CachedSelectionProto(name, memberProto, compat)
137+
def apply(name: Name, memberProto: Type, compat: Compatibility, privateOK: Boolean)(implicit ctx: Context): SelectionProto = {
138+
val selproto = new CachedSelectionProto(name, memberProto, compat, privateOK)
135139
if (compat eq NoViewsAllowed) unique(selproto) else selproto
136140
}
137141
}
@@ -143,7 +147,7 @@ object ProtoTypes {
143147
if (name.isConstructorName) WildcardType
144148
else tp match {
145149
case tp: UnapplyFunProto => new UnapplySelectionProto(name)
146-
case tp => SelectionProto(name, IgnoredProto(tp), typer)
150+
case tp => SelectionProto(name, IgnoredProto(tp), typer, privateOK = true)
147151
}
148152

149153
/** A prototype for expressions [] that are in some unspecified selection operation
@@ -154,10 +158,10 @@ object ProtoTypes {
154158
* operation is further selection. In this case, the expression need not be a value.
155159
* @see checkValue
156160
*/
157-
@sharable object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType, NoViewsAllowed)
161+
@sharable object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType, NoViewsAllowed, true)
158162

159163
/** A prototype for selections in pattern constructors */
160-
class UnapplySelectionProto(name: Name) extends SelectionProto(name, WildcardType, NoViewsAllowed)
164+
class UnapplySelectionProto(name: Name) extends SelectionProto(name, WildcardType, NoViewsAllowed, true)
161165

162166
trait ApplyingProto extends ProtoType
163167

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
17191719
def tryInsertImplicitOnQualifier(tree: Tree, pt: Type)(implicit ctx: Context): Option[Tree] = ctx.traceIndented(i"try insert impl on qualifier $tree $pt") {
17201720
tree match {
17211721
case Select(qual, name) =>
1722-
val qualProto = SelectionProto(name, pt, NoViewsAllowed)
1722+
val qualProto = SelectionProto(name, pt, NoViewsAllowed, privateOK = false)
17231723
tryEither { implicit ctx =>
17241724
val qual1 = adaptInterpolated(qual, qualProto, EmptyTree)
17251725
if ((qual eq qual1) || ctx.reporter.hasErrors) None

tests/neg/i2066.scala

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
class Foo
2+
3+
object Test {
4+
implicit def two(x: Foo): Two = new Two(x)
5+
6+
class Two(x: Foo) {
7+
private def meth: Unit = {}
8+
9+
def test2(foo: Foo): Unit = {
10+
foo.meth // error
11+
}
12+
}
13+
}
14+
15+
16+
object Test2 {
17+
18+
class Two(x: Foo) {
19+
implicit def two(x: Foo): Two = new Two(x)
20+
21+
private def meth: Unit = {}
22+
23+
def test2(foo: Foo): Unit = {
24+
foo.meth // error
25+
}
26+
}
27+
}

tests/pos/i2066.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class Foo
2+
3+
object Test {
4+
implicit class One(x: Foo) {
5+
def meth: Unit = {}
6+
}
7+
8+
implicit class Two(x: Foo) {
9+
private def meth: Unit = {}
10+
}
11+
12+
def test(foo: Foo): Unit = {
13+
foo.meth
14+
}
15+
}

0 commit comments

Comments
 (0)