Skip to content

Commit 8de1265

Browse files
committed
Use selectionType directly in typedSelect
1 parent 50a302c commit 8de1265

File tree

2 files changed

+37
-87
lines changed

2 files changed

+37
-87
lines changed

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

Lines changed: 24 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -84,89 +84,16 @@ trait TypeAssigner {
8484
// it could be that we found an inaccessible private member, but there is
8585
// an inherited non-private member with the same name and signature.
8686
val d2 = pre.nonPrivateMember(name).accessibleFrom(pre, superAccess)
87-
if reallyExists(d2) then
88-
postProcess(d2)
89-
else if (pre.derivesFrom(defn.DynamicClass) && name.isTermName)
90-
TryDynamicCallType // TODO: drop
91-
else
92-
NoType
87+
if reallyExists(d2) then postProcess(d2)
88+
else NoType
9389
case tpe => tpe
9490

9591
def ensureAccessible(tpe: Type, superAccess: Boolean, pos: SrcPos)(using Context): Type =
9692
val tpe1 = accessibleType(tpe, superAccess)
9793
if tpe1.exists then tpe1
9894
else tpe match
99-
case tpe: NamedType =>
100-
val pre = tpe.prefix
101-
val name = tpe.name
102-
val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists)
103-
var packageAccess = false
104-
val whatCanNot = alts match {
105-
case Nil =>
106-
em"$name cannot"
107-
case sym :: Nil =>
108-
em"${if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated} cannot"
109-
case _ =>
110-
em"none of the overloaded alternatives named $name can"
111-
}
112-
val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else ""
113-
val whyNot = new StringBuffer
114-
alts.foreach(_.isAccessibleFrom(pre, superAccess, whyNot))
115-
if tpe.isError then tpe
116-
else errorType(ex"$whatCanNot be accessed as a member of $pre$where.$whyNot", pos)
117-
case _ =>
118-
tpe
119-
120-
/** If `tpe` is a named type, check that its denotation is accessible in the
121-
* current context. Return the type with those alternatives as denotations
122-
* which are accessible.
123-
*
124-
* Also performs the following normalizations on the type `tpe`.
125-
* (1) parameter accessors are always dereferenced.
126-
* (2) if the owner of the denotation is a package object, it is assured
127-
* that the package object shows up as the prefix.
128-
* (3) in Java compilation units, `Object` is replaced by `defn.FromJavaObjectType`
129-
*/
130-
def ensureAccessibleOLD(tpe: Type, superAccess: Boolean, pos: SrcPos)(using Context): Type = {
131-
def test(tpe: Type, firstTry: Boolean): Type = tpe match {
132-
case tpe: NamedType =>
133-
val pre = tpe.prefix
134-
val name = tpe.name
135-
val d = tpe.denot.accessibleFrom(pre, superAccess)
136-
if !d.exists then
137-
// it could be that we found an inaccessible private member, but there is
138-
// an inherited non-private member with the same name and signature.
139-
val d2 = pre.nonPrivateMember(name)
140-
if (reallyExists(d2) && firstTry)
141-
test(NamedType(pre, name, d2), false)
142-
else if (pre.derivesFrom(defn.DynamicClass) && name.isTermName)
143-
TryDynamicCallType
144-
else {
145-
val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists)
146-
var packageAccess = false
147-
val whatCanNot = alts match {
148-
case Nil =>
149-
em"$name cannot"
150-
case sym :: Nil =>
151-
em"${if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated} cannot"
152-
case _ =>
153-
em"none of the overloaded alternatives named $name can"
154-
}
155-
val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else ""
156-
val whyNot = new StringBuffer
157-
alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot))
158-
if (tpe.isError) tpe
159-
else errorType(ex"$whatCanNot be accessed as a member of $pre$where.$whyNot", pos)
160-
}
161-
else if ctx.isJava && tpe.isAnyRef then
162-
defn.FromJavaObjectType
163-
else
164-
TypeOps.makePackageObjPrefixExplicit(tpe withDenot d)
165-
case _ =>
166-
tpe
167-
}
168-
test(tpe, true)
169-
}
95+
case tpe: NamedType => inaccessibleErrorType(tpe, superAccess, pos)
96+
case NoType => tpe
17097

17198
/** Return a potentially skolemized version of `qualTpe` to be used
17299
* as a prefix when selecting `name`.
@@ -215,7 +142,7 @@ trait TypeAssigner {
215142

216143
def importSuggestionAddendum(pt: Type)(using Context): String = ""
217144

218-
def notAMember(tree: untpd.Select, qual: Tree)(using Context): ErrorType =
145+
def notAMemberErrorType(tree: untpd.Select, qual: Tree)(using Context): ErrorType =
219146
val qualType = qual.tpe.widenIfUnstable
220147
def kind = if tree.isType then "type" else "value"
221148
def addendum = err.selectErrorAddendum(tree, qual, qualType, importSuggestionAddendum)
@@ -224,6 +151,24 @@ trait TypeAssigner {
224151
else NotAMember(qualType, tree.name, kind, addendum)
225152
errorType(msg, tree.srcPos)
226153

154+
def inaccessibleErrorType(tpe: NamedType, superAccess: Boolean, pos: SrcPos)(using Context): Type =
155+
val pre = tpe.prefix
156+
val name = tpe.name
157+
val alts = tpe.denot.alternatives.map(_.symbol).filter(_.exists)
158+
var packageAccess = false
159+
val whatCanNot = alts match
160+
case Nil =>
161+
em"$name cannot"
162+
case sym :: Nil =>
163+
em"${if (sym.owner == pre.typeSymbol) sym.show else sym.showLocated} cannot"
164+
case _ =>
165+
em"none of the overloaded alternatives named $name can"
166+
val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else ""
167+
val whyNot = new StringBuffer
168+
alts.foreach(_.isAccessibleFrom(pre, superAccess, whyNot))
169+
if tpe.isError then tpe
170+
else errorType(ex"$whatCanNot be accessed as a member of $pre$where.$whyNot", pos)
171+
227172
/** The type of the selection in `tree`, where `qual1` is the typed qualifier part.
228173
* The selection type is additionally checked for accessibility.
229174
*/
@@ -243,7 +188,7 @@ trait TypeAssigner {
243188
ConstFold.Select(tree.withType(tp))
244189

245190
def assignType(tree: untpd.Select, qual: Tree)(using Context): Select =
246-
val ownType = accessibleSelectionType(tree, qual).orElse(notAMember(tree, qual))
191+
val ownType = accessibleSelectionType(tree, qual).orElse(notAMemberErrorType(tree, qual))
247192
assignType(tree, ownType)
248193

249194
/** Normalize type T appearing in a new T by following eta expansions to

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

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -555,14 +555,14 @@ class Typer extends Namer
555555
val selName = tree0.name
556556
val tree = cpy.Select(tree0)(qual, selName)
557557
def finalize(tp: Type) = assignType(tree, tp)
558-
val ownType = accessibleSelectionType(tree, qual)
559-
if ownType.exists then
560-
val select = assignType(tree, ownType)
561-
val select1 = toNotNullTermRef(select, pt)
562-
558+
val superAccess = qual.isInstanceOf[Super]
559+
val rawType = selectionType(tree, qual)
560+
val checkedType = accessibleType(rawType, superAccess)
561+
if checkedType.exists then
562+
val select = toNotNullTermRef(assignType(tree, checkedType), pt)
563563
if selName.isTypeName then checkStable(qual.tpe, qual.srcPos, "type prefix")
564-
checkStableIdentPattern(select1, pt)
565-
ConstFold(select1)
564+
checkStableIdentPattern(select, pt)
565+
ConstFold(select)
566566
else if couldInstantiateTypeVar(qual.tpe.widen) then
567567
// try again with more defined qualifier type
568568
typedSelect(tree, pt, qual)
@@ -572,7 +572,12 @@ class Typer extends Namer
572572
if pt.isInstanceOf[FunOrPolyProto] || pt == AssignProto then finalize(TryDynamicCallType)
573573
else typedDynamicSelect(tree0, Nil, pt)
574574
else
575-
finalize(notAMember(tree, qual))
575+
finalize(
576+
rawType match
577+
case rawType: NamedType =>
578+
inaccessibleErrorType(rawType, superAccess, tree.srcPos)
579+
case _ =>
580+
notAMemberErrorType(tree, qual))
576581
end typedSelect
577582

578583
def typedSelect(tree: untpd.Select, pt: Type)(using Context): Tree = {

0 commit comments

Comments
 (0)