Skip to content

Don't use _ as a binder for abstract type arguments in patterns #12201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 25, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ class PlainPrinter(_ctx: Context) extends Printer {
Text(lam.paramNames.lazyZip(lam.paramInfos).map(paramText), ", ")
}

protected def ParamRefNameString(name: Name): String = name.toString
protected def ParamRefNameString(name: Name): String = nameString(name)

protected def ParamRefNameString(param: ParamRef): String =
ParamRefNameString(param.binder.paramNames(param.paramNum))
Expand Down
8 changes: 3 additions & 5 deletions compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import typer.ProtoTypes._
import Trees._
import TypeApplications._
import Decorators._
import NameKinds.WildcardParamName
import util.Chars.isOperatorPart
import transform.TypeUtils._
import transform.SymUtils._
Expand Down Expand Up @@ -76,8 +77,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}

override def nameString(name: Name): String =
if ctx.settings.YdebugNames.value
then name.debugString
if ctx.settings.YdebugNames.value then name.debugString
else if name.isTypeName && name.is(WildcardParamName) && !printDebug then "_"
else super.nameString(name)

override protected def simpleNameString(sym: Symbol): String =
Expand Down Expand Up @@ -963,9 +964,6 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
def optText[T >: Untyped](tree: List[Tree[T]])(encl: Text => Text): Text =
if (tree.exists(!_.isEmpty)) encl(blockText(tree)) else ""

override protected def ParamRefNameString(name: Name): String =
name.toString

override protected def treatAsTypeParam(sym: Symbol): Boolean = sym.is(TypeParam)

override protected def treatAsTypeArg(sym: Symbol): Boolean =
Expand Down
11 changes: 6 additions & 5 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1560,9 +1560,9 @@ class Typer extends Namer
super.transform(trt.withType(stripTypeVars(trt.tpe))) match {
case b: Bind =>
val sym = b.symbol
if (sym.name != tpnme.WILDCARD)
if (ctx.scope.lookup(b.name) == NoSymbol) ctx.enter(sym)
else report.error(new DuplicateBind(b, cdef), b.srcPos)
assert(sym.name != tpnme.WILDCARD)
if ctx.scope.lookup(b.name) == NoSymbol then ctx.enter(sym)
else report.error(new DuplicateBind(b, cdef), b.srcPos)
if (!ctx.isAfterTyper) {
val bounds = ctx.gadt.fullBounds(sym)
if (bounds != null) sym.info = bounds
Expand Down Expand Up @@ -1969,8 +1969,9 @@ class Typer extends Namer
//val ptt = if (lo.isEmpty && hi.isEmpty) pt else
if (ctx.isAfterTyper) tree1
else {
val wildcardSym = newPatternBoundSymbol(tpnme.WILDCARD, tree1.tpe & pt, tree.span)
untpd.Bind(tpnme.WILDCARD, tree1).withType(wildcardSym.typeRef)
val boundName = WildcardParamName.fresh().toTypeName
val wildcardSym = newPatternBoundSymbol(boundName, tree1.tpe & pt, tree.span)
untpd.Bind(boundName, tree1).withType(wildcardSym.typeRef)
}
else tree1
}
Expand Down
2 changes: 1 addition & 1 deletion tests/neg-custom-args/kind-projector.check
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
-- Error: tests/neg-custom-args/kind-projector.scala:6:22 --------------------------------------------------------------
6 |class Bar2 extends Foo[*] // error
| ^
| Type argument _$4 does not have the same kind as its bound [_$1]
| Type argument _ does not have the same kind as its bound [_$1]
37 changes: 37 additions & 0 deletions tests/neg/i12169.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
object Var:
class Expanded[T <: Txn[T], B] extends Form[T]

trait Txn[T <: Txn[T]]

trait Form[T]

class TT extends Txn[TT]

private final class FlatVarCellView[T <: Txn[T], B](
firstVr : Option[Var.Expanded[TT, B]]
)

def Test =
val opt: Option[Form[TT]] = ???
val firstVr = opt match
case Some(ex: Var.Expanded[TT, _]) => Some(ex)
case _ => None
new FlatVarCellView(firstVr) // error
// Found: (firstVr : Option[Var.Expanded[TT, ?]])
// Required: Option[Var.Expanded[TT, B]]
//
// where: B is a type variable
//
// Note that we cannot do capture conversion since the `?` does not appear as an argument
// of the a type. It's dubious whether capture conversion for more deeply nested types
// would be sound.

// Remedy:
opt match
case Some(ex: Var.Expanded[TT, _]) => new FlatVarCellView(Some(ex))
// here, we instantiate `B` with the unnamed second parameter of `Var.Expanded`
case _ => new FlatVarCellView(None)
opt match
case Some(ex: Var.Expanded[TT, t]) => new FlatVarCellView[TT, t](Some(ex))
// the same as above, spelt out
case _ => new FlatVarCellView(None)
2 changes: 1 addition & 1 deletion tests/neg/i4986c.check
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@
-- Error: tests/neg/i4986c.scala:62:19 ---------------------------------------------------------------------------------
62 | i.m[Option[Long]] // error
| ^
| String; List; [A, _$6] =>> List[Option[?]]; Int; Option[Long];
| String; List; [A, _] =>> List[Option[?]]; Int; Option[Long];
13 changes: 13 additions & 0 deletions tests/pos/i12169.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Property[T]

class VObject {
def properties() = {
List.empty[Property[?]].collect {
case p: Property[?] => List(p)
}
}
}

class Event extends VObject {
override def properties() = ???
}