scala
9acab45aeead
Update ticket references and bugtracker URL [ci: last-only] (#5859)
Lukas Rytz
3 days ago
* Update URL to issue tracker * Change JIRA URLs to GitHub * Replace SI- by scala/bug# in comments * Replace SI- by scala/bug# string constants * Rename test files from SI-N / SI_N to tN ``` for f in $(find test -name 'SI_*' -or -name 'SI-*'); do n=$(basename $f); d=$(dirname $f); git mv $f $d/t${n:3}; done ```

30 31 32 33 34 35 36 37 38 39 40 41 42 30 31 32 33 34 35 36 37 38 39 40 41 42
The kind of code we can accept depends on the life cycle for the release you're targeting. The current maintenance release (2.11.x) cannot break source/binary compatibility, which means public APIs cannot change. It also means we are reluctant to change, e.g., type inference or implicit search, as this can have unforeseen consequences for source compatibility. #### Bug Fix
Prefix your commit title with "SI-NNNN", where https://issues.scala-lang.org/browse/SI-NNNN tracks the bug you're fixing. We also recommend naming your branch after the JIRA ticket number.
At the end of the commit message, include "Fixes scala/bug#NNNN", where https://github.com/scala/bug/issues/NNNN tracks the bug you're fixing. We also recommend naming your branch after the ticket number.
Please make sure the JIRA ticket's fix version corresponds to the upcoming milestone for the branch your PR targets. The CI automation will automatically assign the milestone after you open the PR.
Please make sure the ticket's milestone corresponds to the upcoming milestone for the branch your PR targets. The CI automation will automatically assign the milestone after you open the PR.
#### Enhancement or New Feature For longer-running development, likely required for this category of code contributions, we suggest you include "topic/" or "wip/" in your branch name, to indicate that this is work in progress, and that others should be prepared to rebase if they branch off your branch.
...
90 91 92 93 94 95 96 97 98 99 100 101 90 91 92 93 94 95 96 97 98 99 100
the first line of the commit as a description of the action performed by the commit on the code base, so use the active voice and the present tense. That also makes the commit subjects easy to reuse in release notes.
For a bugfix, the title must look like "SI-NNNN - don't crash when moon is in wrong phase".
For a bugfix, the end of the commit message should say "Fixes scala/bug#NNNN".
If a commit purely refactors and is not intended to change behaviour, say so. Backports should be tagged as "[backport]".

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
}, { matchName="scala.collection.mutable.ArrayOps#ofDouble.unzip3" problemName=IncompatibleMethTypeProblem },
// see SI-8200
// see scala/bug#8200
{ matchName="scala.reflect.api.StandardLiftables#StandardLiftableInstances.liftTree" problemName=MissingMethodProblem },
// see SI-8331
// see scala/bug#8331
{ matchName="scala.reflect.api.Internals#ReificationSupportApi#SyntacticTypeAppliedExtractor.unapply" problemName=IncompatibleResultTypeProblem }, {
...
141 142 143 144 145 146 147 148 149 150 151 141 142 143 144 145 146 147 148 149 150 151
}, { matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticSelectTerm" problemName=MissingMethodProblem },
// see SI-8366
// see scala/bug#8366
{ matchName="scala.reflect.api.Internals#ReificationSupportApi.SyntacticPartialFunction" problemName=MissingMethodProblem }, {
...
158 159 160 161 162 163 164 165 166 167 168 158 159 160 161 162 163 164 165 166 167 168
}, { matchName="scala.reflect.api.Mirror.weakTypeOf" problemName=MissingMethodProblem },
// see SI-8388
// see scala/bug#8388
{ matchName="scala.reflect.api.Internals$ReificationSupportApi$SyntacticIdentExtractor" problemName=MissingClassProblem }, {
...
199 200 201 202 203 204 205 206 207 208 209 199 200 201 202 203 204 205 206 207 208 209
}, { matchName="scala.reflect.runtime.SynchronizedOps.newNestedScope" problemName=MissingMethodProblem },
// https://github.com/scala/scala/pull/3848 -- SI-8680
// https://github.com/scala/scala/pull/3848 -- scala/bug#8680
{ matchName="scala.collection.immutable.Stream.scala$collection$immutable$Stream$$loop$6" problemName=MissingMethodProblem }, {
...
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
}, { matchName="scala.collection.immutable.Stream.scala$collection$immutable$Stream$$loop$4" problemName=MissingMethodProblem },
// SI-8946
// scala/bug#8946
{ matchName="scala.reflect.runtime.ThreadLocalStorage#MyThreadLocalStorage.values" problemName=MissingMethodProblem }, // the below method was the unused private (sic!) method but the compatibility checker was complaining about it { matchName="scala.reflect.io.ZipArchive.scala$reflect$io$ZipArchive$$walkIterator" problemName=MissingMethodProblem },
// SI-8362: AbstractPromise extends AtomicReference
// scala/bug#8362: AbstractPromise extends AtomicReference
// It's ok to change a package-protected class in an impl package, // even though it's not clear why it changed -- bug in generic signature generation? // -public class scala.concurrent.impl.Promise$DefaultPromise<T> extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise<T> // +public class scala.concurrent.impl.Promise$DefaultPromise<T extends java.lang.Object> extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise<T> { matchName="scala.concurrent.impl.Promise$DefaultPromise" problemName=MissingTypesProblem },
// SI-9488: Due to SI-8362 above, toString was silently changed to the AtomicReference toString implementation, // This is fixed by SI-9488, and this should be safe since the class in question is stdlib internal.
// scala/bug#9488: Due to scala/bug#8362 above, toString was silently changed to the AtomicReference toString implementation, // This is fixed by scala/bug#9488, and this should be safe since the class in question is stdlib internal.
{ matchName="scala.concurrent.impl.Promise.toString" problemName=MissingMethodProblem } ]

164 165 166 167 168 169 170 171 172 173 174 175 164 165 166 167 168 169 170 171 172 173 174 175
<scm> <connection>scm:git:git://github.com/scala/scala.git</connection> <url>https://github.com/scala/scala.git</url> </scm> <issueManagement>
<system>JIRA</system> <url>https://issues.scala-lang.org/</url>
<system>GitHub</system> <url>https://github.com/scala/bug/issues</url>
</issueManagement> <developers> <developer> <id>lamp</id> <name>LAMP/EPFL</name>

1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11
Scala Distribution ------------------ The Scala distribution requires Java 1.8 or above.
Please report bugs at https://issues.scala-lang.org/.
Please report bugs at https://github.com/scala/bug/issues.
We welcome contributions at https://github.com/scala/scala! Scala Tools -----------

79 80 81 82 83 84 85 86 87 88 89 79 80 81 82 83 84 85 86 87 88 89
optFile getOrElse sys.error("Could not resolve previous artifact: " + m) } }
// use the SI-7934 workaround to silence a deprecation warning on an sbt API
// use the scala/bug#7934 workaround to silence a deprecation warning on an sbt API
// we have no choice but to call. on the lack of any suitable alternative, // see https://gitter.im/sbt/sbt-dev?at=5616e2681b0e279854bd74a4 : // "it's my intention to eventually come up with a public API" says Eugene Y object Deprecated { @deprecated("", "") class Inner {

21 22 23 24 25 26 27 28 29 30 31 21 22 23 24 25 26 27 28 29 30 31
UnicodeEscape ::= ‘\’ ‘u’ {‘u’} hexDigit hexDigit hexDigit hexDigit hexDigit ::= ‘0’ | … | ‘9’ | ‘A’ | … | ‘F’ | ‘a’ | … | ‘f’ ``` <!--
TODO SI-4583: UnicodeEscape used to allow additional backslashes,
TODO scala/bug#4583: UnicodeEscape used to allow additional backslashes,
and there is something in the code `evenSlashPrefix` that alludes to it, but I can't make it work nor can I imagine how this would make sense, so I removed it for now. -->

71 72 73 74 75 76 77 78 79 80 81 71 72 73 74 75 76 77 78 79 80 81
} } // aXXX (e.g. aparamss) => characteristics of the actual macro impl signature extracted from the macro impl ("a" stands for "actual") // rXXX (e.g. rparamss) => characteristics of the reference macro impl signature synthesized from the macro def ("r" stands for "reference")
// FIXME: cannot write this concisely because of SI-7507
// FIXME: cannot write this concisely because of scala/bug#7507
//lazy val MacroImplSig(atparams, aparamss, aret) = macroImplSig //lazy val MacroImplSig(_, rparamss, rret) = referenceMacroImplSig lazy val atparams = macroImplSig.tparams lazy val aparamss = macroImplSig.paramss lazy val aret = macroImplSig.ret

29 30 31 32 33 34 35 36 37 38 39 40 41 29 30 31 32 33 34 35 36 37 38 39 40 41
// but even for def macros this can lead to unexpected troubles. Imagine that one Global // creates a term of an anonymous type with a member featuring a "fresh" name, and then another Global // imports that term with a wildcard and then generates a "fresh" name of its own. Given unlucky // circumstances these "fresh" names might end up clashing. //
// TODO: hopefully SI-7823 will provide an ultimate answer to this problem. // In the meanwhile I will also keep open the original issue: SI-6879 "c.freshName is broken". val prefix = if (name.endsWith("$")) name else name + "$" // SI-8425
// TODO: hopefully scala/bug#7823 will provide an ultimate answer to this problem. // In the meanwhile I will also keep open the original issue: scala/bug#6879 "c.freshName is broken". val prefix = if (name.endsWith("$")) name else name + "$" // scala/bug#8425
val sortOfUniqueSuffix = freshNameCreator.newName(nme.FRESH_SUFFIX) prefix + sortOfUniqueSuffix } def freshName[NameType <: Name](name: NameType): NameType =

83 84 85 86 87 88 89 90 91 92 93 83 84 85 86 87 88 89 90 91 92 93
} // tq"$a => $b" override def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree = FunctionTypePlaceholder(argtpes, restpe)
// make q"val (x: T) = rhs" be equivalent to q"val x: T = rhs" for sake of bug compatibility (SI-8211)
// make q"val (x: T) = rhs" be equivalent to q"val x: T = rhs" for sake of bug compatibility (scala/bug#8211)
override def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree) = pat match { case TuplePlaceholder(inParensPat :: Nil) => super.makePatDef(mods, inParensPat, rhs) case _ => super.makePatDef(mods, pat, rhs) } }

71 72 73 74 75 76 77 78 79 80 81 71 72 73 74 75 76 77 78 79 80 81
* object B { object B } => selectType(staticModule("B"), "B") * object B { package B } => impossible */ val hasPackagelessParent = sym.ownerChain.tail.tail exists (_.isEmptyPackageClass) if (sym.isStatic && (sym.isClass || sym.isModule) && !hasPackagelessParent) {
// SI-6238: if applicable, emit references to StandardDefinitions instead of staticClass/staticModule calls
// scala/bug#6238: if applicable, emit references to StandardDefinitions instead of staticClass/staticModule calls
val resolver = if (sym.isType) nme.staticClass else nme.staticModule mirrorMirrorCall(resolver, reify(sym.fullName)) } else { if (reifyDebug) println("Locatable: %s (%s) owned by %s (%s) at %s".format(sym, sym.accurateKindString, sym.owner, sym.owner.accurateKindString, sym.owner.fullNameString)) val rowner = reify(sym.owner)

23 24 25 26 27 28 29 30 31 32 33 23 24 25 26 27 28 29 30 31 32 33
// this is a very special case. see the comments below for more info. if (isSemiConcreteTypeMember(tpe)) return reifySemiConcreteTypeMember(tpe)
// SI-6242: splicing might violate type bounds
// scala/bug#6242: splicing might violate type bounds
val spliced = spliceType(tpe) if (spliced != EmptyTree) return spliced val tsym = tpe.typeSymbolDirect

26 27 28 29 30 31 32 33 34 35 36 26 27 28 29 30 31 32 33 34 35 36
import global._ import definitions.JavaUniverseClass val enclosingErasure = { val rClassTree = reifyEnclosingRuntimeClass(global)(typer0)
// HACK around SI-6259
// HACK around scala/bug#6259
// If we're in the constructor of an object or others don't have easy access to `this`, we have no good way to grab // the class of that object. Instead, we construct an anonymous class and grab his class file, assuming // this is enough to get the correct class loadeer for the class we *want* a mirror for, the object itself. rClassTree orElse Apply(Select(gen.mkAnonymousNew(Nil), sn.GetClass), Nil) }
...
49 50 51 52 53 54 55 56 57 58 59 49 50 51 52 53 54 55 56 57 58 59
def reifyRuntimeClass(global: Global)(typer0: global.analyzer.Typer, tpe0: global.Type, concrete: Boolean = true): global.Tree = { import global._ import definitions._ import analyzer.enclosingMacroPosition
// SI-7375
// scala/bug#7375
val tpe = tpe0.dealiasWiden if (tpe.isSpliceable) { val classTagInScope = typer0.resolveClassTag(enclosingMacroPosition, tpe, allowMaterialization = false) if (!classTagInScope.isEmpty) return Select(classTagInScope, nme.runtimeClass)

20 21 22 23 24 25 26 27 28 29 30 20 21 22 23 24 25 26 27 28 29 30
* * Replacing type trees with TypeTree(tpe) * * Reassembling CompoundTypeTrees into reifiable form * * Transforming Modifiers.annotations into Symbol.annotations * * Transforming Annotated annotations into AnnotatedType annotations * * Transforming Annotated(annot, expr) into Typed(expr, TypeTree(Annotated(annot, _))
* * Non-idempotencies of the typechecker: https://issues.scala-lang.org/browse/SI-5464
* * Non-idempotencies of the typechecker: https://github.com/scala/bug/issues/5464
*/ val reshape = new Transformer { var currentSymbol: Symbol = NoSymbol override def transform(tree0: Tree) = {
...
124 125 126 127 128 129 130 131 132 133 134 124 125 126 127 128 129 130 131 132 133 134
* However if the type involves a symbol declared inside the quasiquote (i.e. registered in `boundSyms`), * then we cannot reify it, or otherwise subsequent reflective compilation will fail. * * Why will it fail? Because reified deftrees (e.g. ClassDef(...)) will generate fresh symbols during that compilation, * so naively reified symbols will become out of sync, which brings really funny compilation errors and/or crashes, e.g.:
* https://issues.scala-lang.org/browse/SI-5230
* https://github.com/scala/bug/issues/5230
* * To deal with this unpleasant fact, we need to fall back from types to equivalent trees (after all, parser trees don't contain any types, just trees, so it should be possible). * Luckily, these original trees get preserved for us in the `original` field when Trees get transformed into TypeTrees. * And if an original of a type tree is empty, we can safely assume that this type is non-essential (e.g. was inferred/generated by the compiler). * In that case the type can be omitted (e.g. reified as an empty TypeTree), since it will be inferred again later on.

153 154 155 156 157 158 159 160 161 162 163 153 154 155 156 157 158 159 160 161 162 163
val cumulativeAliases = mutable.ArrayBuffer[(Symbol, TermName)](symtab0.aliases: _*) def fillInSymbol(sym: Symbol): Tree = { if (reifyDebug) println("Filling in: %s (%s)".format(sym, sym.accurateKindString)) val isFreeTerm = FreeTermDef.unapply(currtab.symDef(sym)).isDefined
// SI-6204 don't reify signatures for incomplete symbols, because this might lead to cyclic reference errors
// scala/bug#6204 don't reify signatures for incomplete symbols, because this might lead to cyclic reference errors
val signature = if (sym.isInitialized) { if (sym.isCapturedVariable) capturedVariableType(sym) else if (isFreeTerm) sym.tpe else sym.info

7 8 9 10 11 12 13 14 15 16 17 7 8 9 10 11 12 13 14 15 16 17
# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. ############################################################################## findScalaHome () {
# see SI-2092 and SI-5792
# see scala/bug#2092 and scala/bug#5792
local source="${BASH_SOURCE[0]}" while [ -h "$source" ] ; do local linked="$(readlink "$source")" local dir="$( cd -P $(dirname "$source") && cd -P $(dirname "$linked") && pwd )" source="$dir/$(basename "$linked")"
...
90 91 92 93 94 95 96 97 98 99 100 90 91 92 93 94 95 96 97 98 99 100
# Constructing the extension classpath TOOL_CLASSPATH="@classpath@" if [[ -z "$TOOL_CLASSPATH" ]]; then for ext in "$SCALA_HOME"/lib/* ; do file_extension="${ext##*.}"
# SI-8967 Only consider directories and files named '*.jar'
# scala/bug#8967 Only consider directories and files named '*.jar'
if [[ -d "$ext" || $file_extension == "jar" ]]; then if [[ -z "$TOOL_CLASSPATH" ]]; then TOOL_CLASSPATH="$ext" else TOOL_CLASSPATH="${TOOL_CLASSPATH}${SEP}${ext}"
...
131 132 133 134 135 136 137 138 139 140 141 131 132 133 134 135 136 137 138 139 140 141
# so they reach the underlying JVM in time to do some good. The # -D options will be available as system properties. declare -a java_args declare -a scala_args
# SI-8358, SI-8368 -- the default should really be false,
# scala/bug#8358, scala/bug#8368 -- the default should really be false,
# but I don't want to flip the default during 2.11's RC cycle OVERRIDE_USEJAVACP="-Dscala.usejavacp=true" while [[ $# -gt 0 ]]; do case "$1" in

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
setlocal enableextensions enabledelayedexpansion set _LINE_TOOLCP= rem Use "%~1" to handle spaces in paths. See http://ss64.com/nt/syntax-args.html
rem SI-7295 The goto here is needed to avoid problems with `scala Script.cmd "arg(with)paren"`, rem we must not evaluate %~2 eagerly, but delayed expansion doesn't seem to allow rem removal of quotation marks.
rem scala/bug#7295 The goto here is needed to avoid problems with `scala Script.cmd "arg(with)paren"`, rem we must not evaluate %~2 eagerly, but delayed expansion doesn't seem to allow rem removal of quotation marks.
if not [%~1]==[-toolcp] ( goto :notoolcp ) shift set _LINE_TOOLCP=%~1 shift :notoolcp
rem SI-8358, SI-8368 -- the default should really be false,
rem scala/bug#8358, scala/bug#8368 -- the default should really be false,
rem but I don't want to flip the default during 2.11's RC cycle set _OVERRIDE_USEJAVACP="-Dscala.usejavacp=true" rem We keep in _JAVA_PARAMS all -J-prefixed and -D-prefixed arguments set _JAVA_PARAMS=

50 51 52 53 54 55 56 57 58 59 60 50 51 52 53 54 55 56 57 58 59 60
/** Note: depends now contains toplevel classes. * To get their sourcefiles, you need to dereference with .sourcefile */ private[this] val _depends = mutable.HashSet[Symbol]()
// sbt compatibility (SI-6875)
// sbt compatibility (scala/bug#6875)
// // imagine we have a file named A.scala, which defines a trait named Foo and a module named Main // Main contains a call to a macro, which calls compileLate to define a mock for Foo // compileLate creates a virtual file Virt35af32.scala, which contains a class named FooMock extending Foo, // and macro expansion instantiates FooMock. the stage is now set. let's see what happens next.

107 108 109 110 111 112 113 114 115 116 117 107 108 109 110 111 112 113 114 115 116 117
} with JavaPlatform type ThisPlatform = JavaPlatform { val global: Global.this.type } lazy val platform: ThisPlatform = new GlobalPlatform /* A hook for the REPL to add a classpath entry containing products of previous runs to inliner's bytecode repository*/
// Fixes SI-8779
// Fixes scala/bug#8779
def optimizerClassPath(base: ClassPath): ClassPath = base def classPath: ClassPath = platform.classPath // sub-components --------------------------------------------------

74 75 76 77 78 79 80 81 82 83 84 74 75 76 77 78 79 80 81 82 83 84
else DocComment(docStr).template ownComment = replaceInheritDocToInheritdoc(ownComment) superComment(sym) match { case None =>
// SI-8210 - The warning would be false negative when this symbol is a setter
// scala/bug#8210 - The warning would be false negative when this symbol is a setter
if (ownComment.indexOf("@inheritdoc") != -1 && ! sym.isSetter) reporter.warning(sym.pos, s"The comment for ${sym} contains @inheritdoc, but no parent comment is available to inherit from.") ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>") case Some(sc) => if (ownComment == "") sc

144 145 146 147 148 149 150 151 152 153 154 144 145 146 147 148 149 150 151 152 153 154
str.append(name).append(" = ").append(value) } str.toString } def printModifiers(tree: MemberDef) {
// SI-5885: by default this won't print annotations of not yet initialized symbols
// scala/bug#5885: by default this won't print annotations of not yet initialized symbols
val annots0 = tree.symbol.annotations match { case Nil => tree.mods.annotations case xs => xs map annotationInfoToString } val annots = annots0 match {

72 73 74 75 76 77 78 79 80 81 82 72 73 74 75 76 77 78 79 80 81 82
case _ => None } } }
// TODO these overrides, and the slow trickle of bugs that they solve (e.g. SI-8479),
// TODO these overrides, and the slow trickle of bugs that they solve (e.g. scala/bug#8479),
// suggest that we should pursue an alternative design in which the DocDef nodes // are eliminated from the tree before typer, and instead are modelled as tree // attachments. /** Is tree legal as a member definition of an interface?

187 188 189 190 191 192 193 194 195 196 197 198 187 188 189 190 191 192 193 194 195 196 197 198
// // def resetAllAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(localOnly = false, leaveAlone).transform(x) // upd. Unfortunately this didn't work out quite as we expected. The last two users of resetAllAttrs: // reification and typedLabelDef broke in very weird ways when we replaced resetAllAttrs with resetLocalAttrs
// (see SI-8316 change from resetAllAttrs to resetLocalAttrs in reifiers broke Slick and // SI-8318 NPE in mixin in scala-continuations for more information).
// (see scala/bug#8316 change from resetAllAttrs to resetLocalAttrs in reifiers broke Slick and // scala/bug#8318 NPE in mixin in scala-continuations for more information).
// Given that we're supposed to release 2.11.0-RC1 in less than a week, I'm temporarily reinstating resetAllAttrs // until we have time to better understand what's going on. In order to dissuade people from using it, // it now comes with a new, ridiculous name. /** @see ResetAttrs */ def brutallyResetAttrs(x: Tree, leaveAlone: Tree => Boolean = null): Tree = new ResetAttrs(brutally = true, leaveAlone).transform(x)
...
291 292 293 294 295 296 297 298 299 300 301 302 291 292 293 294 295 296 297 298 299 300 301 302
val dupl = tree.duplicate // Typically the resetAttrs transformer cleans both symbols and types. // However there are exceptions when we cannot erase symbols due to idiosyncrasies of the typer. // vetoXXX local variables declared below describe the conditions under which we cannot erase symbols. //
// The first reason to not erase symbols is the threat of non-idempotency (SI-5464). // Here we take care of references to package classes (SI-5705).
// The first reason to not erase symbols is the threat of non-idempotency (scala/bug#5464). // Here we take care of references to package classes (scala/bug#5705).
// There are other non-idempotencies, but they are not worked around yet. // // The second reason has to do with the fact that resetAttrs needs to be less destructive. // Erasing locally-defined symbols is useful to prevent tree corruption, but erasing external bindings is not, // therefore we want to retain those bindings, especially given that restoring them can be impossible

1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
def identForType(skipIt: Boolean): TypeName = ident(skipIt).toTypeName def identOrMacro(): Name = if (isMacro) rawIdent() else ident() def selector(t: Tree): Tree = {
val point = if(isIdent) in.offset else in.lastOffset //SI-8459
val point = if(isIdent) in.offset else in.lastOffset //scala/bug#8459
//assert(t.pos.isDefined, t) if (t != EmptyTree) Select(t, ident(skipIt = false)) setPos r2p(t.pos.start, point, in.lastOffset) else errorTermTree // has already been reported
...
1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981
* }}} */ def pattern3(): Tree = { val top = simplePattern(badPattern3) val base = opstack
// See SI-3189, SI-4832 for motivation. Cf SI-3480 for counter-motivation.
// See scala/bug#3189, scala/bug#4832 for motivation. Cf scala/bug#3480 for counter-motivation.
def isCloseDelim = in.token match { case RBRACE => isXML case RPAREN => !isXML case _ => false }

65 66 67 68 69 70 71 72 73 74 75 65 66 67 68 69 70 71 72 73 74 75
case Assign(lhs @ Select(qual, _), rhs) => val isStatic = lhs.symbol.isStaticMember if (!isStatic) { genLoadQualifier(lhs) } genLoad(rhs, symInfoTK(lhs.symbol)) lineNumber(tree)
// receiverClass is used in the bytecode to access the field. using sym.owner may lead to IllegalAccessError, SI-4283
// receiverClass is used in the bytecode to access the field. using sym.owner may lead to IllegalAccessError, scala/bug#4283
val receiverClass = qual.tpe.typeSymbol fieldStore(lhs.symbol, receiverClass) case Assign(lhs, rhs) => val s = lhs.symbol
...
329 330 331 332 333 334 335 336 337 338 339 329 330 331 332 333 334 335 336 337 338 339
case Select(qualifier, _) => val sym = tree.symbol generatedType = symInfoTK(sym) val qualSafeToElide = treeInfo isQualifierSafeToElide qualifier def genLoadQualUnlessElidable() { if (!qualSafeToElide) { genLoadQualifier(tree) } }
// receiverClass is used in the bytecode to access the field. using sym.owner may lead to IllegalAccessError, SI-4283
// receiverClass is used in the bytecode to access the field. using sym.owner may lead to IllegalAccessError, scala/bug#4283
def receiverClass = qualifier.tpe.typeSymbol if (sym.isModule) { genLoadQualUnlessElidable() genLoadModule(tree) } else if (sym.isStaticMember) {
...
937 938 939 940 941 942 943 944 945 946 947 948 937 938 939 940 941 942 943 944 945 946 947 948
def genLoadModule(tree: Tree): BType = { val module = ( if (!tree.symbol.isPackageClass) tree.symbol else tree.symbol.info.packageObject match {
case NoSymbol => abort(s"SI-5604: Cannot use package as value: $tree") case s => abort(s"SI-5604: found package class where package object expected: $tree")
case NoSymbol => abort(s"scala/bug#5604: Cannot use package as value: $tree") case s => abort(s"scala/bug#5604: found package class where package object expected: $tree")
} ) lineNumber(tree) genLoadModule(module) symInfoTK(module)
...
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312
} else if (isNull(r)) { // expr == null -> expr eq null genLoad(l, ObjectRef) genCZJUMP(success, failure, TestOp.EQ, ObjectRef, targetIfNoJump) } else if (isNonNullExpr(l)) {
// SI-7852 Avoid null check if L is statically non-null.
// scala/bug#7852 Avoid null check if L is statically non-null.
genLoad(l, ObjectRef) genLoad(r, ObjectRef) genCallMethod(Object_equals, InvokeStyle.Virtual, pos) genCZJUMP(success, failure, TestOp.NE, BOOL, targetIfNoJump) } else {

84 85 86 87 88 89 90 91 92 93 94 84 85 86 87 88 89 90 91 92 93 94
def nextEnclosing(sym: Symbol): Symbol = { val origOwner = sym.originalOwner // phase travel necessary: after flatten, the name includes the name of outer classes. // if some outer name contains $anon, a non-anon class is considered anon. if (delambdafyInline() && exitingPickler(sym.rawowner.isAnonymousFunction)) {
// SI-9105: special handling for anonymous functions under delambdafy:inline.
// scala/bug#9105: special handling for anonymous functions under delambdafy:inline.
// // class C { def t = () => { def f { class Z } } } // // class C { def t = byNameMethod { def f { class Z } } } //
...
218 219 220 221 222 223 224 225 226 227 228 218 219 220 221 222 223 224 225 226 227 228
*/ def isOriginallyStaticOwner(sym: Symbol): Boolean = sym.isPackageClass || sym.isModuleClass && isOriginallyStaticOwner(sym.originalOwner) /**
* This is a hack to work around SI-9111. The completer of `methodSym` may report type errors. We
* This is a hack to work around scala/bug#9111. The completer of `methodSym` may report type errors. We
* cannot change the typer context of the completer at this point and make it silent: the context * captured when creating the completer in the namer. However, we can temporarily replace * global.reporter (it's a var) to store errors. */ def completeSilentlyAndCheckErroneous(sym: Symbol): Boolean =
...
264 265 266 267 268 269 270 271 272 273 274 264 265 266 267 268 269 270 271 272 273 274
// ----------------------------------------------------------------------------------------- // finding the least upper bound in agreement with the bytecode verifier (given two internal names handed by ASM) // Background: // http://gallium.inria.fr/~xleroy/publi/bytecode-verification-JAR.pdf // http://comments.gmane.org/gmane.comp.java.vm.languages/2293
// https://issues.scala-lang.org/browse/SI-3872
// https://github.com/scala/bug/issues/3872
// ----------------------------------------------------------------------------------------- /* An `asm.ClassWriter` that uses `jvmWiseLUB()` * The internal name of the least common ancestor of the types given by inameA and inameB. * It's what ASM needs to know in order to compute stack map frames, http://asm.ow2.org/doc/developer-guide.html#controlflow
...
577 578 579 580 581 582 583 584 585 586 587 577 578 579 580 581 582 583 584 585 586 587
private def isRuntimeVisible(annot: AnnotationInfo): Boolean = { annot.atp.typeSymbol.getAnnotation(AnnotationRetentionAttr) match { case Some(retentionAnnot) => retentionAnnot.assocs.contains(nme.value -> LiteralAnnotArg(Constant(AnnotationRetentionPolicyRuntimeValue))) case _ =>
// SI-8926: if the annotation class symbol doesn't have a @RetentionPolicy annotation, the
// scala/bug#8926: if the annotation class symbol doesn't have a @RetentionPolicy annotation, the
// annotation is emitted with visibility `RUNTIME` true } }
...
826 827 828 829 830 831 832 833 834 835 836 826 827 828 829 830 831 832 833 834 835 836
if(!isValidSignature) { reporter.warning(sym.pos, sm"""|compiler bug: created invalid generic signature for $sym in ${sym.owner.skipPackageObject.fullName} |signature: $sig
|if this is reproducible, please report bug at https://issues.scala-lang.org/
|if this is reproducible, please report bug at https://github.com/scala/bug/issues
""".trim) return null } }
...
842 843 844 845 846 847 848 849 850 851 852 842 843 844 845 846 847 848 849 850 851 852
sm"""|compiler bug: created generic signature for $sym in ${sym.owner.skipPackageObject.fullName} that does not conform to its erasure |signature: $sig |original type: $memberTpe |normalized type: $normalizedTpe |erasure type: $bytecodeTpe
|if this is reproducible, please report bug at http://issues.scala-lang.org/
|if this is reproducible, please report bug at https://github.com/scala/bug/issues
""".trim) return null } }
...
884 885 886 887 888 889 890 891 892 893 894 884 885 886 887 888 889 890 891 892 893 894
* * must-single-thread */ private def addForwarder(isRemoteClass: Boolean, jclass: asm.ClassVisitor, moduleClass: Symbol, m: Symbol): Unit = { def staticForwarderGenericSignature: String = {
// SI-3452 Static forwarder generation uses the same erased signature as the method if forwards to.
// scala/bug#3452 Static forwarder generation uses the same erased signature as the method if forwards to.
// By rights, it should use the signature as-seen-from the module class, and add suitable // primitive and value-class boxing/unboxing. // But for now, just like we did in mixin, we just avoid writing a wrong generic signature // (one that doesn't erase to the actual signature). See run/t3452b for a test case. val memberTpe = enteringErasure(moduleClass.thisType.memberInfo(m))
...
903 904 905 906 907 908 909 910 911 912 913 903 904 905 906 907 908 909 910 911 912 913
val paramJavaTypes: List[BType] = methodInfo.paramTypes map typeToBType // val paramNames = 0 until paramJavaTypes.length map ("x_" + _) /* Forwarders must not be marked final, * as the JVM will not allow redefinition of a final static method,
* and we don't know what classes might be subclassing the companion class. See SI-4827.
* and we don't know what classes might be subclassing the companion class. See scala/bug#4827.
*/ // TODO: evaluate the other flags we might be dropping on the floor here. // TODO: ACC_SYNTHETIC ? val flags = GenBCode.PublicStatic | ( if (m.isVarargsMethod) asm.Opcodes.ACC_VARARGS else 0

336 337 338 339 340 341 342 343 344 345 346 336 337 338 339 340 341 342 343 344 345 346
// can-multi-thread final def newarray(elem: BType) { elem match { case c: RefBType =>
/* phantom type at play in `Array(null)`, SI-1513. On the other hand, Array(()) has element type `scala.runtime.BoxedUnit` which isObject. */
/* phantom type at play in `Array(null)`, scala/bug#1513. On the other hand, Array(()) has element type `scala.runtime.BoxedUnit` which isObject. */
jmethod.visitTypeInsn(Opcodes.ANEWARRAY, c.classOrArrayType) case _ => assert(elem.isNonVoidPrimitiveType) val rand = { // using `asm.Type.SHORT` instead of `BType.SHORT` because otherwise "warning: could not emit switch for @switch annotated match"
...
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463
j += 1 } i += 1 }
// check for duplicate keys to avoid "VerifyError: unsorted lookupswitch" (SI-6011)
// check for duplicate keys to avoid "VerifyError: unsorted lookupswitch" (scala/bug#6011)
i = 1 while (i < keys.length) { if (keys(i-1) == keys(i)) {
abort("duplicate keys in SWITCH, can't pick arbitrarily one of them to evict, see SI-6011.")
abort("duplicate keys in SWITCH, can't pick arbitrarily one of them to evict, see scala/bug#6011.")
} i += 1 } val keyMin = keys(0)

562 563 564 565 566 567 568 569 570 571 572 562 563 564 565 566 567 568 569 570 571 572
val params = if (vparamss.isEmpty) Nil else vparamss.head for (p <- params) { locals.makeLocal(p.symbol) } // debug assert((params.map(p => locals(p.symbol).tk)) == asmMethodType(methSymbol).getArgumentTypes.toList, "debug") if (params.size > MaximumJvmParameters) {
// SI-7324
// scala/bug#7324
reporter.error(methSymbol.pos, s"Platform restriction: a parameter list's length cannot exceed $MaximumJvmParameters.") return } val isNative = methSymbol.hasAnnotation(definitions.NativeAttr)

107 108 109 110 111 112 113 114 115 116 117 107 108 109 110 111 112 113 114 115 116 117
} /* * Detects whether no instructions have been emitted since label `lbl` and if so emits a NOP. * Useful to avoid emitting an empty try-block being protected by exception handlers,
* which results in "java.lang.ClassFormatError: Illegal exception table range". See SI-6102.
* which results in "java.lang.ClassFormatError: Illegal exception table range". See scala/bug#6102.
*/ def nopIfNeeded(lbl: asm.Label) { val noInstructionEmitted = isAtProgramPoint(lbl) if (noInstructionEmitted) { emit(asm.Opcodes.NOP) } }
...
142 143 144 145 146 147 148 149 150 151 152 142 143 144 145 146 147 148 149 150 151 152
* * Sidenote: * A try-clause may contain an empty block. On CLR, a finally-block has special semantics * regarding Abort interruptions; but on the JVM it's safe to elide an exception-handler * that protects an "empty" range ("empty" as in "containing NOPs only",
* see `asm.optimiz.DanglingExcHandlers` and SI-6720).
* see `asm.optimiz.DanglingExcHandlers` and scala/bug#6720).
* * This means a finally-block indicates instructions that can be reached: * (b.1) Upon normal (non-early-returning) completion of the try-clause or a catch-clause * In this case, the next-program-point is that following the try-catch-finally expression. * (b.2) Upon early-return initiated in the try-clause or a catch-clause

843 844 845 846 847 848 849 850 851 852 853 843 844 845 846 847 848 849 850 851 852 853
* ClassBType is extracted from compiler symbols and types, see BTypesFromSymbols. * * The `info` field contains either the class information on an error message why the info could * not be computed. There are two reasons for an erroneous info: * 1. The ClassBType was built from a class symbol that stems from a java source file, and the
* symbol's type could not be completed successfully (SI-9111)
* symbol's type could not be completed successfully (scala/bug#9111)
* 2. The ClassBType should be built from a classfile, but the class could not be found on the * compilation classpath. * * Note that all ClassBTypes required in a non-optimized run are built during code generation from * the class symbols referenced by the ASTs, so they have a valid info. Therefore the backend
...
955 956 957 958 959 960 961 962 963 964 965 955 956 957 958 959 960 961 962 963 964 965
) }) def inlineInfoAttribute: Either[NoClassBTypeInfo, InlineInfoAttribute] = info.map(i => { // InlineInfos are serialized for classes being compiled. For those the info was built by
// buildInlineInfoFromClassSymbol, which only adds a warning under SI-9111, which in turn
// buildInlineInfoFromClassSymbol, which only adds a warning under scala/bug#9111, which in turn
// only happens for class symbols of java source files. // we could put this assertion into InlineInfoAttribute, but it is more safe to put it here // where it affect only GenBCode, and not add any assertion to GenASM in 2.11.6. assert(i.inlineInfo.warning.isEmpty, i.inlineInfo.warning) InlineInfoAttribute(i.inlineInfo)
...
987 988 989 990 991 992 993 994 995 996 997 987 988 989 990 991 992 993 994 995 996 997
/** * Finding the least upper bound in agreement with the bytecode verifier * Background: * http://gallium.inria.fr/~xleroy/publi/bytecode-verification-JAR.pdf * http://comments.gmane.org/gmane.comp.java.vm.languages/2293
* https://issues.scala-lang.org/browse/SI-3872
* https://github.com/scala/bug/issues/3872
*/ def jvmWiseLUB(other: ClassBType): Either[NoClassBTypeInfo, ClassBType] = { def isNotNullOrNothing(c: ClassBType) = !c.isNullType && !c.isNothingType assert(isNotNullOrNothing(this) && isNotNullOrNothing(other), s"jvmWiseLUB for null or nothing: $this - $other")
...
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022
case _ => // TODO @lry I don't really understand the reasoning here. // Both this and other are classes. The code takes (transitively) all superclasses and // finds the first common one. // MOST LIKELY the answer can be found here, see the comments and links by Miguel:
// - https://issues.scala-lang.org/browse/SI-3872
// - https://github.com/scala/bug/issues/3872
firstCommonSuffix(this :: this.superClassesTransitive.orThrow, other :: other.superClassesTransitive.orThrow) } assert(isNotNullOrNothing(res), s"jvmWiseLUB computed: $res") Right(res)

101 102 103 104 105 106 107 108 109 110 111 101 102 103 104 105 106 107 108 109 110 111
final def classBTypeFromSymbol(sym: Symbol): ClassBType = { // For each java class, the scala compiler creates a class and a module (thus a module class). // If the `sym` is a java module class, we use the java class instead. This ensures that the // ClassBType is created from the main class (instead of the module class). // The two symbols have the same name, so the resulting internalName is the same.
// Phase travel (exitingPickler) required for SI-6613 - linkedCoC is only reliable in early phases (nesting)
// Phase travel (exitingPickler) required for scala/bug#6613 - linkedCoC is only reliable in early phases (nesting)
val classSym = if (sym.isJavaDefined && sym.isModuleClass) exitingPickler(sym.linkedClassOfClass) else sym assert(classSym != NoSymbol, "Cannot create ClassBType from NoSymbol") assert(classSym.isClass, s"Cannot create ClassBType from non-class symbol $classSym") if (global.settings.debug) {
...
201 202 203 204 205 206 207 208 209 210 211 212 213 214 201 202 203 204 205 206 207 208 209 210 211 212 213 214
*/ case tp => warning(tp.typeSymbol.pos, s"an unexpected type representation reached the compiler backend while compiling $currentUnit: $tp. " +
"If possible, please file a bug on issues.scala-lang.org.")
"If possible, please file a bug on https://github.com/scala/bug/issues.")
tp match {
case ThisType(ArrayClass) => ObjectRef // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test
case ThisType(ArrayClass) => ObjectRef // was introduced in 9b17332f11 to fix scala/bug#999, but this code is not reached in its test, or any other test
case ThisType(sym) => classBTypeFromSymbol(sym) case SingleType(_, sym) => primitiveOrClassToBType(sym) case ConstantType(_) => typeToBType(t.underlying) case RefinedType(parents, _) => parents.map(typeToBType(_).asClassBType).reduceLeft((a, b) => a.jvmWiseLUB(b).get) case AnnotatedType(_, t) => typeToBType(t)
...
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
def newParentForAnnotation(ann: AnnotationInfo): Option[Type] = ann.symbol match { case RemoteAttr => Some(RemoteInterfaceClass.tpe) case _ => None }
// SI-9393: java annotations are interfaces, but the classfile / java source parsers make them look like classes.
// scala/bug#9393: java annotations are interfaces, but the classfile / java source parsers make them look like classes.
def isInterfaceOrTrait(sym: Symbol) = sym.isInterface || sym.isTrait || sym.hasJavaAnnotationFlag val classParents = { val parents = classSym.info.parents
// SI-9393: the classfile / java source parsers add Annotation and ClassfileAnnotation to the
// scala/bug#9393: the classfile / java source parsers add Annotation and ClassfileAnnotation to the
// parents of a java annotations. undo this for the backend (where we need classfile-level information). if (classSym.hasJavaAnnotationFlag) parents.filterNot(c => c.typeSymbol == ClassfileAnnotationClass || c.typeSymbol == AnnotationClass) else parents }
...
307 308 309 310 311 312 313 314 315 316 317 307 308 309 310 311 312 313 314 315 316 317
// Java enums for exhaustiveness checking. val hasAbstractMethod = classSym.info.decls.exists(s => s.isMethod && s.isDeferred) if (hasAbstractMethod) ACC_ABSTRACT else 0 } GenBCode.mkFlags(
// SI-9393: the classfile / java source parser make java annotation symbols look like classes.
// scala/bug#9393: the classfile / java source parser make java annotation symbols look like classes.
// here we recover the actual classfile flags. if (classSym.hasJavaAnnotationFlag) ACC_ANNOTATION | ACC_INTERFACE | ACC_ABSTRACT else 0, if (classSym.isPublic) ACC_PUBLIC else 0, if (classSym.isFinal) ACC_FINAL else 0, // see the link above. javac does the same: ACC_SUPER for all classes, but not interfaces.
...
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
if (classSym.isArtifact) ACC_SYNTHETIC else 0, if (classSym.hasJavaEnumFlag) enumFlags else 0 ) }
// Check for hasAnnotationFlag for SI-9393: the classfile / java source parsers add
// Check for hasAnnotationFlag for scala/bug#9393: the classfile / java source parsers add
// scala.annotation.Annotation as superclass to java annotations. In reality, java // annotation classfiles have superclass Object (like any interface classfile). val superClassSym = if (classSym.hasJavaAnnotationFlag) ObjectClass else { val sc = classSym.superClass
// SI-9393: Java annotation classes don't have the ABSTRACT/INTERFACE flag, so they appear
// scala/bug#9393: Java annotation classes don't have the ABSTRACT/INTERFACE flag, so they appear
// (wrongly) as superclasses. Fix this for BTypes: the java annotation will appear as interface // (handled by method implementedInterfaces), the superclass is set to Object. if (sc.hasJavaAnnotationFlag) ObjectClass else sc }
...
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
val isTopLevel = innerClassSym.rawowner.isPackageClass // specialized classes are considered top-level, see comment in BTypes if (isTopLevel || considerAsTopLevelImplementationArtifact(innerClassSym)) None else if (innerClassSym.rawowner.isTerm) { // This case should never be reached: the lambdalift phase mutates the rawowner field of all
// classes to be the enclosing class. SI-9392 shows an errant macro that leaves a reference
// classes to be the enclosing class. scala/bug#9392 shows an errant macro that leaves a reference
// to a local class symbol that no longer exists, which is not updated by lambdalift. devWarning(innerClassSym.pos, s"""The class symbol $innerClassSym with the term symbol ${innerClassSym.rawowner} as `rawowner` reached the backend.
|Most likely this indicates a stale reference to a non-existing class introduced by a macro, see SI-9392.""".stripMargin)
|Most likely this indicates a stale reference to a non-existing class introduced by a macro, see scala/bug#9392.""".stripMargin)
None } else { // See comment in BTypes, when is a class marked static in the InnerClass table. val isStaticNestedClass = isOriginallyStaticOwner(innerClassSym.originalOwner)
...
575 576 577 578 579 580 581 582 583 584 585 586 575 576 577 578 579 580 581 582 583 584 585 586
// Primitive methods cannot be inlined, so there's no point in building a MethodInlineInfo. Also, some // primitive methods (e.g., `isInstanceOf`) have non-erased types, which confuses [[typeToBType]]. val methodInlineInfos = methods.flatMap({ case methodSym => if (completeSilentlyAndCheckErroneous(methodSym)) {
// Happens due to SI-9111. Just don't provide any MethodInlineInfo for that method, we don't need fail the compiler. if (!classSym.isJavaDefined) devWarning("SI-9111 should only be possible for Java classes")
// Happens due to scala/bug#9111. Just don't provide any MethodInlineInfo for that method, we don't need fail the compiler. if (!classSym.isJavaDefined) devWarning("scala/bug#9111 should only be possible for Java classes")
warning = Some(ClassSymbolInfoFailureSI9111(classSym.fullName)) Nil } else { val name = methodSym.javaSimpleName.toString // same as in genDefDef val signature = name + methodBTypeFromSymbol(methodSym).descriptor
...
712 713 714 715 716 717 718 719 720 721 722 712 713 714 715 716 717 718 719 720 721 722
// added to modules and module classes, not anymore since 296b706). // Note that the presence of the `FINAL` flag on a symbol does not correspond 1:1 to emitting // ACC_FINAL in bytecode. // // Top-level modules are marked ACC_FINAL in bytecode (even without the FINAL flag). Nested
// objects don't get the flag to allow overriding (under -Yoverride-objects, SI-5676).
// objects don't get the flag to allow overriding (under -Yoverride-objects, scala/bug#5676).
// // For fields, only eager val fields can receive ACC_FINAL. vars or lazy vals can't: // Source: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.3 // "Another problem is that the specification allows aggressive // optimization of final fields. Within a thread, it is permissible to

130 131 132 133 134 135 136 137 138 139 140 130 131 132 133 134 135 136 137 138 139 140
override def toString = this match { case NoClassBTypeInfoMissingBytecode(cause) => cause.toString case NoClassBTypeInfoClassSymbolInfoFailedSI9111(classFullName) =>
s"Failed to get the type of class symbol $classFullName due to SI-9111."
s"Failed to get the type of class symbol $classFullName due to scala/bug#9111."
} def emitWarning(settings: ScalaSettings): Boolean = this match { case NoClassBTypeInfoMissingBytecode(cause) => cause.emitWarning(settings) case NoClassBTypeInfoClassSymbolInfoFailedSI9111(_) => settings.optWarningNoInlineMissingBytecode
...
278 279 280 281 282 283 284 285 286 287 288 278 279 280 281 282 283 284 285 286 287 288
override def toString = this match { case NoInlineInfoAttribute(internalName) => s"The Scala classfile $internalName does not have a ScalaInlineInfo attribute." case ClassSymbolInfoFailureSI9111(classFullName) =>
s"Failed to get the type of a method of class symbol $classFullName due to SI-9111."
s"Failed to get the type of a method of class symbol $classFullName due to scala/bug#9111."
case ClassNotFoundWhenBuildingInlineInfoFromSymbol(missingClass) => s"Failed to build the inline information: $missingClass" case UnknownScalaInlineInfoVersion(internalName, version) =>

83 84 85 86 87 88 89 90 91 92 93 83 84 85 86 87 88 89 90 91 92 93
/** * Eliminate `xSTORE` instructions that have no consumer. If the instruction can be completely * eliminated, it is replaced by a POP. The [[eliminatePushPop]] cleans up unnecessary POPs. * * Note that an `ASOTRE` can not always be eliminated: it removes a reference to the object that
* is currently stored in that local, which potentially frees it for GC (SI-5313). Therefore
* is currently stored in that local, which potentially frees it for GC (scala/bug#5313). Therefore
* we replace such stores by `POP; ACONST_NULL; ASTORE x`. */ def eliminateStaleStores(method: MethodNode, owner: InternalName): Boolean = { AsmAnalyzer.sizeOKForSourceValue(method) && { lazy val prodCons = new ProdConsAnalyzer(method, owner)
...
472 473 474 475 476 477 478 479 480 481 482 472 473 474 475 476 477 478 479 480 481 482
* Note: store-load pairs that cannot be eliminated could be replaced by `DUP; xSTORE n`, but * that's just cosmetic and doesn't help for anything. * * (1) This could be made more precise by running a prodCons analysis and checking that the load * is the only user of the store. Then we could eliminate the pair even if the variable is live
* (except for ASTORE, SI-5313). Not needing an analyzer is more efficient, and catches most
* (except for ASTORE, scala/bug#5313). Not needing an analyzer is more efficient, and catches most
* cases. * * (2) The implementation uses a conservative estimation for liveness (if some instruction uses * local n, then n is considered live in the entire method). In return, it doesn't need to run an * Analyzer on the method, making it more efficient.

631 632 633 634 635 636 637 638 639 640 641 631 632 633 634 635 636 637 638 639 640 641
assert(!BytecodeUtils.isAbstractMethod(callee), s"Callee is abstract: $calleeDesc") assert(callsiteMethod.instructions.contains(callsiteInstruction), s"Callsite ${textify(callsiteInstruction)} is not an instruction of $calleeDesc") // When an exception is thrown, the stack is cleared before jumping to the handler. When // inlining a method that catches an exception, all values that were on the stack before the
// call (in addition to the arguments) would be cleared (SI-6157). So we don't inline methods
// call (in addition to the arguments) would be cleared (scala/bug#6157). So we don't inline methods
// with handlers in case there are values on the stack. // Alternatively, we could save all stack values below the method arguments into locals, but // that would be inefficient: we'd need to pop all parameters, save the values, and push the // parameters back for the (inlined) invocation. Similarly for the result after the call. def stackHasNonParameters: Boolean = {

74 75 76 77 78 79 80 81 82 83 84 74 75 76 77 78 79 80 81 82 83 84
* * redundant casts: eliminates casts that are statically known to succeed (uses type propagation) * + enables UPSTREAM: * - box-unbox elimination (a removed checkcast may be a box consumer) * + enables downstream:
* - push-pop for closure allocation elimination (every indyLambda is followed by a checkcast, see SI-9540)
* - push-pop for closure allocation elimination (every indyLambda is followed by a checkcast, see scala/bug#9540)
* * push-pop (when a POP is the only consumer of a value, remove the POP and its producer) * + enables UPSTREAM: * - stale stores (if a LOAD is removed, a corresponding STORE may become stale) * - box-unbox elimination (push-pop may eliminate a closure allocation, rendering a captured

168 169 170 171 172 173 174 175 176 177 178 168 169 170 171 172 173 174 175 176 177 178
} val seen = mutable.HashSet[String]() val enabled = (fromPaths ::: fromDirs) map { case Success((pd, loader)) if seen(pd.classname) =>
// a nod to SI-7494, take the plugin classes distinctly
// a nod to scala/bug#7494, take the plugin classes distinctly
Failure(new PluginLoadException(pd.name, s"Ignoring duplicate plugin ${pd.name} (${pd.classname})")) case Success((pd, loader)) if ignoring contains pd.name => Failure(new PluginLoadException(pd.name, s"Disabling plugin ${pd.name}")) case Success((pd, loader)) => seen += pd.classname

129 130 131 132 133 134 135 136 137 138 139 129 130 131 132 133 134 135 136 137 138 139
val Xshowobj = StringSetting ("-Xshow-object", "object", "Show internal representation of object.", "") val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases.") val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "") val reporter = StringSetting ("-Xreporter", "classname", "Specify a custom reporter for compiler messages.", "scala.tools.nsc.reporters.ConsoleReporter") val strictInference = BooleanSetting ("-Xstrict-inference", "Don't infer known-unsound types")
val source = ScalaVersionSetting ("-Xsource", "version", "Treat compiler input as Scala source for the specified version, see SI-8126.", initial = ScalaVersion("2.12"))
val source = ScalaVersionSetting ("-Xsource", "version", "Treat compiler input as Scala source for the specified version, see scala/bug#8126.", initial = ScalaVersion("2.12"))
val XnoPatmatAnalysis = BooleanSetting ("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.") val XfullLubs = BooleanSetting ("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.") val XmixinForceForwarders = ChoiceSetting(

88 89 90 91 92 93 94 95 96 97 98 88 89 90 91 92 93 94 95 96 97 98
if (preExisting != NoSymbol) { // Some jars (often, obfuscated ones) include a package and // object with the same name. Rather than render them unusable, // offer a setting to resolve the conflict one way or the other. // This was motivated by the desire to use YourKit probes, which
// require yjp.jar at runtime. See SI-2089.
// require yjp.jar at runtime. See scala/bug#2089.
if (settings.termConflict.isDefault) throw new TypeError( s"$root contains object and package with same name: $name\none of them needs to be removed from classpath" ) else if (settings.termConflict.value == "package") {
...
131 132 133 134 135 136 137 138 139 140 141 131 132 133 134 135 136 137 138 139 140 141
// representation. `companionModule/Class` prefers the source version, so we should be careful // to reuse the symbols returned below. val clazz = enterClass(root, clazz0, completer) val module = enterModule(root, module0, completer) if (!clazz.isAnonymousClass) {
// Diagnostic for SI-7147
// Diagnostic for scala/bug#7147
def msg: String = { def symLocation(sym: Symbol) = if (sym == null) "null" else s"${clazz.fullLocationString} (from ${clazz.associatedFile})" sm"""Inconsistent class/module symbol pair for `$name` loaded from ${symLocation(root)}. |clazz = ${symLocation(clazz)}; clazz.companionModule = ${clazz.companionModule} |module = ${symLocation(module)}; module.companionClass = ${module.companionClass}"""
...
294 295 296 297 298 299 300 301 302 303 304 305 306 307 294 295 296 297 298 299 300 301 302 303 304 305 306 307
override protected def newConstantPool: ThisConstantPool = new ConstantPool override protected def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol = SymbolLoaders.this.lookupMemberAtTyperPhaseIfPossible(sym, name) /* * The type alias and the cast (where the alias is used) is needed due to problem described
* in SI-7585. In this particular case, the problem is that we need to make sure that symbol
* in scala/bug#7585. In this particular case, the problem is that we need to make sure that symbol
* table used by symbol loaders is exactly the same as they one used by classfileParser. * If you look at the path-dependent types we have here everything should work out ok but
* due to issue described in SI-7585 type-checker cannot tie the knot here.
* due to issue described in scala/bug#7585 type-checker cannot tie the knot here.
* */ private type SymbolLoadersRefined = SymbolLoaders { val symbolTable: classfileParser.symbolTable.type } val loaders = SymbolLoaders.this.asInstanceOf[SymbolLoadersRefined]

365 366 367 368 369 370 371 372 373 374 375 365 366 367 368 369 370 371 372 373 374 375
protected def errorBadTag(start: Int) = abort(s"bad constant pool tag ${in.buf(start)} at byte $start") } def stubClassSymbol(name: Name): Symbol = {
// SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented
// scala/bug#5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented
// therefore, it will rummage through the classpath triggering errors whenever it encounters package objects // that are not in their correct place (see bug for details) // TODO More consistency with use of stub symbols in `Unpickler` // - better owner than `NoSymbol`
...
385 386 387 388 389 390 391 392 393 394 395 396 385 386 387 388 389 390 391 392 393 394 395 396
else // FIXME - we shouldn't be doing ad hoc lookups in the empty package, getClassByName should return the class definitions.getMember(rootMirror.EmptyPackageClass, name.toTypeName) } catch { // The handler
// - prevents crashes with deficient InnerClassAttributes (SI-2464, 0ce0ad5) // - was referenced in the bugfix commit for SI-3756 (4fb0d53), not sure why
// - prevents crashes with deficient InnerClassAttributes (scala/bug#2464, 0ce0ad5) // - was referenced in the bugfix commit for scala/bug#3756 (4fb0d53), not sure why
// - covers the case when a type alias in a package object shadows a class symbol, // getClassByName throws a MissingRequirementError (scala-dev#248) case _: FatalError => // getClassByName can throw a MissingRequirementError (which extends FatalError) // definitions.getMember can throw a FatalError, for example in pos/t5165b
...
428 429 430 431 432 433 434 435 436 437 438 428 429 430 431 432 433 434 435 436 437 438
if (jflags.isAnnotation) ifaces ::= ClassfileAnnotationClass.tpe superType :: ifaces } }
val isTopLevel = !(currentClass containsChar '$') // Java class name; *don't* try to to use Scala name decoding (SI-7532)
val isTopLevel = !(currentClass containsChar '$') // Java class name; *don't* try to to use Scala name decoding (scala/bug#7532)
if (isTopLevel) { val c = pool.getClassSymbol(nameIdx) // scala-dev#248: when a type alias (in a package object) shadows a class symbol, getClassSymbol returns a stub if (!c.isInstanceOf[StubSymbol] && c != clazz) mismatchError(c) }
...
558 559 560 561 562 563 564 565 566 567 568 558 559 560 561 562 563 564 565 566 567 568
info match { case MethodType(params, restpe) => // if this is a non-static inner class, remove the explicit outer parameter val paramsNoOuter = innerClasses getEntry currentClass match { case Some(entry) if !isScalaRaw && !entry.jflags.isStatic =>
/* About `clazz.owner.hasPackageFlag` below: SI-5957
/* About `clazz.owner.hasPackageFlag` below: scala/bug#5957
* For every nested java class A$B, there are two symbols in the scala compiler. * 1. created by SymbolLoader, because of the existence of the A$B.class file, owner: package * 2. created by ClassfileParser of A when reading the inner classes, owner: A * If symbol 1 gets completed (e.g. because the compiled source mentions `A$B`, not `A#B`), the * ClassfileParser for 1 executes, and clazz.owner is the package.
...
573 574 575 576 577 578 579 580 581 582 583 573 574 575 576 577 578 579 580 581 582 583
case _ => params } val newParams = paramsNoOuter match { case (init :+ tail) if jflags.isSynthetic =>
// SI-7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
// scala/bug#7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
// are added when an inner class needs to access a private constructor. init case _ => paramsNoOuter }
...
844 845 846 847 848 849 850 851 852 853 854 855 844 845 846 847 848 849 850 851 852 853 854 855
// Java annotations on classes / methods / fields with RetentionPolicy.RUNTIME case tpnme.RuntimeAnnotationATTR => if (isScalaAnnot || !isScala) { // For Scala classfiles we are only interested in the scala signature annotations. Other // annotations should be skipped (the pickle contains the symbol's annotations).
// Skipping them also prevents some spurious warnings / errors related to SI-7014, // SI-7551, pos/5165b
// Skipping them also prevents some spurious warnings / errors related to scala/bug#7014, // scala/bug#7551, pos/5165b
val scalaSigAnnot = parseAnnotations(onlyScalaSig = isScalaAnnot) if (isScalaAnnot) scalaSigAnnot match { case Some(san: AnnotationInfo) => val bytes = san.assocs.find({ _._1 == nme.bytes }).get._2.asInstanceOf[ScalaSigBytes].bytes
...
937 938 939 940 941 942 943 944 945 946 947 937 938 939 940 941 942 943 944 945 946 947
val n = readName() val module = t.typeSymbol.companionModule val s = module.info.decls.lookup(n) if (s != NoSymbol) Some(LiteralAnnotArg(Constant(s))) else {
warning(s"""While parsing annotations in ${in.file}, could not find $n in enum $module.\nThis is likely due to an implementation restriction: an annotation argument cannot refer to a member of the annotated class (SI-7014).""")
warning(s"""While parsing annotations in ${in.file}, could not find $n in enum $module.\nThis is likely due to an implementation restriction: an annotation argument cannot refer to a member of the annotated class (scala/bug#7014).""")
None } case ARRAY_TAG => val arr = new ArrayBuffer[ClassfileAnnotArg]()
...
975 976 977 978 979 980 981 982 983 984 985 975 976 977 978 979 980 981 982 983 984 985
u2 } Some(ScalaSigBytes(pool.getBytes(entries.toList))) }
// TODO SI-9296 duplicated code, refactor
// TODO scala/bug#9296 duplicated code, refactor
/* Parse and return a single annotation. If it is malformed, * return None. */ def parseAnnotation(attrNameIndex: Int, onlyScalaSig: Boolean): Option[AnnotationInfo] = try { val attrType = pool.getType(attrNameIndex)
...
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
* thrown by a method. */ def parseExceptions(len: Int) { val nClasses = u2 for (n <- 0 until nClasses) {
// FIXME: this performs an equivalent of getExceptionTypes instead of getGenericExceptionTypes (SI-7065)
// FIXME: this performs an equivalent of getExceptionTypes instead of getGenericExceptionTypes (scala/bug#7065)
val cls = pool.getClassSymbol(u2) // we call initialize due to the fact that we call Symbol.isMonomorphicType in addThrowsAnnotation
// and that method requires Symbol to be forced to give the right answers, see SI-7107 for details
// and that method requires Symbol to be forced to give the right answers, see scala/bug#7107 for details
cls.initialize sym.addThrowsAnnotation(cls) } }

91 92 93 94 95 96 97 98 99 100 101 91 92 93 94 95 96 97 98 99 100 101
/** Returns usually symbol's owner, but picks classfile root instead * for existentially bound variables that have a non-local owner. * Question: Should this be done for refinement class symbols as well? *
* Note: tree pickling also finds its way here; e.g. in SI-7501 the pickling
* Note: tree pickling also finds its way here; e.g. in scala/bug#7501 the pickling
* of trees in annotation arguments considers the parameter symbol of a method * called in such a tree as "local". The condition `sym.isValueParameter` was * added to fix that bug, but there may be a better way. */ private def localizedOwner(sym: Symbol) =

215 216 217 218 219 220 221 222 223 224 225 215 216 217 218 219 220 221 222 223 224 225
* Note: The `checkinit` option does not check if transient fields are initialized. */ protected def needsInitFlag(sym: Symbol): Boolean = sym.isGetter && !( sym.isInitializedToDefault
|| isConstantType(sym.info.finalResultType) // SI-4742
|| isConstantType(sym.info.finalResultType) // scala/bug#4742
|| sym.hasFlag(PARAMACCESSOR | SPECIALIZED | LAZY) || sym.accessed.hasFlag(PRESUPER) || sym.isOuterAccessor || (sym.owner isSubClass DelayedInitClass) || (sym.accessed hasAnnotation TransientAttr))

462 463 464 465 466 467 468 469 470 471 472 462 463 464 465 466 467 468 469 470 471 472
super.transform(treeCopy.Apply(app, fun, args)) // Replaces `Array(Predef.wrapArray(ArrayValue(...).$asInstanceOf[...]), <tag>)` // with just `ArrayValue(...).$asInstanceOf[...]` //
// See SI-6611; we must *only* do this for literal vararg arrays.
// See scala/bug#6611; we must *only* do this for literal vararg arrays.
case Apply(appMeth, List(Apply(wrapRefArrayMeth, List(arg @ StripCast(ArrayValue(_, _)))), _)) if wrapRefArrayMeth.symbol == currentRun.runDefinitions.Predef_wrapRefArray && appMeth.symbol == ArrayModule_genericApply => super.transform(arg) case Apply(appMeth, List(elem0, Apply(wrapArrayMeth, List(rest @ ArrayValue(elemtpt, _))))) if wrapArrayMeth.symbol == Predef_wrapArray(elemtpt.tpe) && appMeth.symbol == ArrayModule_apply(elemtpt.tpe) =>

732 733 734 735 736 737 738 739 740 741 742 732 733 734 735 736 737 738 739 740 741 742
} // Return a pair consisting of (all statements up to and including superclass and trait constr calls, rest) def splitAtSuper(stats: List[Tree]) = { def isConstr(tree: Tree): Boolean = tree match {
case Block(_, expr) => isConstr(expr) // SI-6481 account for named argument blocks
case Block(_, expr) => isConstr(expr) // scala/bug#6481 account for named argument blocks
case _ => (tree.symbol ne null) && tree.symbol.isConstructor } val (pre, rest0) = stats span (!isConstr(_)) val (supercalls, rest) = rest0 span (isConstr(_)) (pre ::: supercalls, rest)

278 279 280 281 282 283 284 285 286 287 288 278 279 280 281 282 283 284 285 286 287 288
// during this call boxingBridgeMethods will be populated from the Function case val Template(parents, self, body) = super.transform(deriveTemplate(tree)(_.mapConserve(pretransform))) Template(parents, self, body ++ boxingBridgeMethods) } finally boxingBridgeMethods.clear() case dd: DefDef if dd.symbol.isLiftedMethod && !dd.symbol.isDelambdafyTarget =>
// SI-9390 emit lifted methods that don't require a `this` reference as STATIC
// scala/bug#9390 emit lifted methods that don't require a `this` reference as STATIC
// delambdafy targets are excluded as they are made static by `transformFunction`. if (!dd.symbol.hasFlag(STATIC) && !methodReferencesThis(dd.symbol)) { dd.symbol.setFlag(STATIC) dd.symbol.removeAttachment[mixer.NeedStaticImpl.type] }

274 275 276 277 278 279 280 281 282 283 284 274 275 276 277 278 279 280 281 282 283 284
if (!(AnyRefTpe <:< bounds.hi)) "+" + boxedSig(bounds.hi) else if (!(bounds.lo <:< NullTpe)) "-" + boxedSig(bounds.lo) else "*" } else tp match { case PolyType(_, res) =>
"*" // SI-7932
"*" // scala/bug#7932
case _ => boxedSig(tp) } def classSig = { val preRebound = pre.baseType(sym.owner) // #2585
...
834 835 836 837 838 839 840 841 842 843 844 834 835 836 837 838 839 840 841 842 843 844
/** TODO - adapt SymbolPairs so it can be used here. */ private def checkNoDeclaredDoubleDefs(base: Symbol) { val decls = base.info.decls
// SI-8010 force infos, otherwise makeNotPrivate in ExplicitOuter info transformer can trigger
// scala/bug#8010 force infos, otherwise makeNotPrivate in ExplicitOuter info transformer can trigger
// a scope rehash while were iterating and we can see the same entry twice! // Inspection of SymbolPairs (the basis of OverridingPairs), suggests that it is immune // from this sort of bug as it copies the symbols into a temporary scope *before* any calls to `.info`, // ie, no variant of it calls `info` or `tpe` in `SymbolPair#exclude`. //
...
850 851 852 853 854 855 856 857 858 859 860 850 851 852 853 854 855 856 857 858 859 860
var e = decls.elems while (e ne null) { if (e.sym.isTerm) { var e1 = decls lookupNextEntry e while (e1 ne null) {
assert(e.sym ne e1.sym, s"Internal error: encountered ${e.sym.debugLocationString} twice during scope traversal. This might be related to SI-8010.")
assert(e.sym ne e1.sym, s"Internal error: encountered ${e.sym.debugLocationString} twice during scope traversal. This might be related to scala/bug#8010.")
if (sameTypeAfterErasure(e.sym, e1.sym)) doubleDefError(new SymbolPair(base, e.sym, e1.sym)) e1 = decls lookupNextEntry e1 }
...
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
// // b) a non-primitive, e.g. because the qualifier's type is a refinement type where one parent // of the refinement is a primitive and another is AnyRef. In that case // we get a primitive form of _getClass trying to target a boxed value // so we need replace that method name with Object_getClass to get correct behavior.
// See SI-5568.
// See scala/bug#5568.
tree setSymbol Object_getClass } else { devWarning(s"The symbol '${fn.symbol}' was intercepted but didn't match any cases, that means the intercepted methods set doesn't match the code") tree }
...
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
def isJvmAccessible(sym: Symbol) = (sym.isClass && !sym.isJavaDefined) || localTyper.context.isAccessible(sym, sym.owner.thisType) if (!isJvmAccessible(owner) && qual.tpe != null) { qual match { case Super(_, _) =>
// Insert a cast here at your peril -- see SI-5162.
// Insert a cast here at your peril -- see scala/bug#5162.
reporter.error(tree.pos, s"Unable to access ${tree.symbol.fullLocationString} with a super reference.") tree case _ => // Todo: Figure out how qual.tpe could be null in the check above (it does appear in build where SwingWorker.this // has a null type).
...
1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208
if (tree.symbol == ArrayClass && !tree.isType) tree else { val tree1 = preErase(tree) tree1 match { case TypeApply(fun, targs @ List(targ)) if (fun.symbol == Any_asInstanceOf || fun.symbol == Object_synchronized) && targ.tpe == UnitTpe =>
// SI-9066 prevent transforming `o.asInstanceOf[Unit]` to `o.asInstanceOf[BoxedUnit]`.
// scala/bug#9066 prevent transforming `o.asInstanceOf[Unit]` to `o.asInstanceOf[BoxedUnit]`.
// adaptMember will then replace the call by a reference to BoxedUnit.UNIT. treeCopy.TypeApply(tree1, transform(fun), targs).clearType() case EmptyTree | TypeTree() => tree1 setType specialScalaErasure(tree1.tpe) case ArrayValue(elemtpt, trees) =>

106 107 108 109 110 111 112 113 114 115 116 106 107 108 109 110 111 112 113 114 115 116
* trait T { C.this } // C$T$$$outer$ : C * object T extends T { C.this } // C$T$$$outer$ : C.this.type * } * }}} *
* See SI-7242.
* See scala/bug#7242.
}} */ private def skipMixinOuterAccessor(clazz: Symbol, mixin: Symbol) = { // Reliant on the current scheme for name expansion, the expanded name // of the outer accessors in a trait and its companion object are the same.
...
345 346 347 348 349 350 351 352 353 354 355 345 346 347 348 349 350 351 352 353 354 355
val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass def mixinPrefix = (currentClass.thisType baseType mixinClass).prefix assert(outerAcc != NoSymbol, "No outer accessor for inner mixin " + mixinClass + " in " + currentClass) assert(outerAcc.alternatives.size == 1, s"Multiple outer accessors match inner mixin $mixinClass in $currentClass : ${outerAcc.alternatives.map(_.defString)}") // I added the mixinPrefix.typeArgs.nonEmpty condition to address the
// crash in SI-4970. I feel quite sure this can be improved.
// crash in scala/bug#4970. I feel quite sure this can be improved.
val path = ( if (mixinClass.owner.isTerm) gen.mkAttributedThis(mixinClass.owner.enclClass) else if (mixinPrefix.typeArgs.nonEmpty) gen.mkAttributedThis(mixinPrefix.typeSymbol) else gen.mkAttributedQualifier(mixinPrefix) )
...
413 414 415 416 417 418 419 420 421 422 423 424 425 426 413 414 415 416 417 418 419 420 421 422 423 424 425 426
case Select(qual, name) => // make not private symbol accessed from inner classes, as well as // symbols accessed from @inline methods //
// See SI-6552 for an example of why `sym.owner.enclMethod hasAnnotation ScalaInlineClass`
// See scala/bug#6552 for an example of why `sym.owner.enclMethod hasAnnotation ScalaInlineClass`
// is not suitable; if we make a method-local class non-private, it mangles outer pointer names. def enclMethodIsInline = closestEnclMethod(currentOwner) hasAnnotation ScalaInlineClass
// SI-8710 The extension method condition reflects our knowledge that a call to `new Meter(12).privateMethod`
// scala/bug#8710 The extension method condition reflects our knowledge that a call to `new Meter(12).privateMethod`
// with later be rewritten (in erasure) to `Meter.privateMethod$extension(12)`. if ((currentClass != sym.owner || enclMethodIsInline) && !sym.isMethodWithExtension) sym.makeNotPrivate(sym.owner) val qsym = qual.tpe.widen.typeSymbol
...
449 450 451 452 453 454 455 456 457 458 459 449 450 451 452 453 454 455 456 457 458 459
case Apply(eqsel@Select(eqapp@Apply(sel@Select(base, nme.OUTER_SYNTH), Nil), eq), args) => val outerFor = sel.symbol.owner val acc = outerAccessor(outerFor) if (acc == NoSymbol ||
// since we can't fix SI-4440 properly (we must drop the outer accessors of final classes when there's no immediate reference to them in sight)
// since we can't fix scala/bug#4440 properly (we must drop the outer accessors of final classes when there's no immediate reference to them in sight)
// at least don't crash... this duplicates maybeOmittable from constructors (acc.owner.isEffectivelyFinal && !acc.isOverridingSymbol)) { if (!base.tpe.hasAnnotation(UncheckedClass)) currentRun.reporting.uncheckedWarning(tree.pos, "The outer reference in this type test cannot be checked at run time.") transform(TRUE) // urgh... drop condition if there's no accessor (or if it may disappear after constructors)

59 60 61 62 63 64 65 66 67 68 69 59 60 61 62 63 64 65 66 67 68 69
Stream(newTermName(imeth.name+"$extension")) } } private def companionModuleForce(sym: Symbol) = {
sym.andAlso(_.owner.initialize) // See SI-6976. `companionModule` only calls `rawInfo`. (Why?)
sym.andAlso(_.owner.initialize) // See scala/bug#6976. `companionModule` only calls `rawInfo`. (Why?)
sym.companionModule } /** Return the extension method that corresponds to given instance method `meth`. */ def extensionMethod(imeth: Symbol): Symbol = enteringPhase(currentRun.refchecksPhase) {
...
189 190 191 192 193 194 195 196 197 198 199 189 190 191 192 193 194 195 196 197 198 199
/* This is currently redundant since value classes may not wrap over other value classes anyway. checkNonCyclic(currentOwner.pos, Set(), currentOwner) */ extensionDefs(currentOwner.companionModule) = new mutable.ListBuffer[Tree] currentOwner.primaryConstructor.makeNotPrivate(NoSymbol)
// SI-7859 make param accessors accessible so the erasure can generate unbox operations.
// scala/bug#7859 make param accessors accessible so the erasure can generate unbox operations.
currentOwner.info.decls.foreach(sym => if (sym.isParamAccessor && sym.isMethod) sym.makeNotPrivate(currentOwner)) super.transform(tree) } else if (currentOwner.isStaticOwner) { super.transform(tree) } else tree
...
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
} val castBody = if (extensionBody.tpe <:< extensionMono.finalResultType) extensionBody else
gen.mkCastPreservingAnnotations(extensionBody, extensionMono.finalResultType) // SI-7818 e.g. mismatched existential skolems
gen.mkCastPreservingAnnotations(extensionBody, extensionMono.finalResultType) // scala/bug#7818 e.g. mismatched existential skolems
// Record the extension method. Later, in `Extender#transformStats`, these will be added to the companion object. extensionDefs(companion) += DefDef(extensionMeth, castBody) // These three lines are assembling Foo.bar$extension[T1, T2, ...]($this) // which leaves the actual argument application for extensionCall.
// SI-9542 We form the selection here from the thisType of the companion's owner. This is motivated
// scala/bug#9542 We form the selection here from the thisType of the companion's owner. This is motivated
// by the test case, and is a valid way to construct the reference because we know that this // method is also enclosed by that owner. val sel = Select(gen.mkAttributedRef(companion.owner.thisType, companion), extensionMeth) val targs = origTpeParams map (_.tpeHK) val callPrefix = gen.mkMethodCall(sel, targs, This(origThis) :: Nil)
...
278 279 280 281 282 283 284 285 286 287 288 278 279 280 281 282 283 284 285 286 287 288
} final class SubstututeRecursion(origMeth: Symbol, extensionMeth: Symbol, unit: CompilationUnit) extends TypingTransformer(unit) { override def transform(tree: Tree): Tree = tree match {
// SI-6574 Rewrite recursive calls against the extension method so they can
// scala/bug#6574 Rewrite recursive calls against the extension method so they can
// be tail call optimized later. The tailcalls phases comes before // erasure, which performs this translation more generally at all call // sites. // // // Source

76 77 78 79 80 81 82 83 84 85 86 76 77 78 79 80 81 82 83 84 85 86
decls1 enter sym if (sym.isModule) { // In theory, we could assert(sym.isMethod), because nested, non-static modules are // transformed to methods (METHOD flag added in UnCurry). But this requires // forcing sym.info (see comment on isModuleNotMethod), which forces stub symbols
// too eagerly (SI-8907).
// too eagerly (scala/bug#8907).
// Note that module classes are not entered into the 'decls' of the ClassInfoType // of the outer class, only the module symbols are. So the current loop does // not visit module classes. Therefore we set the LIFTED flag here for module // classes.
...
121 122 123 124 125 126 127 128 129 130 131 132 133 134 121 122 123 124 125 126 127 128 129 130 131 132 133 134
super.transform(tree) case Template(_, _, _) if tree.symbol.isDefinedInPackage => liftedDefs(tree.symbol.owner) = new ListBuffer super.transform(tree) case ClassDef(_, _, _, _) if tree.symbol.isNestedClass =>
// SI-5508 Ordering important. In `object O { trait A { trait B } }`, we want `B` to appear after `A` in
// scala/bug#5508 Ordering important. In `object O { trait A { trait B } }`, we want `B` to appear after `A` in
// the sequence of lifted trees in the enclosing package. Why does this matter? Currently, mixin // needs to transform `A` first to a chance to create accessors for private[this] trait fields
// *before* it transforms inner classes that refer to them. This also fixes SI-6231.
// *before* it transforms inner classes that refer to them. This also fixes scala/bug#6231.
// // Alternative solutions // - create the private[this] accessors eagerly in Namer (but would this cover private[this] fields // added later phases in compilation?) // - move the accessor creation to the Mixin info transformer

85 86 87 88 89 90 91 92 93 94 95 85 86 87 88 89 90 91 92 93 94 95
* def closure(x$1: Int) = new anonFun$1(this, x$1) * class anonFun$1(outer$: Outer, x$1: Int) { def apply() => x$1 } * }}} * * This is fatally bad for named arguments (0e170e4b), extremely impolite to tools
* reflecting on the method parameter names in the generated bytecode (SI-6028),
* reflecting on the method parameter names in the generated bytecode (scala/bug#6028),
* and needlessly bothersome to anyone using a debugger. * * Instead, we transform to: * {{{ * def closure(x: Int) = new anonFun$1(this, x)
...
255 256 257 258 259 260 261 262 263 264 265 255 256 257 258 259 260 261 262 263 264 265
val join = nme.NAME_JOIN_STRING if (sym.isAnonymousFunction && sym.owner.isMethod) { freshen(sym.name + join + nme.ensureNonAnon(sym.owner.name.toString) + join) } else { val name = freshen(sym.name + join)
// SI-5652 If the lifted symbol is accessed from an inner class, it will be made public. (where?)
// scala/bug#5652 If the lifted symbol is accessed from an inner class, it will be made public. (where?)
// Generating a unique name, mangled with the enclosing full class name (including // package - subclass might have the same name), avoids a VerifyError in the case // that a sub-class happens to lifts out a method with the *same* name. if (originalName.isTermName && calledFromInner(sym)) newTermNameCached(nme.ensureNonAnon(sym.enclClass.fullName('$')) + nme.EXPAND_SEPARATOR_STRING + name)
...
345 346 347 348 349 350 351 352 353 354 355 345 346 347 348 349 350 351 352 353 354 355
case EmptyTree => prematureSelfReference() case o => val path = outerPath(o, currentClass.outerClass, clazz) if (path.tpe <:< clazz.tpeHK) path else {
// SI-9920 The outer accessor might have an erased type of the self type of a trait,
// scala/bug#9920 The outer accessor might have an erased type of the self type of a trait,
// rather than the trait itself. Add a cast if necessary. gen.mkAttributedCast(path, clazz.tpeHK) } } }
...
415 416 417 418 419 420 421 422 423 424 425 415 416 417 418 419 420 421 422 423 424 425
case _ => tree }
/* SI-6231: Something like this will be necessary to eliminate the implementation
/* scala/bug#6231: Something like this will be necessary to eliminate the implementation
* restriction from paramGetter above: * We need to pass getters to the interface of an implementation class. private def fixTraitGetters(lifted: List[Tree]): List[Tree] = for (stat <- lifted) yield stat match { case ClassDef(mods, name, tparams, templ @ Template(parents, self, body))
...
454 455 456 457 458 459 460 461 462 463 464 454 455 456 457 458 459 460 461 462 463 464
val oldOwner = sym.owner if (sym.isMethod && isUnderConstruction(sym.owner.owner)) { // # bug 1909 if (sym.isModule) { // Yes, it can be a module and a method, see comments on `isModuleNotMethod`! // TODO promote to an implementation restriction if we can reason that this *always* leads to VerifyError. // See neg/t1909-object.scala
def msg = s"SI-1909 Unable to STATICally lift $sym, which is defined in the self- or super-constructor call of ${sym.owner.owner}. A VerifyError is likely."
def msg = s"scala/bug#1909 Unable to STATICally lift $sym, which is defined in the self- or super-constructor call of ${sym.owner.owner}. A VerifyError is likely."
devWarning(tree.pos, msg) } else sym setFlag STATIC } sym.owner = sym.owner.enclClass
...
577 578 579 580 581 582 583 584 585 586 587 577 578 579 580 581 582 583 584 585 586 587
} // class LambdaLifter private def addFree[A](sym: Symbol, free: List[A], original: List[A]): List[A] = { val prependFree = ( !sym.isConstructor // this condition is redundant for now. It will be needed if we remove the second condition in 2.12.x
&& (settings.Ydelambdafy.value == "method" && sym.isDelambdafyTarget) // SI-8359 Makes the lambda body a viable as the target MethodHandle for a call to LambdaMetafactory
&& (settings.Ydelambdafy.value == "method" && sym.isDelambdafyTarget) // scala/bug#8359 Makes the lambda body a viable as the target MethodHandle for a call to LambdaMetafactory
) if (prependFree) free ::: original else original ::: free } }

444 445 446 447 448 449 450 451 452 453 454 444 445 446 447 448 449 450 451 452 453 454
} } templStats foreach SingleUseTraverser.apply // println("usedIn: " + usedIn)
// only consider usages from non-transient lazy vals (SI-9365)
// only consider usages from non-transient lazy vals (scala/bug#9365)
val singlyUsedIn = usedIn.filter { case (_, member :: Nil) if member.name.endsWith(nme.LAZY_SLOW_SUFFIX) => val lazyAccessor = member.owner.info.decl(member.name.stripSuffix(nme.LAZY_SLOW_SUFFIX)) !lazyAccessor.accessedOrSelf.hasAnnotation(TransientAttr) case _ => false

593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
/* It gets hard to follow all the clazz and cls, and specializedClass * was both already used for a map and mucho long. So "sClass" is the * specialized subclass of "clazz" throughout this file. */
// SI-5545: Eliminate classes with the same name loaded from the bytecode already present - all we need to do is
// scala/bug#5545: Eliminate classes with the same name loaded from the bytecode already present - all we need to do is
// to force .info on them, as their lazy type will be evaluated and the symbols will be eliminated. Unfortunately // evaluating the info after creating the specialized class will mess the specialized class signature, so we'd // better evaluate it before creating the new class symbol val clazzName = specializedName(clazz, env0).toTypeName val bytecodeClazz = clazz.owner.info.decl(clazzName) // debuglog("Specializing " + clazz + ", but found " + bytecodeClazz + " already there") bytecodeClazz.info val sClass = clazz.owner.newClass(clazzName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE)
sClass.setAnnotations(clazz.annotations) // SI-8574 important that the subclass picks up @SerialVersionUID, @strictfp, etc.
sClass.setAnnotations(clazz.annotations) // scala/bug#8574 important that the subclass picks up @SerialVersionUID, @strictfp, etc.
def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long, newName: Name = null) = member.cloneSymbol(sClass, flagFn(member.flags | SPECIALIZED), newName) sClass.associatedFile = clazz.sourceFile
...
886 887 888 889 890 891 892 893 894 895 896 886 887 888 889 890 891 892 893 894 895 896
*/ private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = { sym :: ( if (!sym.isMethod || enteringTyper(sym.typeParams.isEmpty)) Nil else if (sym.hasDefault) {
/* Specializing default getters is useless, also see SI-7329 . */
/* Specializing default getters is useless, also see scala/bug#7329 . */
sym.resetFlag(SPECIALIZED) Nil } else { // debuglog("normalizeMember: " + sym.fullNameAsName('.').decode) var specializingOn = specializedParams(sym)
...
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
case (overridden, env) => val om = specializedOverload(clazz, overridden, env) clazz.info.decls.enter(om) foreachWithIndex(om.paramss) { (params, i) => foreachWithIndex(params) { (param, j) =>
param.name = overriding.paramss(i)(j).name // SI-6555 Retain the parameter names from the subclass.
param.name = overriding.paramss(i)(j).name // scala/bug#6555 Retain the parameter names from the subclass.
} } debuglog(s"specialized overload $om for ${overriding.name.decode} in ${pp(env)}: ${om.info}") om.setFlag(overriding.flags & (ABSOVERRIDE | SYNCHRONIZED)) om.withAnnotations(overriding.annotations.filter(_.symbol == ScalaStrictFPAttr))
...
1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
} protected override def newBodyDuplicator(context: Context) = new BodyDuplicator(context) }
/** Introduced to fix SI-7343: Phase ordering problem between Duplicators and Specialization.
/** Introduced to fix scala/bug#7343: Phase ordering problem between Duplicators and Specialization.
* brief explanation: specialization rewires class parents during info transformation, and * the new info then guides the tree changes. But if a symbol is created during duplication, * which runs after specialization, its info is not visited and thus the corresponding tree * is not specialized. One manifestation is the following: * ```
...
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
def isMatch(member: Symbol) = { val memberType = qual.tpe memberType member val residualTreeType = tree match { case TypeApply(fun, targs) if fun.symbol == symbol =>
// SI-6308 Handle methods with only some type parameters specialized.
// scala/bug#6308 Handle methods with only some type parameters specialized.
// drop the specialized type parameters from the PolyType, and // substitute in the type environment. val GenPolyType(tparams, tpe) = fun.tpe val (from, to) = env.toList.unzip val residualTParams = tparams.filterNot(env.contains)

356 357 358 359 360 361 362 363 364 365 366 356 357 358 359 360 361 362 363 364 365 366
noTailTransform(selector), transformTrees(cases).asInstanceOf[List[CaseDef]] ) case Try(block, catches, finalizer @ EmptyTree) =>
// SI-1672 Catches are in tail position when there is no finalizer
// scala/bug#1672 Catches are in tail position when there is no finalizer
treeCopy.Try(tree, noTailTransform(block), transformTrees(catches).asInstanceOf[List[CaseDef]], EmptyTree )
...
404 405 406 407 408 409 410 411 412 413 414 404 405 406 407 408 409 410 411 412 413 414
case _ => super.transform(tree) } }
// Workaround for SI-6900. Uncurry installs an InfoTransformer and a tree Transformer.
// Workaround for scala/bug#6900. Uncurry installs an InfoTransformer and a tree Transformer.
// These leave us with conflicting view on method signatures; the parameter symbols in // the MethodType can be clones of the ones originally found on the parameter ValDef, and // consequently appearing in the typechecked RHS of the method. private def mkAttributedCastHack(tree: Tree, tpe: Type) = gen.mkAttributedCast(tree, tpe)

13 14 15 16 17 18 19 20 21 22 23 13 14 15 16 17 18 19 20 21 22 23
import definitions._ def typedPos(pos: Position)(tree: Tree): Tree /**
* SI-4148: can't always replace box(unbox(x)) by x because
* scala/bug#4148: can't always replace box(unbox(x)) by x because
* - unboxing x may lead to throwing an exception, e.g. in "aah".asInstanceOf[Int] * - box(unbox(null)) is not `null` but the box of zero */ private def isSafelyRemovableUnbox(fn: Tree, arg: Tree): Boolean = { currentRun.runDefinitions.isUnbox(fn.symbol) && {
...
88 89 90 91 92 93 94 95 96 97 98 88 89 90 91 92 93 94 95 96 97 98
typedPos(tree.pos)(tree1) } final def unboxValueClass(tree: Tree, clazz: Symbol, underlying: Type): Tree = if (tree.tpe.typeSymbol == NullClass && isPrimitiveValueClass(underlying.typeSymbol)) {
// convert `null` directly to underlying type, as going via the unboxed type would yield a NPE (see SI-5866)
// convert `null` directly to underlying type, as going via the unboxed type would yield a NPE (see scala/bug#5866)
unbox(tree, underlying) } else Apply(Select(adaptToType(tree, clazz.tpe), clazz.derivedValueClassUnbox), List()) /** Generate a synthetic cast operation from tree.tpe to pt.
...
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
else if (tree.tpe weak_<:< pt) "widen" else "cast" log(s"erasure ${word}s from ${tree.tpe} to $pt") } if (pt =:= UnitTpe) {
// See SI-4731 for one example of how this occurs.
// See scala/bug#4731 for one example of how this occurs.
log("Attempted to cast to Unit: " + tree) tree.duplicate setType pt } else if (tree.tpe != null && tree.tpe.typeSymbol == ArrayClass && pt.typeSymbol == ArrayClass) {
// See SI-2386 for one example of when this might be necessary.
// See scala/bug#2386 for one example of when this might be necessary.
val needsExtraCast = isPrimitiveValueType(tree.tpe.typeArgs.head) && !isPrimitiveValueType(pt.typeArgs.head) val tree1 = if (needsExtraCast) gen.mkRuntimeCall(nme.toObjectArray, List(tree)) else tree gen.mkAttributedCast(tree1, pt) } else gen.mkAttributedCast(tree, pt) }

74 75 76 77 78 79 80 81 82 83 84 74 75 76 77 78 79 80 81 82 83 84
private var inConstructorFlag = 0L private val byNameArgs = mutable.HashSet[Tree]() private val noApply = mutable.HashSet[Tree]() private val newMembers = mutable.Map[Symbol, mutable.Buffer[Tree]]()
// Expand `Function`s in constructors to class instance creation (SI-6666, SI-8363)
// Expand `Function`s in constructors to class instance creation (scala/bug#6666, scala/bug#8363)
// We use Java's LambdaMetaFactory (LMF), which requires an interface for the sam's owner private def mustExpandFunction(fun: Function) = { // (TODO: Can't use isInterface, yet, as it hasn't been updated for the new trait encoding) val canUseLambdaMetaFactory = (fun.attachments.get[SAMFunction] match { case Some(SAMFunction(userDefinedSamTp, sam)) =>
...
264 265 266 267 268 269 270 271 272 273 274 264 265 266 267 268 269 270 271 272 273 274
def sequenceToArray(tree: Tree) = { val toArraySym = tree.tpe member nme.toArray assert(toArraySym != NoSymbol) def getClassTag(tp: Type): Tree = { val tag = localTyper.resolveClassTag(tree.pos, tp)
// Don't want bottom types getting any further than this (SI-4024)
// Don't want bottom types getting any further than this (scala/bug#4024)
if (tp.typeSymbol.isBottomClass) getClassTag(AnyTpe) else if (!tag.isEmpty) tag else if (tp.bounds.hi ne tp) getClassTag(tp.bounds.hi) else localTyper.TyperErrorGen.MissingClassTagError(tree, tp) }
...
426 427 428 429 430 431 432 433 434 435 436 426 427 428 429 430 431 432 433 434 435 436
val result = if (checkIsElisible(sym)) replaceElidableTree(tree) else translateSynchronized(tree) match { case dd @ DefDef(mods, name, tparams, _, tpt, rhs) =>
// Remove default argument trees from parameter ValDefs, SI-4812
// Remove default argument trees from parameter ValDefs, scala/bug#4812
val vparamssNoRhs = dd.vparamss mapConserve (_ mapConserve {p => treeCopy.ValDef(p, p.mods, p.name, p.tpt, EmptyTree) }) if (dd.symbol hasAnnotation VarargsClass) validateVarargs(dd)
...
462 463 464 465 466 467 468 469 470 471 472 462 463 464 465 466 467 468 469 470 471 472
withNeedLift(needLift = true) { super.transform(tree) } else super.transform(tree) case Apply(fn, args) =>
val needLift = needTryLift || !fn.symbol.isLabel // SI-6749, no need to lift in args to label jumps.
val needLift = needTryLift || !fn.symbol.isLabel // scala/bug#6749, no need to lift in args to label jumps.
withNeedLift(needLift) { val formals = fn.tpe.paramTypes treeCopy.Apply(tree, transform(fn), transformTrees(transformArgs(tree.pos, fn.symbol, args, formals))) }
...
638 639 640 641 642 643 644 645 646 647 648 638 639 640 641 642 643 644 645 646 647 648
* }}} * * This violates the principle that each compiler phase should produce trees that * can be retyped (see [[scala.tools.nsc.typechecker.TreeCheckers]]), and causes * a practical problem in `erasure`: it is not able to correctly determine if
* such a signature overrides a corresponding signature in a parent. (SI-6443).
* such a signature overrides a corresponding signature in a parent. (scala/bug#6443).
* * This transformation erases the dependent method types by: * - Widening the formal parameter type to existentially abstract * over the prior parameters (using `packSymbols`). This transformation * is performed in the `InfoTransform`er [[scala.reflect.internal.transform.UnCurry]].
...
689 690 691 692 693 694 695 696 697 698 699 689 690 691 692 693 694 695 696 697 698 699
// Within the method body, we'll cast the parameter to the originally // declared type and assign this to a synthetic val. Later, we'll patch // the method body to refer to this, rather than the parameter. val tempVal: ValDef = {
// SI-9442: using the "uncurry-erased" type (the one after the uncurry phase) can lead to incorrect
// scala/bug#9442: using the "uncurry-erased" type (the one after the uncurry phase) can lead to incorrect
// tree transformations. For example, compiling: // ``` // def foo(c: Ctx)(l: c.Tree): Unit = { // val l2: c.Tree = l // }

523 524 525 526 527 528 529 530 531 532 533 523 524 525 526 527 528 529 530 531 532 533
* * in general, equality to some type implies equality to its supertypes * (this multi-valued kind of equality is necessary for unreachability) * note that we use subtyping as a model for implication between instanceof tests * i.e., when S <:< T we assume x.isInstanceOf[S] implies x.isInstanceOf[T]
* unfortunately this is not true in general (see e.g. SI-6022)
* unfortunately this is not true in general (see e.g. scala/bug#6022)
*/ def implies(lower: Const, upper: Const): Boolean = // values and null lower == upper || // type implication
...
554 555 556 557 558 559 560 561 562 563 564 554 555 556 557 558 559 560 561 562 563 564
* (2) V = A and V = B, for A and B domain constants, are mutually exclusive unless A == B * * (3) We only reason about test tests as being excluded by null assignments, otherwise we * only consider value assignments. * TODO: refine this, a == 0 excludes a: String, or `a: Int` excludes `a: String`
* (since no value can be of both types. See also SI-7211)
* (since no value can be of both types. See also scala/bug#7211)
* * NOTE: V = 1 does not preclude V = Int, or V = Any, it could be said to preclude * V = String, but we don't model that. */ def excludes(a: Const, b: Const): Boolean = {
...
679 680 681 682 683 684 685 686 687 688 689 679 680 681 682 683 684 685 686 687 688 689
private val trees = mutable.HashSet.empty[Tree] // hashconsing trees (modulo value-equality) private[TreesAndTypesDomain] def uniqueTpForTree(t: Tree): Type = { def freshExistentialSubtype(tp: Type): Type = {
// SI-8611 tp.narrow is tempting, but unsuitable. See `testRefinedTypeSI8611` for an explanation.
// scala/bug#8611 tp.narrow is tempting, but unsuitable. See `testRefinedTypeSI8611` for an explanation.
NoSymbol.freshExistential("", 0).setInfo(TypeBounds.upper(tp)).tpe } if (!t.symbol.isStable) { // Create a fresh type for each unstable value, since we can never correlate it to another value.

19 20 21 22 23 24 25 26 27 28 29 19 20 21 22 23 24 25 26 27 28 29
* Usually, this is the pattern's type because pattern matching implies instance-of checks. * * However, Stable Identifier and Literal patterns are matched using `==`, * which does not imply a type for the binder that binds the matched value. *
* See SI-1503, SI-5024: don't cast binders to types we're not sure they have
* See scala/bug#1503, scala/bug#5024: don't cast binders to types we're not sure they have
* * TODO: update spec as follows (deviation between `**`): * * A pattern binder x@p consists of a pattern variable x and a pattern p. * The type of the variable x is the static type T **IMPLIED BY** the pattern p.
...
50 51 52 53 54 55 56 57 58 59 60 50 51 52 53 54 55 56 57 58 59 60
def unsoundAssumptionUsed = binder.name != nme.WILDCARD && !(pt <:< pat.tpe) if (settings.warnUnsoundMatch && unsoundAssumptionUsed) reporter.warning(pat.pos, sm"""The value matched by $pat is bound to ${binder.name}, which may be used under the |unsound assumption that it has type ${pat.tpe}, whereas we can only safely
|count on it having type $pt, as the pattern is matched using `==` (see SI-1503).""")
|count on it having type $pt, as the pattern is matched using `==` (see scala/bug#1503).""")
pat.tpe }
...
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
} // we use subtyping as a model for implication between instanceof tests // i.e., when S <:< T we assume x.isInstanceOf[S] implies x.isInstanceOf[T] // unfortunately this is not true in general:
// SI-6022 expects instanceOfTpImplies(ProductClass.tpe, AnyRefTpe)
// scala/bug#6022 expects instanceOfTpImplies(ProductClass.tpe, AnyRefTpe)
def instanceOfTpImplies(tp: Type, tpImplied: Type) = { val tpValue = isPrimitiveValueType(tp) // pretend we're comparing to Any when we're actually comparing to AnyVal or AnyRef // (and the subtype is respectively a value type or not a value type) // this allows us to reuse subtyping as a model for implication between instanceOf tests
// the latter don't see a difference between AnyRef, Object or Any when comparing non-value types -- SI-6022
// the latter don't see a difference between AnyRef, Object or Any when comparing non-value types -- scala/bug#6022
val tpImpliedNormalizedToAny = if (tpImplied =:= (if (tpValue) AnyValTpe else AnyRefTpe)) AnyTpe else tpImplied tp <:< tpImpliedNormalizedToAny
...
189 190 191 192 193 194 195 196 197 198 199 189 190 191 192 193 194 195 196 197 198 199
// TODO: this is extremely rough... // replace type args by wildcards, since they can't be checked (don't use existentials: overkill) // TODO: when type tags are available, we will check -- when this is implemented, can we take that into account here? // similar to typer.infer.approximateAbstracts object typeArgsToWildcardsExceptArray extends TypeMap {
// SI-6771 dealias would be enough today, but future proofing with the dealiasWiden.
// scala/bug#6771 dealias would be enough today, but future proofing with the dealiasWiden.
// See neg/t6771b.scala for elaboration def apply(tp: Type): Type = tp.dealias match { case TypeRef(pre, sym, args) if args.nonEmpty && (sym ne ArrayClass) => TypeRef(pre, sym, args map (_ => WildcardType)) case _ =>
...
333 334 335 336 337 338 339 340 341 342 343 333 334 335 336 337 338 339 340 341 342 343
def handleUnknown(tm: TreeMaker): Prop /** apply itself must render a faithful representation of the TreeMaker * * Concretely, True must only be used to represent a TreeMaker that is sure to match and that does not do any computation at all
* e.g., doCSE relies on apply itself being sound in this sense (since it drops TreeMakers that are approximated to True -- SI-6077)
* e.g., doCSE relies on apply itself being sound in this sense (since it drops TreeMakers that are approximated to True -- scala/bug#6077)
* * handleUnknown may be customized by the caller to approximate further * * TODO: don't ignore outer-checks */
...
582 583 584 585 586 587 588 589 590 591 592 582 583 584 585 586 587 588 589 590 591 592
} } object CounterExample { def prune(examples: List[CounterExample]): List[CounterExample] = {
// SI-7669 Warning: we don't used examples.distinct here any more as
// scala/bug#7669 Warning: we don't used examples.distinct here any more as
// we can have A != B && A.coveredBy(B) && B.coveredBy(A) // with Nil and List(). val result = mutable.Buffer[CounterExample]() for (example <- examples if (!result.exists(example coveredBy _))) result += example
...
815 816 817 818 819 820 821 822 823 824 825 815 816 817 818 819 820 821 822 823 824 825
private lazy val ctorParams = if (ctor.paramss.isEmpty) Nil else ctor.paramss.head private lazy val cls = ctor.safeOwner private lazy val caseFieldAccs = cls.caseFieldAccessors def addField(symbol: Symbol, assign: VariableAssignment) {
// SI-7669 Only register this field if if this class contains it.
// scala/bug#7669 Only register this field if if this class contains it.
val shouldConstrainField = !symbol.isCaseAccessor || caseFieldAccs.contains(symbol) if (shouldConstrainField) fields(symbol) = assign } def allFieldAssignmentsLegal: Boolean =

13 14 15 16 17 18 19 20 21 22 23 13 14 15 16 17 18 19 20 21 22 23
import scala.reflect.internal.util.Position /** Optimize and analyze matches based on their TreeMaker-representation. * * The patmat translation doesn't rely on this, so it could be disabled in principle.
* - well, not quite: the backend crashes if we emit duplicates in switches (e.g. SI-7290)
* - well, not quite: the backend crashes if we emit duplicates in switches (e.g. scala/bug#7290)
*/ // TODO: split out match analysis trait MatchOptimization extends MatchTreeMaking with MatchAnalysis { import global._ import global.definitions._
...
396 397 398 399 400 401 402 403 404 405 406 396 397 398 399 400 401 402 403 404 405 406
case _ => false } private def noGuards(cs: List[CaseDef]): Boolean = !cs.exists(isGuardedCase)
// must do this before removing guards from cases and collapsing (SI-6011, SI-6048)
// must do this before removing guards from cases and collapsing (scala/bug#6011, scala/bug#6048)
private def unreachableCase(cases: List[CaseDef]): Option[CaseDef] = { def loop(cases: List[CaseDef]): Option[CaseDef] = cases match { case head :: next :: _ if isDefault(head) => Some(next) // subsumed by the next case, but faster case head :: rest if !isGuardedCase(head) || head.guard.tpe =:= ConstantTrue => rest find caseImplies(head) orElse loop(rest) case head :: _ if head.guard.tpe =:= ConstantFalse => Some(head)
...
436 437 438 439 440 441 442 443 444 445 446 436 437 438 439 440 441 442 443 444 445 446
sequence(switchableAlts) map { switchableAlts => def extractConst(t: Tree) = t match { case Literal(const) => const case _ => t }
// SI-7290 Discard duplicate alternatives that would crash the backend
// scala/bug#7290 Discard duplicate alternatives that would crash the backend
val distinctAlts = distinctBy(switchableAlts)(extractConst) if (distinctAlts.size < switchableAlts.size) { val duplicated = switchableAlts.groupBy(extractConst).flatMap(_._2.drop(1).take(1)) // report the first duplicated reporter.warning(pos, s"Pattern contains duplicate alternatives: ${duplicated.mkString(", ")}") }

239 240 241 242 243 244 245 246 247 248 249 239 240 241 242 243 244 245 246 247 248 249
def translateTry(caseDefs: List[CaseDef], pt: Type, pos: Position): List[CaseDef] = // if they're already simple enough to be handled by the back-end, we're done if (caseDefs forall treeInfo.isCatchCase) caseDefs else { val swatches = { // switch-catches
// SI-7459 must duplicate here as we haven't committed to switch emission, and just figuring out
// scala/bug#7459 must duplicate here as we haven't committed to switch emission, and just figuring out
// if we can ends up mutating `caseDefs` down in the use of `substituteSymbols` in // `TypedSubstitution#Substitution`. That is called indirectly by `emitTypeSwitch`. val bindersAndCases = caseDefs.map(_.duplicate) map { caseDef => // generate a fresh symbol for each case, hoping we'll end up emitting a type-switch (we don't have a global scrut there) // if we fail to emit a fine-grained switch, have to do translateCase again with a single scrutSym (TODO: uniformize substitution on treemakers so we can avoid this)
...
350 351 352 353 354 355 356 357 358 359 360 350 351 352 353 354 355 356 357 358 359 360
*/ /* A pattern binder x@p consists of a pattern variable x and a pattern p. The type of the variable x is the static type T of the pattern p. This pattern matches any value v matched by the pattern p,
provided the run-time type of v is also an instance of T, <-- TODO! https://issues.scala-lang.org/browse/SI-1503
provided the run-time type of v is also an instance of T, <-- TODO! https://github.com/scala/bug/issues/1503
and it binds the variable name to that value. */ /* 8.1.4 Literal Patterns A literal pattern L matches any value that is equal (in terms of ==) to the literal L.
...
496 497 498 499 500 501 502 503 504 505 506 496 497 498 499 500 501 502 503 504 505 506
*/ def treeMaker(binder: Symbol, binderKnownNonNull: Boolean, pos: Position): TreeMaker = { val paramAccessors = aligner.wholeType.typeSymbol.constrParamAccessors val numParams = paramAccessors.length def paramAccessorAt(subPatIndex: Int) = paramAccessors(math.min(subPatIndex, numParams - 1))
// binders corresponding to mutable fields should be stored (SI-5158, SI-6070)
// binders corresponding to mutable fields should be stored (scala/bug#5158, scala/bug#6070)
// make an exception for classes under the scala package as they should be well-behaved, // to optimize matching on List val hasRepeated = paramAccessors.lastOption match { case Some(x) => definitions.isRepeated(x) case _ => false
...
585 586 587 588 589 590 591 592 593 594 595 585 586 587 588 589 590 591 592 593 594 595
REF(binder) setPos pos override def transform(t: Tree) = t match { // duplicated with the extractor Unapplied case Apply(x, List(i @ Ident(nme.SELECTOR_DUMMY))) => treeCopy.Apply(t, x, binderRef(i.pos) :: Nil)
// SI-7868 Account for numeric widening, e.g. <unapplySelector>.toInt
// scala/bug#7868 Account for numeric widening, e.g. <unapplySelector>.toInt
case Apply(x, List(i @ (sel @ Select(Ident(nme.SELECTOR_DUMMY), name)))) => treeCopy.Apply(t, x, treeCopy.Select(sel, binderRef(i.pos), name) :: Nil) case _ => super.transform(t) }

67 68 69 70 71 72 73 74 75 76 77 67 68 69 70 71 72 73 74 75 76 77
* Should not be used to perform actual substitution! * Only used to reason symbolically about the values the subpattern binders are bound to. * See TreeMakerToCond#updateSubstitution. * * Overridden in PreserveSubPatBinders to pretend it replaces the subpattern binders by subpattern refs
* (Even though we don't do so anymore -- see SI-5158, SI-5739 and SI-6070.)
* (Even though we don't do so anymore -- see scala/bug#5158, scala/bug#5739 and scala/bug#6070.)
* * TODO: clean this up, would be nicer to have some higher-level way to compute * the binders bound by this tree maker and the symbolic values that correspond to them */ def subPatternsAsSubstitution: Substitution = substitution
...
131 132 133 134 135 136 137 138 139 140 141 131 132 133 134 135 136 137 138 139 140 141
val subPatBinders: List[Symbol] val subPatRefs: List[Tree] val ignoredSubPatBinders: Set[Symbol] // unless `debugInfoEmitVars`, this set should contain the bare minimum for correctness
// mutable case class fields need to be stored regardless (SI-5158, SI-6070) -- see override in ProductExtractorTreeMaker
// mutable case class fields need to be stored regardless (scala/bug#5158, scala/bug#6070) -- see override in ProductExtractorTreeMaker
// sub patterns bound to wildcard (_) are never stored as they can't be referenced // dirty debuggers will have to get dirty to see the wildcards lazy val storedBinders: Set[Symbol] = (if (debugInfoEmitVars) subPatBinders.toSet else Set.empty) ++ extraStoredBinders -- ignoredSubPatBinders
...
153 154 155 156 157 158 159 160 161 162 163 153 154 155 156 157 158 159 160 161 162 163
} /** The substitution that specifies the trees that compute the values of the subpattern binders. * * We pretend to replace the subpattern binders by subpattern refs
* (Even though we don't do so anymore -- see SI-5158, SI-5739 and SI-6070.)
* (Even though we don't do so anymore -- see scala/bug#5158, scala/bug#5739 and scala/bug#6070.)
*/ override def subPatternsAsSubstitution = Substitution(subPatBinders, subPatRefs) >> super.subPatternsAsSubstitution def bindSubPats(in: Tree): Tree =
...
170 171 172 173 174 175 176 177 178 179 180 170 171 172 173 174 175 176 177 178 179 180
def ref(sym: Symbol) = if (potentiallyStoredBinders(sym)) usedBinders += sym // compute intersection of all symbols in the tree `in` and all potentially stored subpat binders in.foreach { case tt: TypeTree =>
tt.tpe foreach { // SI-7459 e.g. case Prod(t) => new t.u.Foo
tt.tpe foreach { // scala/bug#7459 e.g. case Prod(t) => new t.u.Foo
case SingleType(_, sym) => ref(sym) case _ => } case t => ref(t.symbol) }
...
195 196 197 198 199 200 201 202 203 204 205 195 196 197 198 199 200 201 202 203 204 205
* the function's body is determined by the next TreeMaker * (furthermore, the interpretation of `flatMap` depends on the codegen instance we're using). * * The values for the subpatterns, as computed by the extractor call in `extractor`, * are stored in local variables that re-use the symbols in `subPatBinders`.
* This makes extractor patterns more debuggable (SI-5739).
* This makes extractor patterns more debuggable (scala/bug#5739).
*/ case class ExtractorTreeMaker(extractor: Tree, extraCond: Option[Tree], nextBinder: Symbol)( val subPatBinders: List[Symbol], val subPatRefs: List[Tree], val potentiallyMutableBinders: Set[Symbol],
...
241 242 243 244 245 246 247 248 249 250 251 252 241 242 243 244 245 246 247 248 249 250 251 252
* An optimized version of ExtractorTreeMaker for Products. * For now, this is hard-coded to case classes, and we simply extract the case class fields. * * The values for the subpatterns, as specified by the case class fields at the time of extraction, * are stored in local variables that re-use the symbols in `subPatBinders`.
* This makes extractor patterns more debuggable (SI-5739) as well as * avoiding mutation after the pattern has been matched (SI-5158, SI-6070)
* This makes extractor patterns more debuggable (scala/bug#5739) as well as * avoiding mutation after the pattern has been matched (scala/bug#5158, scala/bug#6070)
* * TODO: make this user-definable as follows * When a companion object defines a method `def unapply_1(x: T): U_1`, but no `def unapply` or `def unapplySeq`, * the extractor is considered to match any non-null value of type T * the pattern is expected to have as many sub-patterns as there are `def unapply_I(x: T): U_I` methods,
...
268 269 270 271 272 273 274 275 276 277 278 268 269 270 271 272 273 274 275 276 277 278
) extends FunTreeMaker with PreserveSubPatBinders { import CODE._ val nextBinder = prevBinder // just passing through
// mutable binders must be stored to avoid unsoundness or seeing mutation of fields after matching (SI-5158, SI-6070)
// mutable binders must be stored to avoid unsoundness or seeing mutation of fields after matching (scala/bug#5158, scala/bug#6070)
def extraStoredBinders: Set[Symbol] = mutableBinders.toSet def chainBefore(next: Tree)(casegen: Casegen): Tree = { val nullCheck = REF(prevBinder) OBJ_NE NULL val cond =
...
402 403 404 405 406 407 408 409 410 411 412 402 403 404 405 406 407 408 409 410 411 412
The bottom types scala.Nothing and scala.Null cannot be used as type patterns, because they would match nothing in any case. - A singleton type p.type. This type pattern matches only the value denoted by the path p (that is, a pattern match involved a comparison of the matched value with p using method eq in class AnyRef). // TODO: the actual pattern matcher uses ==, so that's what I'm using for now
// https://issues.scala-lang.org/browse/SI-4577 "pattern matcher, still disappointing us at equality time"
// https://github.com/scala/bug/issues/4577 "pattern matcher, still disappointing us at equality time"
- A compound type pattern T1 with ... with Tn where each Ti is a type pat- tern. This type pattern matches all values that are matched by each of the type patterns Ti. - A parameterized type pattern T[a1,...,an], where the ai are type variable patterns or wildcards _.
...
464 465 466 467 468 469 470 471 472 473 474 464 465 466 467 468 469 470 471 472 473 474
// I think it's okay: // - the isInstanceOf test includes a test for the element type // - Scala's arrays are invariant (so we don't drop type tests unsoundly) if (extractorArgTypeTest) mkDefault else expectedTp match {
case SingleType(_, sym) => mkEqTest(gen.mkAttributedQualifier(expectedTp)) // SI-4577, SI-4897
case SingleType(_, sym) => mkEqTest(gen.mkAttributedQualifier(expectedTp)) // scala/bug#4577, scala/bug#4897
case ThisType(sym) if sym.isModule => and(mkEqualsTest(CODE.REF(sym)), mkTypeTest) // must use == to support e.g. List() == Nil case ConstantType(Constant(null)) if isAnyRef => mkEqTest(expTp(CODE.NULL)) case ConstantType(const) => mkEqualsTest(expTp(Literal(const))) case ThisType(sym) => mkEqTest(expTp(This(sym))) case _ => mkDefault
...
563 564 565 566 567 568 569 570 571 572 573 563 564 565 566 567 568 569 570 571 572 573
if (settings.XnoPatmatAnalysis) (Suppression.FullSuppression, false) else scrut match { case Typed(tree, tpt) => val suppressExhaustive = tpt.tpe hasAnnotation UncheckedClass val suppressUnreachable = tree match {
case Ident(name) if name startsWith nme.CHECK_IF_REFUTABLE_STRING => true // SI-7183 don't warn for withFilter's that turn out to be irrefutable.
case Ident(name) if name startsWith nme.CHECK_IF_REFUTABLE_STRING => true // scala/bug#7183 don't warn for withFilter's that turn out to be irrefutable.
case _ => false } val suppression = Suppression(suppressExhaustive, suppressUnreachable) val hasSwitchAnnotation = treeInfo.isSwitchAnnotation(tpt.tpe) // matches with two or fewer cases need not apply for switchiness (if-then-else will do)

247 248 249 250 251 252 253 254 255 256 257 247 248 249 250 251 252 253 254 255 256 257
tree1.modifyType(_.substituteTypes(from, toTypes)) } } if (containsSym) { if (to.forall(_.isInstanceOf[Ident]))
tree.duplicate.substituteSymbols(from, to.map(_.symbol)) // SI-7459 catches `case t => new t.Foo`
tree.duplicate.substituteSymbols(from, to.map(_.symbol)) // scala/bug#7459 catches `case t => new t.Foo`
else substIdentsForTrees.transform(tree) } else tree }

134 135 136 137 138 139 140 141 142 143 144 134 135 136 137 138 139 140 141 142 143 144
case nme.unapply => unapplyMethodTypes(context, firstParamType(fn.tpe), sel.tpe, isSeq = false) case nme.unapplySeq => unapplyMethodTypes(context, firstParamType(fn.tpe), sel.tpe, isSeq = true) case _ => applyMethodTypes(fn.tpe) }
/** Rather than let the error that is SI-6675 pollute the entire matching
/** Rather than let the error that is scala/bug#6675 pollute the entire matching
* process, we will tuple the extractor before creation Aligned so that * it contains known good values. */ def productArity = extractor.productArity def acceptMessage = if (extractor.isErroneous) "" else s" to hold ${extractor.offeringString}"
...