Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7c0198a

Browse files
authored
Merge pull request #11086 from som-snytt/issue/13109-select-reflect
Check reflective if ident ref is selection [ci: last-only]
2 parents 29e4422 + cdd5f20 commit 7c0198a

File tree

5 files changed

+86
-50
lines changed

5 files changed

+86
-50
lines changed

src/compiler/scala/tools/nsc/typechecker/Infer.scala

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -237,32 +237,6 @@ trait Infer extends Checkable {
237237
withDisambiguation(List(), tp1, tp2)(global.explainTypes(tp1, tp2))
238238
}
239239

240-
// When filtering sym down to the accessible alternatives leaves us empty handed.
241-
private def checkAccessibleError(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree = {
242-
if (settings.isDebug) {
243-
Console.println(context)
244-
Console.println(tree)
245-
Console.println("" + pre + " " + sym.owner + " " + context.owner + " " + context.outer.enclClass.owner + " " + sym.owner.thisType + (pre =:= sym.owner.thisType))
246-
}
247-
ErrorUtils.issueTypeError(AccessError(tree, sym, pre, context.enclClass.owner,
248-
if (settings.check.isDefault)
249-
analyzer.lastAccessCheckDetails
250-
else
251-
ptBlock("because of an internal error (no accessible symbol)",
252-
"sym.ownerChain" -> sym.ownerChain,
253-
"underlyingSymbol(sym)" -> underlyingSymbol(sym),
254-
"pre" -> pre,
255-
"site" -> site,
256-
"tree" -> tree,
257-
"sym.accessBoundary(sym.owner)" -> sym.accessBoundary(sym.owner),
258-
"context.owner" -> context.owner,
259-
"context.outer.enclClass.owner" -> context.outer.enclClass.owner
260-
)
261-
))(context)
262-
263-
setError(tree)
264-
}
265-
266240
/* -- Tests & Checks---------------------------------------------------- */
267241

268242
/** Check that `sym` is defined and accessible as a member of
@@ -279,41 +253,71 @@ trait Infer extends Checkable {
279253
* since pre may not occur in its type (callers should wrap the result in a TypeTreeWithDeferredRefCheck)
280254
*/
281255
def checkAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree, isJava: Boolean): Tree = {
256+
// When filtering sym down to the accessible alternatives leaves us empty handed.
257+
def checkAccessibleError(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree = {
258+
if (settings.isDebug) {
259+
Console.println(context)
260+
Console.println(tree)
261+
Console.println(s"$pre ${sym.owner} ${context.owner} ${context.outer.enclClass.owner} ${sym.owner.thisType
262+
} ${pre =:= sym.owner.thisType}")
263+
}
264+
ErrorUtils.issueTypeError(AccessError(tree, sym, pre, context.enclClass.owner,
265+
if (settings.check.isDefault)
266+
analyzer.lastAccessCheckDetails
267+
else
268+
ptBlock("because of an internal error (no accessible symbol)",
269+
"sym.ownerChain" -> sym.ownerChain,
270+
"underlyingSymbol(sym)" -> underlyingSymbol(sym),
271+
"pre" -> pre,
272+
"site" -> site,
273+
"tree" -> tree,
274+
"sym.accessBoundary(sym.owner)" -> sym.accessBoundary(sym.owner),
275+
"context.owner" -> context.owner,
276+
"context.outer.enclClass.owner" -> context.outer.enclClass.owner
277+
)
278+
))(context)
279+
280+
setError(tree)
281+
}
282282
def malformed(ex: MalformedType, instance: Type): Type = {
283283
val what = if (ex.msg contains "malformed type") "is malformed" else s"contains a ${ex.msg}"
284284
val message = s"\n because its instance type $instance $what"
285285
val error = AccessError(tree, sym, pre, context.enclClass.owner, message)
286286
ErrorUtils.issueTypeError(error)(context)
287287
ErrorType
288288
}
289-
def accessible = sym.filter(context.isAccessible(_, pre, site.isInstanceOf[Super])) match {
290-
case NoSymbol if sym.isJavaDefined && context.unit.isJava => sym // don't try to second guess Java; see #4402
291-
case sym1 => sym1
292-
}
293289
if (context.unit.exists && settings.YtrackDependencies.value)
294290
context.unit.registerDependency(sym.enclosingTopLevelClass)
295291

296292
if (sym.isError)
297-
tree setSymbol sym setType ErrorType
298-
else accessible match {
299-
case NoSymbol => checkAccessibleError(tree, sym, pre, site)
300-
case acc if context.owner.isTermMacro && (acc hasFlag LOCKED) => throw CyclicReference(acc, CheckAccessibleMacroCycle)
301-
case acc =>
302-
val sym1 = if (acc.isTerm) acc.cookJavaRawInfo() else acc // xform java rawtypes into existentials
303-
val owntype = (
304-
try pre memberType sym1
305-
catch { case ex: MalformedType => malformed(ex, pre memberType underlyingSymbol(sym)) }
306-
)
307-
tree setSymbol sym1 setType (
293+
tree.setSymbol(sym).setType(ErrorType)
294+
else {
295+
val accessible = sym.filter(context.isAccessible(_, pre, site.isInstanceOf[Super])) match {
296+
case NoSymbol if sym.isJavaDefined && context.unit.isJava => sym // don't try to second guess Java; see #4402
297+
case sym1 => sym1
298+
}
299+
if (accessible eq NoSymbol)
300+
checkAccessibleError(tree, sym, pre, site)
301+
else if (context.owner.isTermMacro && accessible.hasFlag(LOCKED))
302+
throw CyclicReference(accessible, CheckAccessibleMacroCycle)
303+
else {
304+
val sym1 =
305+
if (accessible.isTerm) accessible.cookJavaRawInfo() // xform java rawtypes into existentials
306+
else accessible
307+
val owntype =
308+
try pre.memberType(sym1)
309+
catch { case ex: MalformedType => malformed(ex, pre.memberType(underlyingSymbol(sym))) }
310+
val owntype1 =
308311
pre match {
309312
// OPT: avoid lambda allocation and Type.map for super constructor calls
310313
case _: SuperType if !sym.isConstructor && !owntype.isInstanceOf[OverloadedType] =>
311-
owntype map ((tp: Type) => if (tp eq pre) site.symbol.thisType else tp)
314+
owntype.map((tp: Type) => if (tp eq pre) site.symbol.thisType else tp)
312315
case _ =>
313316
if ((owntype eq ObjectTpe) && isJava) ObjectTpeJava
314317
else owntype
315318
}
316-
)
319+
tree.setSymbol(sym1).setType(owntype1)
320+
}
317321
}
318322
}
319323

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -665,9 +665,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
665665
settings.language.contains(featureName) || {
666666
def action(): Boolean = {
667667
if (!immediate)
668-
debuglog(s"deferred check of feature $featureTrait")
669-
def hasImport = inferImplicitByType(featureTrait.tpe, context).isSuccess
670-
hasImport || {
668+
debuglog(s"deferred check of feature $featureTrait")
669+
def hasImport = inferImplicitByType(featureTrait.tpe, context).isSuccess
670+
hasImport || {
671671
val Some(AnnotationInfo(_, List(Literal(Constant(featureDesc: String)), Literal(Constant(required: Boolean))), _)) =
672672
featureTrait.getAnnotation(LanguageFeatureAnnot): @unchecked
673673
context.featureWarning(pos, featureName, featureDesc, featureTrait, construct, required)
@@ -5646,9 +5646,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
56465646

56475647
if (tree.hasAttachment[PostfixAttachment.type])
56485648
checkFeature(tree.pos, currentRun.runDefinitions.PostfixOpsFeature, name.decode)
5649-
val sym = tree1.symbol
5650-
if (sym != null && sym.isOnlyRefinementMember && !sym.isMacro)
5651-
checkFeature(tree1.pos, currentRun.runDefinitions.ReflectiveCallsFeature, sym.toString)
5649+
checkReflectiveCallsFeature(tree1)
56525650

56535651
qualTyped.symbol match {
56545652
case s: Symbol if s.isRootPackage => treeCopy.Ident(tree1, name)
@@ -5657,6 +5655,12 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
56575655
}
56585656
}
56595657

5658+
def checkReflectiveCallsFeature(tree: Tree): Unit = {
5659+
val sym = tree.symbol
5660+
if (sym != null && sym.isOnlyRefinementMember && !sym.isMacro)
5661+
checkFeature(tree.pos, currentRun.runDefinitions.ReflectiveCallsFeature, sym.toString)
5662+
}
5663+
56605664
/* A symbol qualifies if:
56615665
* - it exists
56625666
* - it is not stale (stale symbols are made to disappear here)
@@ -5782,6 +5786,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
57825786
// scala/bug#5967 Important to replace param type A* with Seq[A] when seen from from a reference,
57835787
// to avoid inference errors in pattern matching.
57845788
stabilize(tree2, pre2, mode, pt).modifyType(dropIllegalStarTypes)
5789+
.tap(t => if (tree1 ne tree) checkReflectiveCallsFeature(t))
57855790
}
57865791
onSuccess.setAttachments(tree.attachments)
57875792
}

test/files/neg/t13109.check

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
t13109.scala:6: warning: reflective access of structural type member method x should be enabled
2+
by making the implicit value scala.language.reflectiveCalls visible.
3+
This can be achieved by adding the import clause 'import scala.language.reflectiveCalls'
4+
or by setting the compiler option -language:reflectiveCalls.
5+
See the Scaladoc for value scala.language.reflectiveCalls for a discussion
6+
why the feature should be explicitly enabled.
7+
def f1 = b.x // warn
8+
^
9+
t13109.scala:10: warning: reflective access of structural type member method x should be enabled
10+
by making the implicit value scala.language.reflectiveCalls visible.
11+
x // also expect warn but not report
12+
^
13+
error: No warnings can be incurred under -Werror.
14+
2 warnings
15+
1 error

test/files/neg/t13109.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//> using options -feature -Werror
2+
3+
class A {
4+
val b = new AnyRef { def x: Int = 2 }
5+
6+
def f1 = b.x // warn
7+
8+
def f2 = {
9+
import b._
10+
x // also expect warn but not report
11+
}
12+
}

test/files/presentation/doc/doc.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//> using options -Xlint -Werror
1+
//> using options -Xlint -Werror -feature -language:reflectiveCalls
22
import scala.reflect.internal.util.{ BatchSourceFile, SourceFile }
33
import scala.tools.nsc.doc
44
import scala.tools.nsc.doc.base._

0 commit comments

Comments
 (0)