diff options
33 files changed, 376 insertions, 85 deletions
@@ -772,6 +772,7 @@ TODO: <stopwatch name="@{project}.timer"/> <mkdir dir="${@{project}-classes}"/> <javac + debug="true" srcdir="${src.dir}/@{project}" destdir="${@{project}-classes}" classpath="${@{project}-classes}" @@ -805,6 +806,7 @@ TODO: <sequential> <javac + debug="true" srcdir="${src.dir}/@{project}" destdir="${build-@{stage}.dir}/classes/@{destproject}" includes="**/*.java" diff --git a/src/build/pack.xml b/src/build/pack.xml index 381d3f1931..20c4034107 100644 --- a/src/build/pack.xml +++ b/src/build/pack.xml @@ -112,8 +112,10 @@ MAIN DISTRIBUTION PACKAGING </target> <target name="pack-archives.latest.unix" depends="pack-archives.src" unless="os.win"> + <!-- be sure to use a relative symlink to make the distribution portable, + `resource` is relative to directory of `link` --> <symlink link="${dists.dir}/archives/scala-latest-sources.tgz" - resource="${dists.dir}/archives/scala-${version.number}-sources.tgz" + resource="scala-${version.number}-sources.tgz" overwrite="yes"/> </target> diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index a70fb5369d..b8791c15dc 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1333,11 +1333,10 @@ self => def parseWhile = { val start = in.offset atPos(in.skipToken()) { - val lname: Name = freshTermName(nme.WHILE_PREFIX) val cond = condExpr() newLinesOpt() val body = expr() - makeWhile(lname, cond, body) + makeWhile(start, cond, body) } } parseWhile diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index cd93221c50..b5771454f8 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -251,8 +251,13 @@ abstract class TreeBuilder { else CompoundTypeTree(Template(tps, emptyValDef, Nil)) /** Create tree representing a while loop */ - def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = { - val continu = atPos(o2p(body.pos pointOrElse wrappingPos(List(cond, body)).pos.endOrPoint)) { Apply(Ident(lname), Nil) } + def makeWhile(startPos: Int, cond: Tree, body: Tree): Tree = { + val lname = freshTermName(nme.WHILE_PREFIX) + def default = wrappingPos(List(cond, body)) match { + case p if p.isDefined => p.endOrPoint + case _ => startPos + } + val continu = atPos(o2p(body.pos pointOrElse default)) { Apply(Ident(lname), Nil) } val rhs = If(cond, Block(List(body), continu), Literal(Constant())) LabelDef(lname, Nil, rhs) } diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 0a469c9227..d9b173bc43 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -897,32 +897,36 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } } - /** */ def makeAnnotation(annot: AnnotationInfo): scala.tools.nsc.doc.model.Annotation = { val aSym = annot.symbol new EntityImpl(aSym, makeTemplate(aSym.owner)) with scala.tools.nsc.doc.model.Annotation { lazy val annotationClass = makeTemplate(annot.symbol) - val arguments = { // lazy - def noParams = annot.args map { _ => None } - val params: List[Option[ValueParam]] = annotationClass match { + val arguments = { + val paramsOpt: Option[List[ValueParam]] = annotationClass match { case aClass: DocTemplateEntity with Class => - (aClass.primaryConstructor map { _.valueParams.head }) match { - case Some(vps) => vps map { Some(_) } - case None => noParams + val constr = aClass.constructors collectFirst { + case c: MemberImpl if c.sym == annot.original.symbol => c } - case _ => noParams + constr flatMap (_.valueParams.headOption) + case _ => None } - assert(params.length == annot.args.length) - (params zip annot.args) flatMap { case (param, arg) => - makeTree(arg) match { - case Some(tree) => - Some(new ValueArgument { - def parameter = param + val argTrees = annot.args map makeTree + paramsOpt match { + case Some (params) => + params zip argTrees map { case (param, tree) => + new ValueArgument { + def parameter = Some(param) def value = tree - }) - case None => None - } + } + } + case None => + argTrees map { tree => + new ValueArgument { + def parameter = None + def value = tree + } + } } } } @@ -962,9 +966,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { sym.name == aSym.name && sym.isParamWithDefault ) - (unit.body find (t => isCorrespondingParam(t.symbol))) match { - case Some(ValDef(_,_,_,rhs)) => makeTree(rhs) - case _ => None + unit.body find (t => isCorrespondingParam(t.symbol)) collect { + case ValDef(_,_,_,rhs) if rhs ne EmptyTree => makeTree(rhs) } case _ => None } diff --git a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala index bd7534ded4..fdad84d0bc 100755 --- a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala @@ -19,7 +19,7 @@ trait TreeFactory { thisTreeFactory: ModelFactory with TreeFactory => val global: Global import global._ - def makeTree(rhs: Tree): Option[TreeEntity] = { + def makeTree(rhs: Tree): TreeEntity = { var expr = new StringBuilder var refs = new immutable.TreeMap[Int, (Entity, Int)] // start, (Entity to be linked to , end) @@ -80,17 +80,16 @@ trait TreeFactory { thisTreeFactory: ModelFactory with TreeFactory => traverser.traverse(rhs) - Some(new TreeEntity { + new TreeEntity { val expression = expr.toString val refEntity = refs - }) + } } - case pos: OffsetPosition => - Some(new TreeEntity { + case _ => + new TreeEntity { val expression = rhs.toString val refEntity = new immutable.TreeMap[Int, (Entity, Int)] - }) - case _ => None + } } } } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index fb2301de65..743530f632 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -52,18 +52,14 @@ abstract class ClassfileParser { private def handleMissing(e: MissingRequirementError) = { if (settings.debug.value) e.printStackTrace - throw new IOException("Missing dependency '" + e.req + "', required by " + in.file) + throw new IOException(s"Missing dependency '${e.req}', required by ${in.file}") } private def handleError(e: Exception) = { if (settings.debug.value) e.printStackTrace() - throw new IOException("class file '%s' is broken\n(%s/%s)".format( - in.file, - e.getClass, - if (e.getMessage eq null) "" else e.getMessage) - ) + throw new IOException(s"class file '${in.file}' is broken\n(${e.getClass}/${e.getMessage})") } private def mismatchError(c: Symbol) = { - throw new IOException("class file '%s' has location not matching its contents: contains ".format(in.file) + c) + throw new IOException(s"class file '${in.file}' has location not matching its contents: contains $c") } private def parseErrorHandler[T]: PartialFunction[Throwable, T] = { @@ -72,8 +68,8 @@ abstract class ClassfileParser { } @inline private def pushBusy[T](sym: Symbol)(body: => T): T = { busy match { - case Some(`sym`) => throw new IOException("unsatisfiable cyclic dependency in '%s'".format(sym)) - case Some(sym1) => throw new IOException("illegal class file dependency between '%s' and '%s'".format(sym, sym1)) + case Some(`sym`) => throw new IOException(s"unsatisfiable cyclic dependency in '$sym'") + case Some(sym1) => throw new IOException(s"illegal class file dependency between '$sym' and '$sym1'") case _ => () } @@ -232,8 +228,6 @@ abstract class ClassfileParser { forceMangledName(tpe0.typeSymbol.name, false) val (name, tpe) = getNameAndType(in.getChar(start + 3), ownerTpe) -// println("new tpe: " + tpe + " at phase: " + phase) - if (name == nme.MODULE_INSTANCE_FIELD) { val index = in.getChar(start + 1) val name = getExternalName(in.getChar(starts(index) + 1)) @@ -244,14 +238,12 @@ abstract class ClassfileParser { } else { val origName = nme.originalName(name) val owner = if (static) ownerTpe.typeSymbol.linkedClassOfClass else ownerTpe.typeSymbol -// println("\t" + owner.info.member(name).tpe.widen + " =:= " + tpe) f = owner.info.findMember(origName, 0, 0, false).suchThat(_.tpe.widen =:= tpe) if (f == NoSymbol) f = owner.info.findMember(newTermName(origName + nme.LOCAL_SUFFIX_STRING), 0, 0, false).suchThat(_.tpe =:= tpe) if (f == NoSymbol) { // if it's an impl class, try to find it's static member inside the class if (ownerTpe.typeSymbol.isImplClass) { -// println("impl class, member: " + owner.tpe.member(origName) + ": " + owner.tpe.member(origName).tpe) f = ownerTpe.findMember(origName, 0, 0, false).suchThat(_.tpe =:= tpe) } else { log("Couldn't find " + name + ": " + tpe + " inside: \n" + ownerTpe) @@ -262,11 +254,13 @@ abstract class ClassfileParser { f setInfo tpe log("created fake member " + f.fullName) } -// println("\townerTpe.decls: " + ownerTpe.decls) -// println("Looking for: " + name + ": " + tpe + " inside: " + ownerTpe.typeSymbol + "\n\tand found: " + ownerTpe.members) } } - assert(f != NoSymbol, "could not find\n " + name + ": " + tpe + "\ninside:\n " + ownerTpe.members.mkString(", ")) + assert(f != NoSymbol, + s"could not find $name: $tpe in $ownerTpe" + ( + if (settings.debug.value) ownerTpe.members.mkString(", members are:\n ", "\n ", "") else "" + ) + ) values(index) = f } f @@ -586,11 +580,9 @@ abstract class ClassfileParser { def addEnclosingTParams(clazz: Symbol) { var sym = clazz.owner while (sym.isClass && !sym.isModuleClass) { -// println("adding tparams of " + sym) - for (t <- sym.tpe.typeArgs) { -// println("\tadding " + (t.typeSymbol.name + "->" + t.typeSymbol)) + for (t <- sym.tpe.typeArgs) classTParams = classTParams + (t.typeSymbol.name -> t.typeSymbol) - } + sym = sym.owner } } @@ -740,10 +732,7 @@ abstract class ClassfileParser { // raw type - existentially quantify all type parameters val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams) val t = typeRef(pre, classSym, eparams.map(_.tpeHK)) - val res = newExistentialType(eparams, t) - if (settings.debug.value && settings.verbose.value) - println("raw type " + classSym + " -> " + res) - res + newExistentialType(eparams, t) } case tp => assert(sig.charAt(index) != '<', s"sig=$sig, index=$index, tp=$tp") @@ -865,8 +854,6 @@ abstract class ClassfileParser { val sig = pool.getExternalName(in.nextChar) val newType = sigToType(sym, sig) sym.setInfo(newType) - if (settings.debug.value && settings.verbose.value) - println("" + sym + "; signature = " + sig + " type = " + newType) } else in.skip(attrLen) case tpnme.SyntheticATTR => @@ -883,10 +870,10 @@ abstract class ClassfileParser { val c = pool.getConstant(in.nextChar) val c1 = convertTo(c, symtype) if (c1 ne null) sym.setInfo(ConstantType(c1)) - else println("failure to convert " + c + " to " + symtype); //debug + else debugwarn(s"failure to convert $c to $symtype") case tpnme.ScalaSignatureATTR => if (!isScalaAnnot) { - debuglog("warning: symbol " + sym.fullName + " has pickled signature in attribute") + debugwarn(s"symbol ${sym.fullName} has pickled signature in attribute") unpickler.unpickle(in.buf, in.bp, clazz, staticModule, in.file.name) } in.skip(attrLen) @@ -1018,16 +1005,18 @@ abstract class ClassfileParser { } if (hasError) None else Some(AnnotationInfo(attrType, List(), nvpairs.toList)) - } catch { - case f: FatalError => throw f // don't eat fatal errors, they mean a class was not found - case ex: Throwable => + } + catch { + case f: FatalError => throw f // don't eat fatal errors, they mean a class was not found + case ex: java.lang.Error => throw ex + case ex: Throwable => // We want to be robust when annotations are unavailable, so the very least // we can do is warn the user about the exception // There was a reference to ticket 1135, but that is outdated: a reference to a class not on // the classpath would *not* end up here. A class not found is signaled // with a `FatalError` exception, handled above. Here you'd end up after a NPE (for example), // and that should never be swallowed silently. - warning("Caught: " + ex + " while parsing annotations in " + in.file) + warning(s"Caught: $ex while parsing annotations in ${in.file}") if (settings.debug.value) ex.printStackTrace() None // ignore malformed annotations diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index e8b0cd2696..c3aded2b2d 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -293,7 +293,6 @@ abstract class Pickler extends SubComponent { putTree(definition) */ case Template(parents, self, body) => - writeNat(parents.length) putTrees(parents) putTree(self) putTrees(body) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala index 0fab48028e..dbe08315f4 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala @@ -385,18 +385,35 @@ trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis { // else debug.patmat("NOT implies: "+(lower, upper)) - /** does V = C preclude V having value `other`? - (1) V = null is an exclusive assignment, - (2) V = A and V = B, for A and B value constants, are mutually exclusive unless A == B - we err on the safe side, for example: - - assume `val X = 1; val Y = 1`, then - (2: Int) match { case X => case Y => <falsely considered reachable> } - - V = 1 does not preclude V = Int, or V = Any, it could be said to preclude V = String, but we don't model that - - (3) for types we could try to do something fancy, but be conservative and just say no + /** Does V=A preclude V=B? + * + * (0) A or B must be in the domain to draw any conclusions. + * + * For example, knowing the the scrutinee is *not* true does not + * statically exclude it from being `X`, because that is an opaque + * Boolean. + * + * val X = true + * (true: Boolean) match { case true => case X <reachable> } + * + * (1) V = null excludes assignment to any other constant (modulo point #0). This includes + * both values and type tests (which are both modelled here as `Const`) + * (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) + * + * 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 = - a != b && ((a == NullConst || b == NullConst) || (a.isValue && b.isValue)) + def excludes(a: Const, b: Const): Boolean = { + val bothInDomain = domain exists (d => d(a) && d(b)) + val eitherIsNull = a == NullConst || b == NullConst + val bothAreValues = a.isValue && b.isValue + bothInDomain && (eitherIsNull || bothAreValues) && (a != b) + } // if(r) debug.patmat("excludes : "+(a, a.tp, b, b.tp)) // else debug.patmat("NOT excludes: "+(a, b)) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index d9f93f27b6..9558542533 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -99,7 +99,9 @@ trait TreeAndTypeAnalysis extends Debugging { // 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 { - def apply(tp: Type): Type = tp match { + // SI-6771 dealias would be enough today, but future proofing with the dealiasWiden. + // See neg/t6771b.scala for elaboration + def apply(tp: Type): Type = tp.dealiasWiden match { case TypeRef(pre, sym, args) if args.nonEmpty && (sym ne ArrayClass) => TypeRef(pre, sym, args map (_ => WildcardType)) case _ => diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 01ae0a7a94..04e0b9d653 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -149,7 +149,7 @@ trait Implicits { class SearchResult(val tree: Tree, val subst: TreeTypeSubstituter) { override def toString = "SearchResult(%s, %s)".format(tree, if (subst.isEmpty) "" else subst) - + def isFailure = false def isAmbiguousFailure = false final def isSuccess = !isFailure @@ -158,7 +158,7 @@ trait Implicits { lazy val SearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) { override def isFailure = true } - + lazy val AmbiguousSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) { override def isFailure = true override def isAmbiguousFailure = true @@ -892,11 +892,20 @@ trait Implicits { */ if (divergence) throw DivergentImplicit - - if (invalidImplicits.nonEmpty) + else invalidImplicits take 1 foreach { sym => + def isSensibleAddendum = pt match { + case Function1(_, out) => out <:< sym.tpe.finalResultType + case tp => tp <:< sym.tpe.finalResultType + case _ => false + } + // Don't pitch in with this theory unless it looks plausible that the + // implicit would have helped setAddendum(pos, () => - "\n Note: implicit "+invalidImplicits.head+" is not applicable here"+ - " because it comes after the application point and it lacks an explicit result type") + if (isSensibleAddendum) + s"\n Note: implicit $sym is not applicable here because it comes after the application point and it lacks an explicit result type" + else "" + ) + } } best diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 7f8aeceeec..94d92af228 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1063,9 +1063,13 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case _ => } + private def isObjectOrAnyComparisonMethod(sym: Symbol) = sym match { + case Object_eq | Object_ne | Object_== | Object_!= | Any_== | Any_!= => true + case _ => false + } def checkSensible(pos: Position, fn: Tree, args: List[Tree]) = fn match { - case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 => - def isReferenceOp = name == nme.eq || name == nme.ne + case Select(qual, name @ (nme.EQ | nme.NE | nme.eq | nme.ne)) if args.length == 1 && isObjectOrAnyComparisonMethod(fn.symbol) => + def isReferenceOp = fn.symbol == Object_eq || fn.symbol == Object_ne def isNew(tree: Tree) = tree match { case Function(_, _) | Apply(Select(New(_), nme.CONSTRUCTOR), _) => true @@ -1411,6 +1415,16 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } } + private def checkDelayedInitSelect(qual: Tree, sym: Symbol, pos: Position) = { + def isLikelyUninitialized = ( + (sym.owner isSubClass DelayedInitClass) + && !qual.tpe.isInstanceOf[ThisType] + && sym.accessedOrSelf.isVal + ) + if (settings.lint.value && isLikelyUninitialized) + unit.warning(pos, s"Selecting ${sym} from ${sym.owner}, which extends scala.DelayedInit, is likely to yield an uninitialized value") + } + private def lessAccessible(otherSym: Symbol, memberSym: Symbol): Boolean = ( (otherSym != NoSymbol) && !otherSym.isProtected @@ -1610,6 +1624,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans if(settings.Xmigration.value != NoScalaVersion) checkMigration(sym, tree.pos) checkCompileTimeOnly(sym, tree.pos) + checkDelayedInitSelect(qual, sym, tree.pos) if (sym eq NoSymbol) { unit.warning(tree.pos, "Select node has NoSymbol! " + tree + " / " + tree.tpe) diff --git a/test/files/neg/delayed-init-ref.check b/test/files/neg/delayed-init-ref.check new file mode 100644 index 0000000000..42ccabed1b --- /dev/null +++ b/test/files/neg/delayed-init-ref.check @@ -0,0 +1,10 @@ +delayed-init-ref.scala:17: error: Selecting value vall from object O, which extends scala.DelayedInit, is likely to yield an uninitialized value + println(O.vall) // warn + ^ +delayed-init-ref.scala:19: error: Selecting value vall from object O, which extends scala.DelayedInit, is likely to yield an uninitialized value + println(vall) // warn + ^ +delayed-init-ref.scala:40: error: Selecting value foo from trait UserContext, which extends scala.DelayedInit, is likely to yield an uninitialized value + println({locally(()); this}.foo) // warn (spurious, but we can't discriminate) + ^ +three errors found diff --git a/test/files/neg/delayed-init-ref.flags b/test/files/neg/delayed-init-ref.flags new file mode 100644 index 0000000000..7949c2afa2 --- /dev/null +++ b/test/files/neg/delayed-init-ref.flags @@ -0,0 +1 @@ +-Xlint -Xfatal-warnings diff --git a/test/files/neg/delayed-init-ref.scala b/test/files/neg/delayed-init-ref.scala new file mode 100644 index 0000000000..f2aa804e28 --- /dev/null +++ b/test/files/neg/delayed-init-ref.scala @@ -0,0 +1,42 @@ +trait T { + val traitVal = "" +} + +object O extends App with T { + val vall = "" + lazy val lazyy = "" + def deff = "" + + println(vall) // no warn + new { + println(vall) // no warn + } +} + +object Client { + println(O.vall) // warn + import O.vall + println(vall) // warn + + println(O.lazyy) // no warn + println(O.deff) // no warn + println(O.traitVal) // no warn +} + +// Delayed init usage pattern from Specs2 +// See: https://groups.google.com/d/msg/scala-sips/wP6dL8nIAQs/ogjoPE-MSVAJ +trait Before extends DelayedInit { + def before() + override def delayedInit(x: => Unit): Unit = { before; x } +} +object Spec { + trait UserContext extends Before { + def before() = () + val foo = "foo" + } + new UserContext { + println(foo) // no warn + println(this.foo) // no warn + println({locally(()); this}.foo) // warn (spurious, but we can't discriminate) + } +} diff --git a/test/files/neg/t6771b.check b/test/files/neg/t6771b.check new file mode 100644 index 0000000000..ba99e9178d --- /dev/null +++ b/test/files/neg/t6771b.check @@ -0,0 +1,6 @@ +t6771b.scala:14: error: type mismatch; + found : x.type (with underlying type String) + required: Test.a.type + b = b match { case x => x } + ^ +one error found diff --git a/test/files/neg/t6771b.scala b/test/files/neg/t6771b.scala new file mode 100644 index 0000000000..78f11f7750 --- /dev/null +++ b/test/files/neg/t6771b.scala @@ -0,0 +1,16 @@ +// Currently, the pattern matcher widens the type of the +// scrutinee, so this doesn't typecheck. This test just +// confirms this behaviour, although it would be an improvement +// to change this and make this a `pos` test. +// +// But, to the intrepid hacker who works on this, a few notes: +// You'll have to look into places in the pattern matcher that +// call `dealias`, and see if they need to be `dealiasWiden`. +// For example, if `checkableType` used only `dealias`, `pos/t6671.scala` +// would fail. +object Test { + val a = ""; var b: a.type = a + + b = b match { case x => x } +} + diff --git a/test/files/neg/t7369.check b/test/files/neg/t7369.check new file mode 100644 index 0000000000..4f101e145a --- /dev/null +++ b/test/files/neg/t7369.check @@ -0,0 +1,13 @@ +t7369.scala:6: error: unreachable code + case Tuple1(X) => // unreachable + ^ +t7369.scala:13: error: unreachable code + case Tuple1(true) => // unreachable + ^ +t7369.scala:31: error: unreachable code + case Tuple1(X) => // unreachable + ^ +t7369.scala:40: error: unreachable code + case Tuple1(null) => // unreachable + ^ +four errors found diff --git a/test/files/neg/t7369.flags b/test/files/neg/t7369.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/neg/t7369.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/neg/t7369.scala b/test/files/neg/t7369.scala new file mode 100644 index 0000000000..87ddfe98b7 --- /dev/null +++ b/test/files/neg/t7369.scala @@ -0,0 +1,43 @@ +object Test { + val X, Y = true + (null: Tuple1[Boolean]) match { + case Tuple1(X) => + case Tuple1(Y) => + case Tuple1(X) => // unreachable + case _ => + } + + (null: Tuple1[Boolean]) match { + case Tuple1(true) => + case Tuple1(false) => + case Tuple1(true) => // unreachable + case _ => + } +} + + +sealed abstract class B; +case object True extends B; +case object False extends B; + +object Test2 { + + val X: B = True + val Y: B = False + + (null: Tuple1[B]) match { + case Tuple1(X) => + case Tuple1(Y) => + case Tuple1(X) => // unreachable + case _ => + } +} + +object Test3 { + (null: Tuple1[B]) match { + case Tuple1(null) => + case Tuple1(True) => + case Tuple1(null) => // unreachable + case _ => + } +} diff --git a/test/files/neg/t7385.check b/test/files/neg/t7385.check new file mode 100644 index 0000000000..70d3c3fb61 --- /dev/null +++ b/test/files/neg/t7385.check @@ -0,0 +1,10 @@ +t7385.scala:2: error: '(' expected but identifier found. + do { println("bippy") } while i<10 + ^ +t7385.scala:6: error: '(' expected but identifier found. + while i<10 { () } + ^ +t7385.scala:7: error: illegal start of simple expression +} +^ +three errors found diff --git a/test/files/neg/t7385.scala b/test/files/neg/t7385.scala new file mode 100644 index 0000000000..a7f801098b --- /dev/null +++ b/test/files/neg/t7385.scala @@ -0,0 +1,7 @@ +object Bar { + do { println("bippy") } while i<10 +} + +object Foo { + while i<10 { () } +} diff --git a/test/files/neg/t7441.check b/test/files/neg/t7441.check new file mode 100644 index 0000000000..f259457197 --- /dev/null +++ b/test/files/neg/t7441.check @@ -0,0 +1,6 @@ +t7441.scala:4: error: type mismatch; + found : Int(1) + required: List[Any] + def test = apply(1) + ^ +one error found diff --git a/test/files/neg/t7441.scala b/test/files/neg/t7441.scala new file mode 100644 index 0000000000..dad7421e3f --- /dev/null +++ b/test/files/neg/t7441.scala @@ -0,0 +1,7 @@ +object Test { + object Bar { + def apply(xs: List[Any]): Int = 0 + def test = apply(1) + } + implicit def foo = 1 +} diff --git a/test/files/pos/t6091.flags b/test/files/pos/t6091.flags new file mode 100644 index 0000000000..954eaba352 --- /dev/null +++ b/test/files/pos/t6091.flags @@ -0,0 +1 @@ +-Xfatal-warnings -Xlint diff --git a/test/files/pos/t6091.scala b/test/files/pos/t6091.scala new file mode 100644 index 0000000000..72e663ec3b --- /dev/null +++ b/test/files/pos/t6091.scala @@ -0,0 +1,10 @@ +object Foo { def eq(x:Int) = x } + +class X { def ==(other: String) = true } + +object Test { + def main(args: Array[String]): Unit = { + Foo eq 1 + new X == null + } +} diff --git a/test/files/pos/t6771.flags b/test/files/pos/t6771.flags new file mode 100644 index 0000000000..e8fb65d50c --- /dev/null +++ b/test/files/pos/t6771.flags @@ -0,0 +1 @@ +-Xfatal-warnings
\ No newline at end of file diff --git a/test/files/pos/t6771.scala b/test/files/pos/t6771.scala new file mode 100644 index 0000000000..0f0bd4e4a0 --- /dev/null +++ b/test/files/pos/t6771.scala @@ -0,0 +1,9 @@ +object Test { + type Id[X] = X + val a: Id[Option[Int]] = None + + a match { + case Some(x) => println(x) + case None => + } +} diff --git a/test/files/pos/t7369.flags b/test/files/pos/t7369.flags new file mode 100644 index 0000000000..85d8eb2ba2 --- /dev/null +++ b/test/files/pos/t7369.flags @@ -0,0 +1 @@ +-Xfatal-warnings diff --git a/test/files/pos/t7369.scala b/test/files/pos/t7369.scala new file mode 100644 index 0000000000..2f31c93d29 --- /dev/null +++ b/test/files/pos/t7369.scala @@ -0,0 +1,37 @@ +object Test { + val X, Y = true + (null: Tuple1[Boolean]) match { + case Tuple1(X) => + case Tuple1(Y) => // unreachable + case _ => + } +} + + +sealed abstract class B; +case object True extends B; +case object False extends B; + +object Test2 { + + val X: B = True + val Y: B = False + + (null: Tuple1[B]) match { + case Tuple1(X) => + case Tuple1(Y) => // no warning + case _ => + } +} + +object Test3 { + val X, O = true + def classify(neighbourhood: (Boolean, Boolean, Boolean)): String = { + neighbourhood match { + case (X, X, X) => "middle" + case (X, X, O) => "right" + case (O, X, X) => "left" + case _ => throw new IllegalArgumentException("Invalid") + } + } +}
\ No newline at end of file diff --git a/test/files/pos/t7426.scala b/test/files/pos/t7426.scala new file mode 100644 index 0000000000..8e42ad1812 --- /dev/null +++ b/test/files/pos/t7426.scala @@ -0,0 +1,3 @@ +class foo(x: Any) extends annotation.StaticAnnotation + +@foo(new AnyRef { }) trait A diff --git a/test/scaladoc/run/SI-7367.check b/test/scaladoc/run/SI-7367.check new file mode 100755 index 0000000000..3925a0d464 --- /dev/null +++ b/test/scaladoc/run/SI-7367.check @@ -0,0 +1 @@ +Done.
\ No newline at end of file diff --git a/test/scaladoc/run/SI-7367.scala b/test/scaladoc/run/SI-7367.scala new file mode 100755 index 0000000000..6e5a317932 --- /dev/null +++ b/test/scaladoc/run/SI-7367.scala @@ -0,0 +1,25 @@ +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest + +object Test extends ScaladocModelTest { + override def code = """ + class annot() extends annotation.StaticAnnotation { + def this(a: Any) = this() + } + + @annot(0) + class B + """ + + def scaladocSettings = "" + + def testModel(root: Package) = { + import access._ + val annotations = root._class("B").annotations + assert(annotations.size == 1) + assert(annotations(0).annotationClass == root._class("annot")) + val args = annotations(0).arguments + assert(args.size == 1) + assert(args(0).value.expression == "0") + } +} |