Skip to content

Commit c9ba59d

Browse files
committed
remove heuristic, turn into a warning
1 parent 189fc85 commit c9ba59d

File tree

11 files changed

+115
-81
lines changed

11 files changed

+115
-81
lines changed

src/compiler/scala/tools/nsc/settings/ScalaSettings.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,6 @@ trait ScalaSettings extends StandardScalaSettings with Warnings { _: MutableSett
267267
val exposeEmptyPackage = BooleanSetting ("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
268268
val Ydelambdafy = ChoiceSetting ("-Ydelambdafy", "strategy", "Strategy used for translating lambdas into JVM code.", List("inline", "method"), "method")
269269

270-
val legacyBinding = BooleanSetting("-Ylegacy-binding", "Observe legacy name binding preference for inherited member competing with local definition.")
271-
272270
// Allows a specialised jar to be written. For instance one that provides stable hashing of content, or customisation of the file storage
273271
val YjarFactory = StringSetting ("-YjarFactory", "classname", "factory for jar files", classOf[DefaultJarFactory].getName)
274272
val YaddBackendThreads = IntSetting ("-Ybackend-parallelism", "maximum worker threads for backend", 1, Some((1,16)), (x: String) => None )

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

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,8 +1362,28 @@ trait Contexts { self: Analyzer =>
13621362
LookupAmbiguous(s"it is imported twice in the same scope by\n$imp1\nand $imp2")
13631363
def ambiguousDefnAndImport(owner: Symbol, imp: ImportInfo) =
13641364
LookupAmbiguous(s"it is both defined in $owner and imported subsequently by \n$imp")
1365-
def ambiguousDefinitions(owner: Symbol, other: Symbol, addendum: String) =
1366-
LookupAmbiguous(s"it is both defined in $owner and available as ${other.fullLocationString}$addendum")
1365+
def ambiguousDefinitions(sym: Symbol, other: Symbol, otherFoundInSuper: Boolean, otherEnclClass: Symbol) = {
1366+
if (otherFoundInSuper) {
1367+
val enclDesc = if (otherEnclClass.isAnonymousClass) "anonymous class" else otherEnclClass.toString
1368+
val parent = otherEnclClass.parentSymbols.find(_.isNonBottomSubClass(other.owner)).getOrElse(NoSymbol)
1369+
val inherit = if (parent.exists && parent != other.owner) s", inherited through parent $parent" else ""
1370+
val message =
1371+
s"""it is both defined in the enclosing ${sym.owner} and available in the enclosing $enclDesc as $other (defined in ${other.ownsString}$inherit)
1372+
|Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
1373+
|To continue using the symbol from the superclass, write `this.${sym.name}`.""".stripMargin
1374+
if (currentRun.isScala3)
1375+
Some(LookupAmbiguous(message))
1376+
else {
1377+
// passing the message to `typedIdent` as attachment, we don't have the position here to report the warning
1378+
other.updateAttachment(
1379+
s"""reference to ${sym.name} is ambiguous;
1380+
|$message
1381+
|Or use `-Wconf:msg=legacy-binding:s` to silence this warning.""".stripMargin)
1382+
None
1383+
}
1384+
} else
1385+
Some(LookupAmbiguous(s"it is both defined in ${sym.owner} and available as ${other.fullLocationString}"))
1386+
}
13671387

13681388
def apply(thisContext: Context, name: Name)(qualifies: Symbol => Boolean): NameLookup = {
13691389
lookupError = null
@@ -1466,27 +1486,10 @@ trait Contexts { self: Analyzer =>
14661486
}
14671487
if (!defSym.exists) cx = cx.outer // push further outward
14681488
}
1469-
def forwardedClassParam = lastDef.isParamAccessor && {
1470-
val parentClass = lastDef.owner
1471-
val templateCtx = thisContext.nextEnclosing(c => c.tree.isInstanceOf[Template] && c.owner.isNonBottomSubClass(parentClass))
1472-
templateCtx.owner.superClass == parentClass && {
1473-
templateCtx.tree.asInstanceOf[Template].parents.headOption.collect {
1474-
case Apply(_, args) => args
1475-
} match {
1476-
case Some(args) =>
1477-
// named args? repeated args?
1478-
args.zip(parentClass.primaryConstructor.paramss.headOption.getOrElse(Nil)).exists {
1479-
case (arg: Ident, param) => param.name == lastDef.name && arg.symbol == defSym
1480-
case _ => false
1481-
}
1482-
case _ => false
1483-
}
1484-
}
1485-
}
14861489
if ((defSym.isAliasType || lastDef.isAliasType) && pre.memberType(defSym) =:= lastPre.memberType(lastDef))
14871490
defSym = NoSymbol
14881491
if (defSym.isStable && lastDef.isStable &&
1489-
(lastPre.memberType(lastDef).termSymbol == defSym || pre.memberType(defSym).termSymbol == lastDef || forwardedClassParam))
1492+
(lastPre.memberType(lastDef).termSymbol == defSym || pre.memberType(defSym).termSymbol == lastDef))
14901493
defSym = NoSymbol
14911494
foundInPrefix = inPrefix && defSym.exists
14921495
foundInSuper = foundInPrefix && defSym.owner != cx.owner
@@ -1524,7 +1527,7 @@ trait Contexts { self: Analyzer =>
15241527
* 1b) Definitions and declarations that are either inherited, or made
15251528
* available by a package clause and also defined in the same compilation unit
15261529
* as the reference to them, have the next highest precedence.
1527-
* (Same precedence as 1 under -Ylegacy-binding.)
1530+
* (Only in -Xsource:3, same precedence as 1 with a warning in Scala 2.)
15281531
* 2) Explicit imports have next highest precedence.
15291532
* 3) Wildcard imports have next highest precedence.
15301533
* 4) Definitions made available by a package clause, but not also defined in the same compilation unit
@@ -1588,7 +1591,7 @@ trait Contexts { self: Analyzer =>
15881591
// If the defSym is at 4, and there is a def at 1b in scope due to packaging, then the reference is ambiguous.
15891592
// Also if defSym is at 1b inherited, the reference can be rendered ambiguous by a def at 1a in scope.
15901593
val possiblyAmbiguousDefinition =
1591-
foundInSuper && cx.owner.isClass && !settings.legacyBinding.value ||
1594+
foundInSuper && cx.owner.isClass ||
15921595
foreignDefined && !defSym.hasPackageFlag
15931596
if (possiblyAmbiguousDefinition && !thisContext.unit.isJava) {
15941597
val defSym0 = defSym
@@ -1608,17 +1611,10 @@ trait Contexts { self: Analyzer =>
16081611
if (!done && (cx ne NoContext)) cx = cx.outer
16091612
}
16101613
if (defSym.exists && (defSym ne defSym0)) {
1611-
val addendum =
1612-
if (wasFoundInSuper)
1613-
s"""|
1614-
|Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
1615-
|If shadowing was intended, write `this.${defSym0.name}`.
1616-
|Or use `-Ylegacy-binding` to enable the previous behavior everywhere.""".stripMargin
1617-
else ""
16181614
val ambiguity =
1619-
if (preferDef) ambiguousDefinitions(owner = defSym.owner, defSym0, addendum)
1620-
else ambiguousDefnAndImport(owner = defSym.owner, imp1)
1621-
return ambiguity
1615+
if (preferDef) ambiguousDefinitions(defSym, defSym0, wasFoundInSuper, cx0.enclClass.owner)
1616+
else Some(ambiguousDefnAndImport(owner = defSym.owner, imp1))
1617+
if (ambiguity.nonEmpty) return ambiguity.get
16221618
}
16231619
defSym = defSym0
16241620
pre = pre0

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5501,6 +5501,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
55015501
case sym => typed1(tree setSymbol sym, mode, pt)
55025502
}
55035503
case LookupSucceeded(qual, sym) =>
5504+
sym.getAndRemoveAttachment[String].foreach(w =>
5505+
runReporting.warning(tree.pos, w, WarningCategory.Other, context.owner))
55045506
(// this -> Foo.this
55055507
if (sym.isThisSym)
55065508
typed1(This(sym.owner) setPos tree.pos, mode, pt)

test/files/neg/t11921-alias.check

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,31 @@
1-
t11921-alias.scala:16: error: reference to TT is ambiguous;
2-
it is both defined in object O and available as type TT in class C
3-
Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
4-
If shadowing was intended, write `this.TT`.
5-
Or use `-Ylegacy-binding` to enable the previous behavior everywhere.
1+
t11921-alias.scala:18: warning: reference to TT is ambiguous;
2+
it is both defined in the enclosing object O and available in the enclosing class D as type TT (defined in class C)
3+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
4+
To continue using the symbol from the superclass, write `this.TT`.
5+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
66
def n(x: TT) = x // ambiguous
77
^
8-
t11921-alias.scala:36: error: reference to c is ambiguous;
9-
it is both defined in class B and available as value c in class A
10-
Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
11-
If shadowing was intended, write `this.c`.
12-
Or use `-Ylegacy-binding` to enable the previous behavior everywhere.
8+
t11921-alias.scala:38: warning: reference to c is ambiguous;
9+
it is both defined in the enclosing class B and available in the enclosing anonymous class as value c (defined in class A)
10+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
11+
To continue using the symbol from the superclass, write `this.c`.
12+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
1313
def n = c // ambiguous
1414
^
15-
t11921-alias.scala:65: error: reference to name is ambiguous;
16-
it is both defined in method m and available as value name in class A
17-
Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
18-
If shadowing was intended, write `this.name`.
19-
Or use `-Ylegacy-binding` to enable the previous behavior everywhere.
15+
t11921-alias.scala:57: warning: reference to name is ambiguous;
16+
it is both defined in the enclosing method m and available in the enclosing anonymous class as value name (defined in class C)
17+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
18+
To continue using the symbol from the superclass, write `this.name`.
19+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
2020
println(name)
2121
^
22-
3 errors
22+
t11921-alias.scala:67: warning: reference to name is ambiguous;
23+
it is both defined in the enclosing method m and available in the enclosing anonymous class as value name (defined in class A, inherited through parent class C)
24+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
25+
To continue using the symbol from the superclass, write `this.name`.
26+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
27+
println(name)
28+
^
29+
error: No warnings can be incurred under -Werror.
30+
4 warnings
31+
1 error

test/files/neg/t11921-alias.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalac: -Werror
2+
13
object t1 {
24
class C[T] { type TT = T }
35
object O {

test/files/neg/t11921.check

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
t11921.scala:6: error: reference to coll is ambiguous;
2-
it is both defined in method lazyMap and available as method coll in trait Iterable
3-
Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
4-
If shadowing was intended, write `this.coll`.
5-
Or use `-Ylegacy-binding` to enable the previous behavior everywhere.
1+
t11921.scala:6: error: type mismatch;
2+
found : A => B
3+
required: B => B
4+
def iterator = coll.iterator.map(f) // coll is ambiguous
5+
^
6+
t11921.scala:6: warning: reference to coll is ambiguous;
7+
it is both defined in the enclosing method lazyMap and available in the enclosing anonymous class as method coll (defined in trait Iterable)
8+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
9+
To continue using the symbol from the superclass, write `this.coll`.
10+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
611
def iterator = coll.iterator.map(f) // coll is ambiguous
712
^
13+
1 warning
814
1 error

test/files/neg/t11921b.check

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,38 @@
1-
t11921b.scala:11: error: reference to x is ambiguous;
2-
it is both defined in object Test and available as value x in class C
3-
Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
4-
If shadowing was intended, write `this.x`.
5-
Or use `-Ylegacy-binding` to enable the previous behavior everywhere.
1+
t11921b.scala:11: warning: reference to x is ambiguous;
2+
it is both defined in the enclosing object Test and available in the enclosing class D as value x (defined in class C)
3+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
4+
To continue using the symbol from the superclass, write `this.x`.
5+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
66
println(x) // error
77
^
8-
t11921b.scala:15: error: reference to x is ambiguous;
9-
it is both defined in object Test and available as value x in class C
10-
Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
11-
If shadowing was intended, write `this.x`.
12-
Or use `-Ylegacy-binding` to enable the previous behavior everywhere.
8+
t11921b.scala:15: warning: reference to x is ambiguous;
9+
it is both defined in the enclosing object Test and available in the enclosing anonymous class as value x (defined in class C)
10+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
11+
To continue using the symbol from the superclass, write `this.x`.
12+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
1313
println(x) // error
1414
^
15-
t11921b.scala:26: error: reference to y is ambiguous;
16-
it is both defined in method c and available as value y in class D
17-
Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
18-
If shadowing was intended, write `this.y`.
19-
Or use `-Ylegacy-binding` to enable the previous behavior everywhere.
15+
t11921b.scala:26: warning: reference to y is ambiguous;
16+
it is both defined in the enclosing method c and available in the enclosing anonymous class as value y (defined in class D)
17+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
18+
To continue using the symbol from the superclass, write `this.y`.
19+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
2020
println(y) // error
2121
^
22-
t11921b.scala:38: error: reference to y is ambiguous;
23-
it is both defined in method c and available as value y in class D
24-
Since 2.13.11, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
25-
If shadowing was intended, write `this.y`.
26-
Or use `-Ylegacy-binding` to enable the previous behavior everywhere.
22+
t11921b.scala:38: warning: reference to y is ambiguous;
23+
it is both defined in the enclosing method c and available in the enclosing class E as value y (defined in class D)
24+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
25+
To continue using the symbol from the superclass, write `this.y`.
26+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
2727
println(y) // error
2828
^
29-
4 errors
29+
t11921b.scala:75: warning: reference to x is ambiguous;
30+
it is both defined in the enclosing object Uhu and available in the enclosing class C as value x (defined in class A, inherited through parent class B)
31+
Since 3, symbols inherited from a superclass no longer shadow symbols defined in an outer scope.
32+
To continue using the symbol from the superclass, write `this.x`.
33+
Or use `-Wconf:msg=legacy-binding:s` to silence this warning.
34+
def t = x // ambiguous, message mentions parent B
35+
^
36+
error: No warnings can be incurred under -Werror.
37+
5 warnings
38+
1 error

test/files/neg/t11921b.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
// scalac: -Werror
22

33
object test1 {
44

@@ -64,3 +64,16 @@ class C {
6464
object D extends C {
6565
println(global) // OK, since global is defined in package
6666
}
67+
68+
object test5 {
69+
class A { val x = 1 }
70+
class B extends A
71+
object Uhu {
72+
val x = 2
73+
class C extends B {
74+
class Inner {
75+
def t = x // ambiguous, message mentions parent B
76+
}
77+
}
78+
}
79+
}

test/files/neg/t11921c.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
t11921c.scala:7: error: type mismatch;
1+
t11921c.scala:6: error: type mismatch;
22
found : A => B
33
required: B => B
44
def iterator = coll.iterator.map(f) // coll is ambiguous

test/files/neg/t11921c.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
2-
// scalac: -Ylegacy-binding
1+
// scalac: -Wconf:msg=legacy-binding:s
32

43
class C {
54
def lazyMap[A, B](coll: Iterable[A], f: A => B) =

test/files/pos/t11921b.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
// scalac: -Werror -Ylegacy-binding
2+
// scalac: -Werror -Wconf:msg=legacy-binding:s
33

44
object test1 {
55

0 commit comments

Comments
 (0)