Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class ScalaSettings extends Settings.SettingGroup {
*/
val dependencyfile = StringSetting("-dependencyfile", "file", "Set dependency tracking file.", ".scala_dependencies")
val deprecation = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.")
val migration = BooleanSetting("-migration", "Emit warning and location for migration issues from Scala 2.")
val encoding = StringSetting("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding)
val explaintypes = BooleanSetting("-explaintypes", "Explain type errors in more detail.")
val feature = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.")
Expand Down
4 changes: 3 additions & 1 deletion src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
projection.name == tpnme.hkApply &&
!other.isHKApply &&
other.testLifted(projection.prefix.LambdaClass(forcing = true).typeParams,
if (inOrder) isSubType(projection.prefix, _) else isSubType(_, projection.prefix),
{ xx => println(i"test lifted with $xx")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

println left in code.

if (inOrder) isSubType(projection.prefix, xx) else isSubType(xx, projection.prefix)
},
if (inOrder) Nil else classBounds(projection.prefix))

/** The class symbols bounding the type of the `Apply` member of `tp` */
Expand Down
10 changes: 10 additions & 0 deletions src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package core
import Contexts._, Types._, Symbols._, Names._, Flags._, Scopes._
import SymDenotations._, Denotations.Denotation
import config.Printers._
import util.Positions._
import Decorators._
import StdNames._
import util.SimpleMap
Expand Down Expand Up @@ -572,6 +573,15 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
/** Is auto-tupling enabled? */
def canAutoTuple =
!featureEnabled(defn.LanguageModuleClass, nme.noAutoTupling)

def scala2Mode =
featureEnabled(defn.LanguageModuleClass, nme.Scala2)

def testScala2Mode(msg: String, pos: Position) = {
if (scala2Mode) migrationWarning(msg, pos)
scala2Mode
}

}

object TypeOps {
Expand Down
13 changes: 9 additions & 4 deletions src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,11 @@ object Parsers {
}

/** Cannot use ctx.featureEnabled because accessing the context would force too much */
private def scala2mode = ctx.settings.language.value.contains(nme.Scala2.toString)
private def testScala2Mode(msg: String, pos: Position = Position(in.offset)) = {
val s2 = ctx.settings.language.value.contains(nme.Scala2.toString)
if (s2) ctx.migrationWarning(msg, source atPos pos)
s2
}

/* ---------- TREE CONSTRUCTION ------------------------------------------- */

Expand Down Expand Up @@ -1726,12 +1730,13 @@ object Parsers {
* DefSig ::= id [DefTypeParamClause] ParamClauses
*/
def defDefOrDcl(mods: Modifiers): Tree = atPos(tokenRange) {
def atScala2Brace = scala2mode && in.token == LBRACE
def scala2ProcedureSyntax =
testScala2Mode("Procedure syntax no longer supported; `=' should be inserted here")
if (in.token == THIS) {
in.nextToken()
val vparamss = paramClauses(nme.CONSTRUCTOR)
val rhs = {
if (!atScala2Brace) accept(EQUALS)
if (!scala2ProcedureSyntax || in.token != LBRACE) accept(EQUALS)
atPos(in.offset) { constrExpr() }
}
makeConstructor(Nil, vparamss, rhs).withMods(mods)
Expand All @@ -1748,7 +1753,7 @@ object Parsers {
}
else if (!tpt.isEmpty)
EmptyTree
else if (scala2mode) {
else if (scala2ProcedureSyntax) {
tpt = scalaUnit
if (in.token == LBRACE) expr()
else EmptyTree
Expand Down
6 changes: 6 additions & 0 deletions src/dotty/tools/dotc/reporting/Reporter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ object Reporter {
class DeprecationWarning(msgFn: => String, pos: SourcePosition) extends ConditionalWarning(msgFn, pos) {
def enablingOption(implicit ctx: Context) = ctx.settings.deprecation
}
class MigrationWarning(msgFn: => String, pos: SourcePosition) extends ConditionalWarning(msgFn, pos) {
def enablingOption(implicit ctx: Context) = ctx.settings.migration
}
}

import Reporter._
Expand All @@ -82,6 +85,9 @@ trait Reporting { this: Context =>
def deprecationWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
reporter.report(new DeprecationWarning(msg, pos))

def migrationWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
reporter.report(new MigrationWarning(msg, pos))

def uncheckedWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
reporter.report(new UncheckedWarning(msg, pos))

Expand Down
12 changes: 8 additions & 4 deletions src/dotty/tools/dotc/typer/VarianceChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,20 @@ class VarianceChecker()(implicit ctx: Context) {
private object Traverser extends TreeTraverser {
def checkVariance(sym: Symbol) = Validator.validateDefinition(sym) match {
case Some(VarianceError(tvar, required)) =>
ctx.error(
i"${varianceString(tvar.flags)} $tvar occurs in ${varianceString(required)} position in type ${sym.info} of $sym",
sym.pos)
def msg = i"${varianceString(tvar.flags)} $tvar occurs in ${varianceString(required)} position in type ${sym.info} of $sym"
if (ctx.scala2Mode && sym.owner.isConstructor)
ctx.migrationWarning(s"According to new variance rules, this is no longer accepted; need to annotate with @uncheckedVariance:\n$msg", sym.pos)
else ctx.error(msg, sym.pos)
case None =>
}

override def traverse(tree: Tree)(implicit ctx: Context) = {
def sym = tree.symbol
// No variance check for private/protected[this] methods/values.
def skip = !sym.exists || sym.is(Local)
def skip =
!sym.exists ||
sym.is(Local) || // !!! watch out for protected local!
sym.is(TypeParam) && sym.owner.isClass // already taken care of in primary constructor of class
tree match {
case defn: MemberDef if skip =>
ctx.debuglog(s"Skipping variance check of ${sym.showDcl}")
Expand Down
2 changes: 2 additions & 0 deletions test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class tests extends CompilerTest {

@Test def pos_t2613 = compileFile(posSpecialDir, "t2613")(allowDeepSubtypes)
@Test def pos_i871 = compileFile(posSpecialDir, "i871", scala2mode)
@Test def pos_variancesConstr = compileFile(posSpecialDir, "variances-constr", scala2mode)

@Test def new_all = compileFiles(newDir, twice)

Expand Down Expand Up @@ -137,6 +138,7 @@ class tests extends CompilerTest {
@Test def neg_t2994 = compileFile(negDir, "t2994", xerrors = 2)
@Test def neg_subtyping = compileFile(negDir, "subtyping", xerrors = 5)
@Test def neg_variances = compileFile(negDir, "variances", xerrors = 2)
@Test def neg_variancesConstr = compileFile(negDir, "variances-constr", xerrors = 2)
@Test def neg_i871_missingReturnType = compileFile(negDir, "i871", xerrors = 2)
@Test def neg_badAuxConstr = compileFile(negDir, "badAuxConstr", xerrors = 2)
@Test def neg_typetest = compileFile(negDir, "typetest", xerrors = 1)
Expand Down
26 changes: 26 additions & 0 deletions tests/neg/variances-constr.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class C[+A] {

private[this] var y: A = _
def getY: A = y

class Inner(x: A) { // error A appears contravariantly
y = x
}
class Inner2[B <: A](x: B) { // error A appears contravariantly
y = x
}
}

object Test {

def main(args: Array[String]) = {
val x = new C[String]
val y: C[Any] = x
val i = new y.Inner(1)
val s: String = x.getY
val i2 = new y.Inner2(1)
val s2: String = x.getY
println(s)
}
}

21 changes: 21 additions & 0 deletions tests/pos-special/variances-constr.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class C[+A] {

private[this] var y: A = _
def getY: A = y

class Inner(x: A) {
y = x
}
}

object Test {

def main(args: Array[String]) = {
val x = new C[String]
val y: C[Any] = x
val i = new y.Inner(1)
val s: String = x.getY
println(s)
}
}