Skip to content

Commit 2ed0d2a

Browse files
committed
Remove references to trait impl classes, mostly in doc comments
1 parent 2d62eea commit 2ed0d2a

File tree

11 files changed

+49
-85
lines changed

11 files changed

+49
-85
lines changed

src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
3131
* True for classes generated by the Scala compiler that are considered top-level in terms of
3232
* the InnerClass / EnclosingMethod classfile attributes. See comment in BTypes.
3333
*/
34-
def considerAsTopLevelImplementationArtifact(classSym: Symbol) =
35-
classSym.isSpecialized
34+
def considerAsTopLevelImplementationArtifact(classSym: Symbol) = classSym.isSpecialized
3635

3736
/**
3837
* Cache the value of delambdafy == "inline" for each run. We need to query this value many
@@ -147,10 +146,10 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
147146
assert(classSym.isClass, classSym)
148147

149148
def doesNotExist(method: Symbol) = {
150-
// Value classes. Member methods of value classes exist in the generated box class. However,
151-
// nested methods lifted into a value class are moved to the companion object and don't exist
152-
// in the value class itself. We can identify such nested methods: the initial enclosing class
153-
// is a value class, but the current owner is some other class (the module class).
149+
// Value classes. Member methods of value classes exist in the generated box class. However,
150+
// nested methods lifted into a value class are moved to the companion object and don't exist
151+
// in the value class itself. We can identify such nested methods: the initial enclosing class
152+
// is a value class, but the current owner is some other class (the module class).
154153
val enclCls = nextEnclosingClass(method)
155154
exitingPickler(enclCls.isDerivedValueClass) && method.owner != enclCls
156155
}
@@ -172,8 +171,6 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
172171
private def enclosingClassForEnclosingMethodAttribute(classSym: Symbol): Symbol = {
173172
assert(classSym.isClass, classSym)
174173
val r = nextEnclosingClass(nextEnclosing(classSym))
175-
// this should be an assertion, but we are more cautious for now as it was introduced before the 2.11.6 minor release
176-
if (considerAsTopLevelImplementationArtifact(r)) devWarning(s"enclosing class of $classSym should not be an implementation artifact class: $r")
177174
r
178175
}
179176

@@ -188,20 +185,11 @@ abstract class BCodeHelpers extends BCodeIdiomatic with BytecodeWriters {
188185
* on the implementation of GenASM / GenBCode, so they need to be passed in.
189186
*/
190187
def enclosingMethodAttribute(classSym: Symbol, classDesc: Symbol => String, methodDesc: Symbol => String): Option[EnclosingMethodEntry] = {
191-
// trait impl classes are always top-level, see comment in BTypes
188+
// specialized classes are always top-level, see comment in BTypes
192189
if (isAnonymousOrLocalClass(classSym) && !considerAsTopLevelImplementationArtifact(classSym)) {
193190
val enclosingClass = enclosingClassForEnclosingMethodAttribute(classSym)
194-
val methodOpt = enclosingMethodForEnclosingMethodAttribute(classSym) match {
195-
case some @ Some(m) =>
196-
if (m.owner != enclosingClass) {
197-
// This should never happen. In case it does, it prevents emitting an invalid
198-
// EnclosingMethod attribute: if the attribute specifies an enclosing method,
199-
// it needs to exist in the specified enclosing class.
200-
devWarning(s"the owner of the enclosing method ${m.locationString} should be the same as the enclosing class $enclosingClass")
201-
None
202-
} else some
203-
case none => none
204-
}
191+
val methodOpt = enclosingMethodForEnclosingMethodAttribute(classSym)
192+
for (m <- methodOpt) assert(m.owner == enclosingClass, s"the owner of the enclosing method ${m.locationString} should be the same as the enclosing class $enclosingClass")
205193
Some(EnclosingMethodEntry(
206194
classDesc(enclosingClass),
207195
methodOpt.map(_.javaSimpleName.toString).orNull,

src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,13 +232,6 @@ abstract class BCodeSkelBuilder extends BCodeHelpers {
232232
}
233233

234234
def addClassFields() {
235-
/* Non-method term members are fields, except for module members. Module
236-
* members can only happen on .NET (no flatten) for inner traits. There,
237-
* a module symbol is generated (transformInfo in mixin) which is used
238-
* as owner for the members of the implementation class (so that the
239-
* backend emits them as static).
240-
* No code is needed for this module symbol.
241-
*/
242235
for (f <- fieldSymbols(claszSymbol)) {
243236
val javagensig = getGenericSignature(f, claszSymbol)
244237
val flags = javaFieldFlags(f)

src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -790,26 +790,17 @@ abstract class BTypes {
790790
* }
791791
*
792792
*
793-
* Traits Members
794-
* --------------
795-
*
796-
* Some trait methods don't exist in the generated interface, but only in the implementation class
797-
* (private methods in traits for example). Since EnclosingMethod expresses a source-level property,
798-
* but the source-level enclosing method doesn't exist in the classfile, we the enclosing method
799-
* is null (the enclosing class is still emitted).
800-
* See BCodeAsmCommon.considerAsTopLevelImplementationArtifact
801-
*
793+
* Specialized Classes, Delambdafy:method closure classes
794+
* ------------------------------------------------------
802795
*
803-
* Implementation Classes, Specialized Classes, Delambdafy:method closure classes
804-
* ------------------------------------------------------------------------------
805-
*
806-
* Trait implementation classes and specialized classes are always considered top-level. Again,
807-
* the InnerClass / EnclosingMethod attributes describe a source-level properties. The impl
808-
* classes are compilation artifacts.
796+
* Specialized classes are always considered top-level, as the InnerClass / EnclosingMethod
797+
* attributes describe a source-level properties.
809798
*
810799
* The same is true for delambdafy:method closure classes. These classes are generated at
811800
* top-level in the delambdafy phase, no special support is required in the backend.
812801
*
802+
* See also BCodeHelpers.considerAsTopLevelImplementationArtifact.
803+
*
813804
*
814805
* Mirror Classes
815806
* --------------

src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,6 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
9696
* scala.Null is mapped to scala.runtime.Null$. This is because there exist no class files
9797
* for the Nothing / Null. If used for example as a parameter type, we use the runtime classes
9898
* in the classfile method signature.
99-
*
100-
* Note that the referenced class symbol may be an implementation class. For example when
101-
* compiling a mixed-in method that forwards to the static method in the implementation class,
102-
* the class descriptor of the receiver (the implementation class) is obtained by creating the
103-
* ClassBType.
10499
*/
105100
final def classBTypeFromSymbol(classSym: Symbol): ClassBType = {
106101
assert(classSym != NoSymbol, "Cannot create ClassBType from NoSymbol")
@@ -159,9 +154,6 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
159154

160155
/**
161156
* This method returns the BType for a type reference, for example a parameter type.
162-
*
163-
* If `t` references a class, typeToBType ensures that the class is not an implementation class.
164-
* See also comment on classBTypeFromSymbol, which is invoked for implementation classes.
165157
*/
166158
final def typeToBType(t: Type): BType = {
167159
import definitions.ArrayClass
@@ -264,12 +256,12 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
264256
* current phase, for example, after lambdalift, all local classes become member of the enclosing
265257
* class.
266258
*
267-
* Impl classes are always considered top-level, see comment in BTypes.
259+
* Specialized classes are always considered top-level, see comment in BTypes.
268260
*/
269261
private def memberClassesForInnerClassTable(classSymbol: Symbol): List[Symbol] = classSymbol.info.decls.collect({
270262
case sym if sym.isClass && !considerAsTopLevelImplementationArtifact(sym) =>
271263
sym
272-
case sym if sym.isModule && !considerAsTopLevelImplementationArtifact(sym) => // impl classes get the lateMODULE flag in mixin
264+
case sym if sym.isModule && !considerAsTopLevelImplementationArtifact(sym) =>
273265
val r = exitingPickler(sym.moduleClass)
274266
assert(r != NoSymbol, sym.fullLocationString)
275267
r
@@ -317,7 +309,6 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
317309
)
318310
}
319311

320-
// Check for isImplClass: trait implementation classes have NoSymbol as superClass
321312
// Check for hasAnnotationFlag for SI-9393: the classfile / java source parsers add
322313
// scala.annotation.Annotation as superclass to java annotations. In reality, java
323314
// annotation classfiles have superclass Object (like any interface classfile).
@@ -380,8 +371,8 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
380371
}
381372

382373
val companionModuleMembers = if (considerAsTopLevelImplementationArtifact(classSym)) Nil else {
383-
// If this is a top-level non-impl (*) class, the member classes of the companion object are
384-
// added as members of the class. For example:
374+
// If this is a top-level class, the member classes of the companion object are added as
375+
// members of the class. For example:
385376
// class C { }
386377
// object C {
387378
// class D
@@ -392,11 +383,6 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
392383
// (done by buildNestedInfo). See comment in BTypes.
393384
// For consistency, the InnerClass entry for D needs to be present in C - to Java it looks
394385
// like D is a member of C, not C$.
395-
//
396-
// (*) We exclude impl classes: if the classfile for the impl class exists on the classpath,
397-
// a linkedClass symbol is found for which isTopLevelModule is true, so we end up searching
398-
// members of that weird impl-class-module-class-symbol. that search probably cannot return
399-
// any classes, but it's better to exclude it.
400386
val javaCompatMembers = {
401387
if (linkedClass != NoSymbol && isTopLevelModuleClass(linkedClass))
402388
// phase travel to exitingPickler: this makes sure that memberClassesForInnerClassTable only sees member
@@ -454,7 +440,7 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
454440
assert(innerClassSym.isClass, s"Cannot build NestedInfo for non-class symbol $innerClassSym")
455441

456442
val isTopLevel = innerClassSym.rawowner.isPackageClass
457-
// impl classes are considered top-level, see comment in BTypes
443+
// specialized classes are considered top-level, see comment in BTypes
458444
if (isTopLevel || considerAsTopLevelImplementationArtifact(innerClassSym)) None
459445
else if (innerClassSym.rawowner.isTerm) {
460446
// This case should never be reached: the lambdalift phase mutates the rawowner field of all
@@ -592,17 +578,11 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes {
592578

593579
/**
594580
* True for module classes of modules that are top-level or owned only by objects. Module classes
595-
* for such objects will get a MODULE$ flag and a corresponding static initializer.
581+
* for such objects will get a MODULE$ field and a corresponding static initializer.
596582
*/
597583
final def isStaticModuleClass(sym: Symbol): Boolean = {
598-
/* (1) Phase travel to to pickler is required to exclude implementation classes; they have the
599-
* lateMODULEs after mixin, so isModuleClass would be true.
600-
* (2) isStaticModuleClass is a source-level property. See comment on isOriginallyStaticOwner.
601-
*/
602-
exitingPickler { // (1)
603-
sym.isModuleClass &&
604-
isOriginallyStaticOwner(sym.originalOwner) // (2)
605-
}
584+
sym.isModuleClass &&
585+
isOriginallyStaticOwner(sym.originalOwner) // isStaticModuleClass is a source-level property, see comment on isOriginallyStaticOwner
606586
}
607587

608588
// legacy, to be removed when the @remote annotation gets removed

src/reflect/scala/reflect/api/Symbols.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,9 +260,6 @@ trait Symbols { self: Universe =>
260260
* with an object definition (module class in scala compiler parlance)?
261261
* If yes, `isType` is also guaranteed to be true.
262262
*
263-
* Note to compiler developers: During the "mixin" phase, trait implementation class symbols
264-
* receive the `lateMODULE` flag, hence `isImplClass && isModuleClass` becomes true.
265-
*
266263
* @group Tests
267264
*/
268265
def isModuleClass: Boolean = false
@@ -354,8 +351,7 @@ trait Symbols { self: Universe =>
354351
/******************* tests *******************/
355352

356353
/** Does this symbol represent a synthetic (i.e. a compiler-generated) entity?
357-
* Examples of synthetic entities are accessors for vals and vars
358-
* or mixin constructors in trait implementation classes.
354+
* Examples of synthetic entities are accessors for vals and vars.
359355
*
360356
* @group Tests
361357
*/

src/reflect/scala/reflect/internal/Flags.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ package internal
5050
// 34: LIFTED
5151
// 35: EXISTENTIAL MIXEDIN
5252
// 36: EXPANDEDNAME
53-
// 37: IMPLCLASS PRESUPER/M
53+
// 37: PRESUPER/M
5454
// 38: TRANS_FLAG
5555
// 39: LOCKED
5656
// 40: SPECIALIZED

src/reflect/scala/reflect/internal/Symbols.scala

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -956,10 +956,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
956956
* method `owner` returns the class C.
957957
*
958958
* Why not make a stable version of `isStatic`? Maybe some parts of the compiler depend on the
959-
* current implementation. For example
960-
* trait T { def foo = 1 }
961-
* The method `foo` in the implementation class T$impl will be `isStatic`, because trait
962-
* impl classes get the `lateMODULE` flag (T$impl.isStaticOwner is true).
959+
* current implementation.
963960
*/
964961
def isStatic = (this hasFlag STATIC) || owner.isStaticOwner
965962

@@ -2780,7 +2777,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
27802777
case DEFAULTPARAM => "<defaultparam>" // TRAIT
27812778
case MIXEDIN => "<mixedin>" // EXISTENTIAL
27822779
case LABEL => "<label>" // CONTRAVARIANT / INCONSTRUCTOR
2783-
case PRESUPER => "<presuper>" // IMPLCLASS
27842780
case BYNAMEPARAM => if (this.isValueParameter) "<bynameparam>" else "<captured>" // COVARIANT
27852781
case _ => super.resolveOverloadedFlag(flag)
27862782
}

src/reflect/scala/reflect/internal/Types.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2462,7 +2462,6 @@ trait Types
24622462
def isImplicit = (params ne Nil) && params.head.isImplicit
24632463
def isJava = false // can we do something like for implicits? I.e. do Java methods without parameters need to be recognized?
24642464

2465-
//assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG
24662465
override def paramSectionCount: Int = resultType.paramSectionCount + 1
24672466

24682467
override def paramss: List[List[Symbol]] = params :: resultType.paramss

src/repl/scala/tools/nsc/interpreter/Power.scala

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,10 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
176176
*/
177177
class InternalInfo[T](value: Option[T] = None)(implicit typeEvidence: ru.TypeTag[T], runtimeClassEvidence: ClassTag[T]) {
178178
private def isSpecialized(s: Symbol) = s.name.toString contains "$mc"
179-
private def isImplClass(s: Symbol) = s.name.toString endsWith "$class"
180179

181180
/** Standard noise reduction filter. */
182181
def excludeMember(s: Symbol) = (
183182
isSpecialized(s)
184-
|| isImplClass(s)
185183
|| s.isAnonOrRefinementClass
186184
|| s.isAnonymousFunction
187185
)

test/files/jvm/innerClassAttribute/Classes_1.scala

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ trait A24 extends A24Base {
186186
}
187187
}
188188

189-
class SI_9105 {
189+
class SI_9105 {
190190
// outerClass enclMeth
191191
val fun = (s: String) => {
192192
class A // SI_9105 null
@@ -269,6 +269,23 @@ class SpecializedClassesAreTopLevel {
269269
// }
270270
}
271271

272+
object AnonymousClassesMayBeNestedInSpecialized {
273+
abstract class A
274+
class C[@specialized(Int) T] {
275+
def foo(t: T): A = new A { }
276+
}
277+
278+
// specialization duplicates the anonymous class, one copy is nested in the specialized subclass of C
279+
280+
// class C$mcI$sp extends C[Int] {
281+
// override def foo(t: Int): A = C$mcI$sp.this.foo$mcI$sp(t);
282+
// override def foo$mcI$sp(t: Int): A = {
283+
// final class $anon extends A { }
284+
// new <$anon: A>()
285+
// }
286+
// }
287+
}
288+
272289
object NestedInValueClass {
273290
// note that we can only test anonymous functions, nested classes are not allowed inside value classes
274291
class A(val arg: String) extends AnyVal {

0 commit comments

Comments
 (0)