diff options
Diffstat (limited to 'src/compiler/scala')
3 files changed, 20 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 1e479d3f63..636fb08b89 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -501,8 +501,6 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { !sym.isSetter ) - private def possiblySpecialized(s: Symbol) = specializeTypes.specializedTypeVars(s).nonEmpty - /* * whether `sym` denotes a param-accessor (ie a field) that fulfills all of: * (a) has stationary value, ie the same value provided via the corresponding ctor-arg; and @@ -511,7 +509,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { * (b.2) the constructor in the specialized (sub-)class. * (c) isn't part of a DelayedInit subclass. */ - private def canBeSupplanted(sym: Symbol) = !isDelayedInitSubclass && isStationaryParamRef(sym) && !possiblySpecialized(sym) + private def canBeSupplanted(sym: Symbol) = !isDelayedInitSubclass && isStationaryParamRef(sym) && !specializeTypes.possiblySpecialized(sym) override def transform(tree: Tree): Tree = tree match { case Apply(Select(This(_), _), List()) => @@ -531,7 +529,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { gen.mkAttributedIdent(parameter(tree.symbol)) setPos tree.pos case Select(_, _) if guardSpecializedFieldInit => // reasoning behind this guard in the docu of `usesSpecializedField` - if (possiblySpecialized(tree.symbol)) { + if (specializeTypes.possiblySpecialized(tree.symbol)) { usesSpecializedField = true } super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 998f0b22cb..0050d08f1b 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -285,6 +285,19 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !tvar.isSpecialized || !isPrimitiveValueType(tpe)) yield tpe + /** Is `member` potentially affected by specialization? This is a gross overapproximation, + * but it should be okay for use outside of specialization. + */ + def possiblySpecialized(sym: Symbol) = specializedTypeVars(sym).nonEmpty + + /** Refines possiblySpecialized taking into account the instantiation of the specialized type variables at `site` */ + def isSpecializedIn(sym: Symbol, site: Type) = + specializedTypeVars(sym) exists { tvar => + val concretes = concreteTypes(tvar) + (concretes contains AnyRefClass) || (concretes contains site.memberType(tvar)) + } + + val specializedType = new TypeMap { override def apply(tp: Type): Type = tp match { case TypeRef(pre, sym, args) if args.nonEmpty => diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index afa0fc92ff..9c4b125fc1 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -77,8 +77,8 @@ abstract class UnCurry extends InfoTransform // We use Java's LambdaMetaFactory (LMF), which requires an interface for the sam's owner private def mustExpandFunction(fun: Function) = forceExpandFunction || { // (TODO: Can't use isInterface, yet, as it hasn't been updated for the new trait encoding) - val canUseLambdaMetaFactory = inConstructorFlag == 0 && (fun.attachments.get[SAMFunction].map(_.samTp) match { - case Some(userDefinedSamTp) => + val canUseLambdaMetaFactory = inConstructorFlag == 0 && (fun.attachments.get[SAMFunction] match { + case Some(SAMFunction(userDefinedSamTp, sam)) => val tpSym = erasure.javaErasure(userDefinedSamTp).typeSymbol // we only care about what ends up in the bytecode ( // LMF only supports interfaces @@ -90,7 +90,9 @@ abstract class UnCurry extends InfoTransform // to expand sam at compile time or use LMF, and this implementation restriction could be lifted. && tpSym.isStatic // impl restriction -- we currently use the boxed apply, so not really useful to allow specialized sam types (https://github.com/scala/scala/pull/4971#issuecomment-198119167) - && !tpSym.isSpecialized + // specialization and LMF are at odds, since LMF implements the single abstract method, + // but that's the one that specialization leaves generic, whereas we need to implement the specialized one to avoid boxing + && !specializeTypes.isSpecializedIn(sam, userDefinedSamTp) ) case _ => true // our built-in FunctionN's are suitable for LambdaMetaFactory by construction |