Skip to content

Commit

Permalink
Merge pull request #1919 from paulp/pr/fix-merge-210
Browse files Browse the repository at this point in the history
Re-merge of #1906
  • Loading branch information
paulp committed Jan 17, 2013
2 parents bc1d0ca + cc4436a commit d7b59f4
Show file tree
Hide file tree
Showing 49 changed files with 812 additions and 335 deletions.
5 changes: 5 additions & 0 deletions src/compiler/scala/tools/nsc/ast/TreeGen.scala
Expand Up @@ -162,6 +162,11 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
}
}

// drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any
// let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree
def mkCastPreservingAnnotations(tree: Tree, pt: Type) =
Typed(mkCast(tree, pt.withoutAnnotations.dealias), TypeTree(pt))

/** Generate a cast for tree Tree representing Array with
* elem type elemtp to expected type pt.
*/
Expand Down
20 changes: 13 additions & 7 deletions src/compiler/scala/tools/nsc/doc/Settings.scala
Expand Up @@ -6,7 +6,7 @@
package scala.tools.nsc
package doc

import java.net.URI
import java.io.File
import scala.language.postfixOps

/** An extended version of compiler settings, with additional Scaladoc-specific options.
Expand Down Expand Up @@ -70,10 +70,10 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
""
)

val docExternalUris = MultiStringSetting (
"-doc-external-uris",
val docExternalDoc = MultiStringSetting (
"-doc-external-doc",
"external-doc",
"comma-separated list of file://classpath_entry_path#doc_URL URIs for external dependencies"
"comma-separated list of classpath_entry_path#doc_URL pairs describing external dependencies."
)

val useStupidTypes = BooleanSetting (
Expand Down Expand Up @@ -263,9 +263,15 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
map ++ (pkgs map (_ -> url))
}

lazy val extUrlMapping: Map[String, String] = docExternalUris.value map { s =>
val uri = new URI(s)
uri.getSchemeSpecificPart -> appendIndex(uri.getFragment)
lazy val extUrlMapping: Map[String, String] = docExternalDoc.value flatMap { s =>
val idx = s.indexOf("#")
if (idx > 0) {
val (first, last) = s.splitAt(idx)
Some(new File(first).getAbsolutePath -> appendIndex(last.substring(1)))
} else {
error(s"Illegal -doc-external-doc option; expected a pair with '#' separator, found: '$s'")
None
}
} toMap

/**
Expand Down
Expand Up @@ -339,7 +339,7 @@ function configureTextFilter() {
printAlphabet();
var input = $("#textfilter input");
resizeFilterBlock();
input.bind("keydown", function(event) {
input.bind('keyup', function(event) {
if (event.keyCode == 27) { // escape
input.attr("value", "");
}
Expand Down
4 changes: 3 additions & 1 deletion src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
Expand Up @@ -82,7 +82,8 @@ trait ScalaSettings extends AbsScalaSettings
val logFreeTerms = BooleanSetting ("-Xlog-free-terms", "Print a message when reification creates a free term.")
val logFreeTypes = BooleanSetting ("-Xlog-free-types", "Print a message when reification resorts to generating a free type.")
val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None)
val Xmigration28 = BooleanSetting ("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.")
val Xmigration28 = BooleanSetting ("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.").
withDeprecationMessage("This setting is no longer useful and will be removed. Please remove it from your build.")
val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.")
val Xnojline = BooleanSetting ("-Xnojline", "Do not use JLine for editing.")
val Xverify = BooleanSetting ("-Xverify", "Verify generic signatures in generated bytecode (asm backend only.)")
Expand Down Expand Up @@ -170,6 +171,7 @@ trait ScalaSettings extends AbsScalaSettings
val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.")
val Yinvalidate = StringSetting ("-Yinvalidate", "classpath-entry", "Invalidate classpath entry before run", "")
val noSelfCheck = BooleanSetting ("-Yno-self-type-checks", "Suppress check for self-type conformance among inherited members.")
val companionsInPkgObjs = BooleanSetting("-Ycompanions-in-pkg-objs", "Allow companion objects and case classes in package objects. See issue SI-5954.")
val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes")

val exposeEmptyPackage = BooleanSetting("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
Expand Down
5 changes: 3 additions & 2 deletions src/compiler/scala/tools/nsc/transform/UnCurry.scala
Expand Up @@ -461,13 +461,14 @@ abstract class UnCurry extends InfoTransform
val fn1 = withInPattern(false)(transform(fn))
val args1 = transformTrees(fn.symbol.name match {
case nme.unapply => args
case nme.unapplySeq => transformArgs(tree.pos, fn.symbol, args, analyzer.unapplyTypeList(fn.symbol, fn.tpe, args.length))
case nme.unapplySeq => transformArgs(tree.pos, fn.symbol, args, analyzer.unapplyTypeList(fn.pos, fn.symbol, fn.tpe, args.length))
case _ => sys.error("internal error: UnApply node has wrong symbol")
})
treeCopy.UnApply(tree, fn1, args1)

case Apply(fn, args) =>
withNeedLift(true) {
val needLift = needTryLift || !fn.symbol.isLabel // SI-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)))
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/typechecker/Implicits.scala
Expand Up @@ -952,7 +952,7 @@ trait Implicits {
infoMap get sym match {
case Some(infos1) =>
if (infos1.nonEmpty && !(pre =:= infos1.head.pre.prefix)) {
println("amb prefix: "+pre+"#"+sym+" "+infos1.head.pre.prefix+"#"+sym)
log(s"Ignoring implicit members of $pre#$sym as it is also visible via another prefix: ${infos1.head.pre.prefix}")
infoMap(sym) = List() // ambiguous prefix - ignore implicit members
}
case None =>
Expand Down
63 changes: 38 additions & 25 deletions src/compiler/scala/tools/nsc/typechecker/Infer.scala
Expand Up @@ -90,7 +90,7 @@ trait Infer extends Checkable {
* n > 1 and unapply’s result type is Option[(T1, ..., Tn)], for some types T1, ..., Tn.
* the argument patterns p1, ..., pn are typed in turn with expected types T1, ..., Tn
*/
def extractorFormalTypes(resTp: Type, nbSubPats: Int, unappSym: Symbol): (List[Type], List[Type]) = {
def extractorFormalTypes(pos: Position, resTp: Type, nbSubPats: Int, unappSym: Symbol): (List[Type], List[Type]) = {
val isUnapplySeq = unappSym.name == nme.unapplySeq
val booleanExtractor = resTp.typeSymbolDirect == BooleanClass

Expand All @@ -104,11 +104,18 @@ trait Infer extends Checkable {
if (nbSubPats == 0 && booleanExtractor && !isUnapplySeq) Nil
else resTp.baseType(OptionClass).typeArgs match {
case optionTArg :: Nil =>
if (nbSubPats == 1)
def productArgs = getProductArgs(optionTArg)
if (nbSubPats == 1) {
if (isUnapplySeq) List(seqToRepeatedChecked(optionTArg))
else List(optionTArg)
else {
val productArity = productArgs.size
if (productArity > 1 && settings.lint.value)
global.currentUnit.warning(pos, s"extractor pattern binds a single value to a Product${productArity} of type ${optionTArg}")
List(optionTArg)
}
}
// TODO: update spec to reflect we allow any ProductN, not just TupleN
else getProductArgs(optionTArg) match {
else productArgs match {
case Nil if isUnapplySeq => List(seqToRepeatedChecked(optionTArg))
case tps if isUnapplySeq => tps.init :+ seqToRepeatedChecked(tps.last)
case tps => tps
Expand Down Expand Up @@ -569,7 +576,7 @@ trait Infer extends Checkable {

foreach3(tparams, tvars, targs) { (tparam, tvar, targ) =>
val retract = (
targ.typeSymbol == NothingClass // only retract Nothings
targ.typeSymbol == NothingClass // only retract Nothings
&& (restpe.isWildcard || !varianceInType(restpe)(tparam).isPositive) // don't retract covariant occurrences
)

Expand Down Expand Up @@ -851,7 +858,7 @@ trait Infer extends Checkable {
val lencmp = compareLengths(argtpes0, formals)
if (lencmp > 0) tryTupleApply
else if (lencmp == 0) {
// fast track if no named arguments are used
// fast track if no named arguments are used
if (!containsNamedType(argtpes0))
typesCompatible(argtpes0)
else {
Expand Down Expand Up @@ -1177,10 +1184,10 @@ trait Infer extends Checkable {
args: List[Tree], pt0: Type): List[Symbol] = fn.tpe match {
case mt @ MethodType(params0, _) =>
try {
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
val formals = formalTypes(mt.paramTypes, args.length)
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
val formals = formalTypes(mt.paramTypes, args.length)
val argtpes = tupleIfNecessary(formals, args map (x => elimAnonymousClass(x.tpe.deconst)))
val restpe = fn.tpe.resultType(argtpes)
val restpe = fn.tpe.resultType(argtpes)

val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) =
methTypeArgs(undetparams, formals, restpe, argtpes, pt)
Expand Down Expand Up @@ -1289,13 +1296,13 @@ trait Infer extends Checkable {

inferred match {
case Some(targs) =>
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
notifyUndetparamsInferred(undetparams, targs)
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
notifyUndetparamsInferred(undetparams, targs)
case _ =>
def full = if (isFullyDefined(pt)) "(fully defined)" else "(not fully defined)"
devWarning(s"failed inferConstructorInstance for $tree: ${tree.tpe} undet=$undetparams, pt=$pt $full")
// if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt)
ConstrInstantiationError(tree, resTp, pt)
// if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt)
ConstrInstantiationError(tree, resTp, pt)
}
}

Expand Down Expand Up @@ -1491,26 +1498,32 @@ trait Infer extends Checkable {
*/
def inferExprAlternative(tree: Tree, pt: Type) = tree.tpe match {
case OverloadedType(pre, alts) => tryTwice { isSecondTry =>
val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))
val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))
val alts1 = if (alts0.isEmpty) alts else alts0

val bests = bestAlternatives(alts1) { (sym1, sym2) =>
val tp1 = pre.memberType(sym1)
val tp2 = pre.memberType(sym2)
val tp2 = pre.memberType(sym2)

( tp2 == ErrorType
|| (!isWeaklyCompatible(tp2, pt) && isWeaklyCompatible(tp1, pt))
|| isStrictlyMoreSpecific(tp1, tp2, sym1, sym2)
)
}
}
// todo: missing test case for bests.isEmpty
bests match {
case best :: Nil => tree setSymbol best setType (pre memberType best)
case best :: competing :: _ if alts0.nonEmpty => if (!pt.isErroneous) AmbiguousExprAlternativeError(tree, pre, best, competing, pt, isSecondTry)
case best :: competing :: _ if alts0.nonEmpty =>
// SI-6912 Don't give up and leave an OverloadedType on the tree.
// Originally I wrote this as `if (secondTry) ... `, but `tryTwice` won't attempt the second try
// unless an error is issued. We're not issuing an error, in the assumption that it would be
// spurious in light of the erroneous expected type
if (pt.isErroneous) setError(tree)
else AmbiguousExprAlternativeError(tree, pre, best, competing, pt, isSecondTry)
case _ => if (bests.isEmpty || alts0.isEmpty) NoBestExprAlternativeError(tree, pt, isSecondTry)
}
}
}
}

@inline private def inSilentMode(context: Context)(expr: => Boolean): Boolean = {
val oldState = context.state
Expand Down Expand Up @@ -1554,16 +1567,16 @@ trait Infer extends Checkable {
val namesMatch = namesOfNamedArguments(argtpes) match {
case Nil => Nil
case names => eligible filter (m => names forall (name => m.info.params exists (p => paramMatchesName(p, name))))
}
}
if (namesMatch.nonEmpty)
namesMatch
else if (eligible.isEmpty || eligible.tail.isEmpty)
eligible
else
eligible filter (alt =>
!alt.hasDefault && isApplicableBasedOnArity(alt.tpe, argtpes.length, varargsStar, tuplingAllowed = true)
)
}
)
}

/** Assign `tree` the type of an alternative which is applicable
* to `argtpes`, and whose result type is compatible with `pt`.
Expand All @@ -1587,7 +1600,7 @@ trait Infer extends Checkable {
val argtpes = argtpes0 mapConserve {
case RepeatedType(tp) => varargsStar = true ; tp
case tp => tp
}
}
def followType(sym: Symbol) = followApply(pre memberType sym)
def bestForExpectedType(pt: Type, isLastTry: Boolean): Unit = {
val applicable0 = alts filter (alt => inSilentMode(context)(isApplicable(undetparams, followType(alt), argtpes, pt)))
Expand All @@ -1600,16 +1613,16 @@ trait Infer extends Checkable {
case best :: Nil => tree setSymbol best setType (pre memberType best) // success
case Nil if pt eq WildcardType => NoBestMethodAlternativeError(tree, argtpes, pt, isLastTry) // failed
case Nil => bestForExpectedType(WildcardType, isLastTry) // failed, but retry with WildcardType
}
}
}
}
// This potentially makes up to four attempts: tryTwice may execute
// with and without views enabled, and bestForExpectedType will try again
// with pt = WildcardType if it fails with pt != WildcardType.
tryTwice { isLastTry =>
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
debuglog(s"infer method alt ${tree.symbol} with alternatives ${alts map pre.memberType} argtpes=$argtpes pt=$pt")
bestForExpectedType(pt, isLastTry)
}
}
}

/** Try inference twice, once without views and once with views,
Expand Down
15 changes: 5 additions & 10 deletions src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
Expand Up @@ -604,7 +604,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
// Some(this(extractorCall, args)) // TODO: simplify spliceApply?
// }
// }
}
}

abstract class ExtractorCall(val args: List[Tree]) {
val nbSubPats = args.length
Expand Down Expand Up @@ -1470,13 +1470,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
def drop(tgt: Tree)(n: Int): Tree = (tgt DOT vpmName.drop) (LIT(n))
def _equals(checker: Tree, binder: Symbol): Tree = checker MEMBER_== REF(binder) // NOTE: checker must be the target of the ==, that's the patmat semantics for ya

// drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any
// let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree
private def mkCast(t: Tree, tp: Type) =
Typed(gen.mkAsInstanceOf(t, tp.withoutAnnotations, true, false), TypeTree() setType tp)

// the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly)
def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp)
def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else gen.mkCastPreservingAnnotations(REF(b), tp)
def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false)

// duplicated out of frustration with cast generation
Expand Down Expand Up @@ -1820,8 +1815,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
if (cols.isEmpty || cols.tails.isEmpty) cols map toString
else {
val colLens = cols map (c => toString(c).length)
val maxLen = max(colLens)
val avgLen = colLens.sum/colLens.length
val maxLen = max(colLens)
val avgLen = colLens.sum/colLens.length
val goalLen = maxLen min avgLen*2
def pad(s: String) = {
val toAdd = ((goalLen - s.length) max 0) + 2
Expand Down Expand Up @@ -3239,7 +3234,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}

private val defaultLabel: Symbol = newSynthCaseLabel("default")
private val defaultLabel: Symbol = newSynthCaseLabel("default")

/** Collapse guarded cases that switch on the same constant (the last case may be unguarded).
*
Expand Down

0 comments on commit d7b59f4

Please sign in to comment.