Skip to content

Commit 0341f7f

Browse files
committed
Also check well-formedness of method signatures
1 parent f5611e3 commit 0341f7f

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

compiler/src/dotty/tools/dotc/typer/CheckCaptures.scala

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,20 +96,21 @@ class CheckCaptures extends RefineTypes:
9696

9797
inline val disallowGlobal = true
9898

99+
def checkRelativeVariance(mt: MethodType, whole: Type, pos: SrcPos)(using Context) = new TypeTraverser:
100+
def traverse(tp: Type): Unit = tp match
101+
case CapturingType(parent, ref @ TermParamRef(`mt`, _)) =>
102+
if variance <= 0 then
103+
val direction = if variance < 0 then "contra" else "in"
104+
report.error(em"captured reference $ref appears ${direction}variantly in type $whole", pos)
105+
traverse(parent)
106+
case _ =>
107+
traverseChildren(tp)
108+
99109
def checkWellFormed(whole: Type, pos: SrcPos)(using Context): Unit =
100-
def checkRelativeVariance(mt: MethodType) = new TypeTraverser:
101-
def traverse(tp: Type): Unit = tp match
102-
case CapturingType(parent, ref @ TermParamRef(`mt`, _)) =>
103-
if variance <= 0 then
104-
val direction = if variance < 0 then "contra" else "in"
105-
report.error(em"captured reference $ref appears ${direction}variantly in type $whole", pos)
106-
traverse(parent)
107-
case _ =>
108-
traverseChildren(tp)
109110
val checkVariance = new TypeTraverser:
110111
def traverse(tp: Type): Unit = tp match
111112
case mt: MethodType if mt.isResultDependent =>
112-
checkRelativeVariance(mt).traverse(mt)
113+
checkRelativeVariance(mt, whole, pos).traverse(mt)
113114
case _ =>
114115
traverseChildren(tp)
115116
checkVariance.traverse(whole)
@@ -138,6 +139,16 @@ class CheckCaptures extends RefineTypes:
138139
// it's inferred, no need to check
139140
case tree: TypTree =>
140141
checkWellFormed(tree.tpe, tree.srcPos)
142+
case tree: DefDef =>
143+
def check(tp: Type): Unit = tp match
144+
case tp: PolyType =>
145+
check(tp.resType)
146+
case mt: MethodType =>
147+
if mt.isResultDependent then
148+
checkRelativeVariance(mt, tree.symbol.info, ctx.source.atSpan(tree.nameSpan)).traverse(mt)
149+
check(mt.resType)
150+
case _ =>
151+
check(tree.symbol.info)
141152
case _ =>
142153
traverseChildren(tree)
143154

tests/neg-custom-args/captures/capt-wf.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ type Top = Any retains *
55
type T = (x: Cap) => List[String retains x.type] => Unit // error
66
val x: (x: Cap) => Array[String retains x.type] = ??? // error
77
val y = x
8+
9+
def test: Unit =
10+
def f(x: Cap) = // error
11+
val g = (xs: List[String retains x.type]) => ()
12+
g
13+
()

0 commit comments

Comments
 (0)