Skip to content
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/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ object Erasure {
case _: FunProto | AnyFunctionProto => tree
case _ => tree.tpe.widen match
case mt: MethodType if tree.isTerm =>
assert(mt.paramInfos.isEmpty)//, i"bad adapt for $tree: $mt")
assert(mt.paramInfos.isEmpty, i"bad adapt for $tree: $mt")
adaptToType(tree.appliedToNone, pt)
case tpw =>
if (pt.isInstanceOf[ProtoType] || tree.tpe <:< pt)
Expand Down
10 changes: 10 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1460,6 +1460,15 @@ trait Checking {
|CanThrow capabilities can only be generated $req.""",
pat.srcPos)

/** Check that tree does not define a context function type */
def checkNoContextFunctionType(tree: Tree)(using Context): Unit =
def recur(tp: Type): Unit = tp.dealias match
case tp: HKTypeLambda => recur(tp.resType)
case tp if defn.isContextFunctionType(tp) =>
report.error(em"context function type cannot have opaque aliases", tree.srcPos)
case _ =>
recur(tree.tpe)

/** (1) Check that every named import selector refers to a type or value member of the
* qualifier type.
* (2) Check that no import selector is renamed more than once.
Expand Down Expand Up @@ -1495,6 +1504,7 @@ trait ReChecking extends Checking {
override def checkNoModuleClash(sym: Symbol)(using Context) = ()
override def checkCanThrow(tp: Type, span: Span)(using Context): Tree = EmptyTree
override def checkCatch(pat: Tree, guard: Tree)(using Context): Unit = ()
override def checkNoContextFunctionType(tree: Tree)(using Context): Unit = ()
override def checkFeature(name: TermName, description: => String, featureUseSite: Symbol, pos: SrcPos)(using Context): Unit = ()
}

Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2417,6 +2417,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
case rhs =>
typedType(rhs)
checkFullyAppliedType(rhs1)
if sym.isOpaqueAlias then checkNoContextFunctionType(rhs1)
assignType(cpy.TypeDef(tdef)(name, rhs1), sym)
}

Expand Down
1 change: 1 addition & 0 deletions docs/_docs/reference/other-new-features/opaques-details.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def id(x: o.T): o.T = x
```

Opaque type aliases cannot be `private` and cannot be overridden in subclasses.
Opaque type aliases cannot have a context function type as right-hand side.

## Type Parameters of Opaque Types

Expand Down
12 changes: 12 additions & 0 deletions tests/neg/i16035.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
object Scope:
opaque type Uses[A, B] = A ?=> B // error
opaque type UsesAlt = [A, B] =>> A ?=> B // error

object Uses:
def apply[A, B](fn: A ?=> B): Uses[A, B] = fn

import Scope.*
val uses =
given Int = 1
Uses[Int, String](i ?=> s"*$i*")

14 changes: 14 additions & 0 deletions tests/neg/i16035a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
trait S:
type Uses[A, B] <: A ?=> B
object Uses:
def apply[A, B](fn: A ?=> B): Uses[A, B] = fn // error
val uses1 =
given Int = 1
Uses[Int, String](i ?=> s"*$i*")

object I extends S:
type Uses[A, B] = A ?=> B
val uses2 =
given Int = 1
Uses[Int, String](i ?=> s"*$i*")

11 changes: 11 additions & 0 deletions tests/pos/i16035.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
object Scope:
type Uses[A, B] = A ?=> B

object Uses:
def apply[A, B](fn: A ?=> B): Uses[A, B] = fn

import Scope.*
val uses =
given Int = 1
Uses[Int, String](i ?=> s"*$i*")