Skip to content

Commit b5e4e33

Browse files
committed
Allow single identifiers in direct references
1 parent 90b9c6a commit b5e4e33

File tree

1 file changed

+30
-41
lines changed

1 file changed

+30
-41
lines changed

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

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -133,15 +133,6 @@ class Typer extends Namer
133133
val noImports = ctx.mode.is(Mode.InPackageClauseName)
134134
def fail(msg: Message) = report.error(msg, pos)
135135

136-
def qualifies(denot: Denotation): Boolean =
137-
reallyExists(denot)
138-
&& {
139-
if required.is(ExtensionMethod) then
140-
denot.hasAltWith(_.symbol.is(ExtensionMethod))
141-
else
142-
denot.hasAltWith(!_.symbol.is(ExtensionMethod))
143-
}
144-
145136
/** A symbol qualifies if it really exists and is not a package class.
146137
* In addition, if we are in a constructor of a pattern, we ignore all definitions
147138
* which are methods and not accessors (note: if we don't do that
@@ -151,8 +142,8 @@ class Typer extends Namer
151142
* we could not reload them via `_.member`. On the other hand, accessing a
152143
* package as a type from source is always an error.
153144
*/
154-
def qualifiesAsDef(denot: Denotation): Boolean =
155-
qualifies(denot)
145+
def qualifies(denot: Denotation): Boolean =
146+
reallyExists(denot)
156147
&& !(pt.isInstanceOf[UnapplySelectionProto] && denot.symbol.is(Method, butNot = Accessor))
157148
&& !denot.symbol.is(PackageClass)
158149

@@ -213,7 +204,7 @@ class Typer extends Namer
213204
denot = denot.filterWithPredicate { mbr =>
214205
mbr.matchesImportBound(if mbr.symbol.is(Given) then imp.givenBound else imp.wildcardBound)
215206
}
216-
if qualifies(denot) then
207+
if reallyExists(denot) then
217208
if unimported.isEmpty || !unimported.contains(pre.termSymbol) then
218209
return pre.select(name, denot)
219210
case _ =>
@@ -345,7 +336,7 @@ class Typer extends Namer
345336

346337
if isNewDefScope then
347338
val defDenot = ctx.denotNamed(name, required)
348-
if (qualifiesAsDef(defDenot)) {
339+
if (qualifies(defDenot)) {
349340
val found =
350341
if (isSelfDenot(defDenot)) curOwner.enclosingClass.thisType
351342
else {
@@ -458,8 +449,7 @@ class Typer extends Namer
458449
unimported = Set.empty
459450
foundUnderScala2 = NoType
460451
try
461-
val reqFlags = if pt.isExtensionApplyProto then ExtensionMethod else EmptyFlags
462-
val found = findRef(name, pt, reqFlags, tree.srcPos)
452+
val found = findRef(name, pt, EmptyFlags, tree.srcPos)
463453
if foundUnderScala2.exists && !(foundUnderScala2 =:= found) then
464454
report.migrationWarning(
465455
ex"""Name resolution will change.
@@ -481,41 +471,40 @@ class Typer extends Namer
481471
checkStableIdentPattern(tree2, pt)
482472
tree2
483473

484-
def fail: Tree =
485-
if ctx.owner.isConstructor && !ctx.owner.isPrimaryConstructor
486-
&& ctx.owner.owner.unforcedDecls.lookup(tree.name).exists
487-
then
488-
// we are in the arguments of a this(...) constructor call
489-
errorTree(tree, ex"$tree is not accessible from constructor arguments")
490-
else
491-
errorTree(tree, MissingIdent(tree, kind, name))
474+
def isLocalExtensionMethodRef: Boolean = { rawType match
475+
case rawType: TermRef =>
476+
rawType.denot.hasAltWith(_.symbol.is(ExtensionMethod))
477+
&& !pt.isExtensionApplyProto
478+
&& {
479+
val xmethod = ctx.owner.enclosingExtensionMethod
480+
rawType.denot.hasAltWith { alt =>
481+
alt.symbol.is(ExtensionMethod)
482+
&& alt.symbol.extensionParam.span == xmethod.extensionParam.span
483+
}
484+
}
485+
case _ =>
486+
false
487+
}
492488

493-
if rawType.exists then
489+
if ctx.mode.is(Mode.InExtensionMethod) && isLocalExtensionMethodRef then
490+
val xmethod = ctx.owner.enclosingExtensionMethod
491+
val qualifier = untpd.ref(xmethod.extensionParam.termRef)
492+
val selection = untpd.cpy.Select(tree)(qualifier, name)
493+
typed(selection, pt)
494+
else if rawType.exists then
494495
setType(ensureAccessible(rawType, superAccess = false, tree.srcPos))
495496
else if name == nme._scope then
496497
// gross hack to support current xml literals.
497498
// awaiting a better implicits based solution for library-supported xml
498499
ref(defn.XMLTopScopeModule.termRef)
499500
else if name.toTermName == nme.ERROR then
500501
setType(UnspecifiedErrorType)
501-
else if name.isTermName then
502-
// Convert a reference `f` to an extension method select `p.f`, where
503-
// `p` is the closest enclosing extension parameter, or else convert to `this.f`.
504-
val xmethod = ctx.owner.enclosingExtensionMethod
505-
if xmethod.exists then
506-
val qualifier = untpd.ref(xmethod.extensionParam.termRef)
507-
val selection = untpd.cpy.Select(tree)(qualifier, name)
508-
val result = tryEither(typed(selection, pt))((_, _) => fail)
509-
def canAccessUnqualified(sym: Symbol) =
510-
sym.is(ExtensionMethod) && (sym.extensionParam.span == xmethod.extensionParam.span)
511-
if result.tpe.isError || canAccessUnqualified(result.symbol) then
512-
result
513-
else
514-
fail
515-
else
516-
fail
502+
else if ctx.owner.isConstructor && !ctx.owner.isPrimaryConstructor
503+
&& ctx.owner.owner.unforcedDecls.lookup(tree.name).exists
504+
then // we are in the arguments of a this(...) constructor call
505+
errorTree(tree, ex"$tree is not accessible from constructor arguments")
517506
else
518-
fail
507+
errorTree(tree, MissingIdent(tree, kind, name))
519508
end typedIdent
520509

521510
/** Check that a stable identifier pattern is indeed stable (SLS 8.1.5)

0 commit comments

Comments
 (0)