Skip to content

Commit 5fba379

Browse files
authored
Merge pull request #510 from scala/backport-lts-3.3-23514
Backport "Fix this references everywhere in dependent function types" to 3.3 LTS
2 parents 6099915 + 16b756c commit 5fba379

File tree

3 files changed

+38
-23
lines changed

3 files changed

+38
-23
lines changed

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

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,11 +1451,11 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
14511451
else typedFunctionValue(tree, pt)
14521452

14531453
def typedFunctionType(tree: untpd.Function, pt: Type)(using Context): Tree = {
1454-
val untpd.Function(args, body) = tree
1455-
body match
1456-
case untpd.CapturesAndResult(refs, result) =>
1454+
val untpd.Function(args, result) = tree
1455+
result match
1456+
case untpd.CapturesAndResult(refs, result1) =>
14571457
return typedUnadapted(untpd.makeRetaining(
1458-
cpy.Function(tree)(args, result), refs, tpnme.retains), pt)
1458+
cpy.Function(tree)(args, result1), refs, tpnme.retains), pt)
14591459
case _ =>
14601460
var (funFlags, erasedParams) = tree match {
14611461
case tree: untpd.FunctionWithMods => (tree.mods.flags, tree.erasedParams)
@@ -1467,37 +1467,28 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
14671467
val isImpure = funFlags.is(Impure)
14681468

14691469
/** Typechecks dependent function type with given parameters `params` */
1470-
def typedDependent(params: List[untpd.ValDef])(using Context): Tree =
1471-
val fixThis = new untpd.UntypedTreeMap:
1472-
// pretype all references of this in outer context,
1473-
// so that they do not refer to the refined type being constructed
1474-
override def transform(tree: untpd.Tree)(using Context): untpd.Tree = tree match
1475-
case This(id) => untpd.TypedSplice(typedExpr(tree)(using ctx.outer))
1476-
case _ => super.transform(tree)
1477-
1470+
def typedDependent(params: List[untpd.ValDef], result: untpd.Tree)(using Context): Tree =
14781471
val params1 =
14791472
if funFlags.is(Given) then params.map(_.withAddedFlags(Given))
14801473
else params
1481-
val params2 = params1.map(fixThis.transformSub)
1482-
val params3 = params2.zipWithConserve(erasedParams) { (arg, isErased) =>
1474+
val params2 = params1.zipWithConserve(erasedParams): (arg, isErased) =>
14831475
if isErased then arg.withAddedFlags(Erased) else arg
1484-
}
1485-
val appDef0 = untpd.DefDef(nme.apply, List(params3), body, EmptyTree).withSpan(tree.span)
1476+
val appDef0 = untpd.DefDef(nme.apply, List(params2), result, EmptyTree).withSpan(tree.span)
14861477
index(appDef0 :: Nil)
14871478
val appDef = typed(appDef0).asInstanceOf[DefDef]
14881479
val mt = appDef.symbol.info.asInstanceOf[MethodType]
14891480
if (mt.isParamDependent)
14901481
report.error(em"$mt is an illegal function type because it has inter-parameter dependencies", tree.srcPos)
14911482
// Restart typechecking if there are erased classes that we want to mark erased
14921483
if mt.erasedParams.zip(mt.paramInfos.map(_.isErasedClass)).exists((paramErased, classErased) => classErased && !paramErased) then
1493-
val newParams = params3.zipWithConserve(mt.paramInfos.map(_.isErasedClass)) { (arg, isErasedClass) =>
1484+
val newParams = params2.zipWithConserve(mt.paramInfos.map(_.isErasedClass)) { (arg, isErasedClass) =>
14941485
if isErasedClass then arg.withAddedFlags(Erased) else arg
14951486
}
1496-
return typedDependent(newParams)
1487+
return typedDependent(newParams, result)
14971488
val core =
14981489
if mt.hasErasedParams then TypeTree(defn.ErasedFunctionClass.typeRef)
14991490
else
1500-
val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(body.span)
1491+
val resTpt = TypeTree(mt.nonDependentResultApprox).withSpan(result.span)
15011492
val paramTpts = appDef.termParamss.head.map(p => TypeTree(p.tpt.tpe).withSpan(p.tpt.span))
15021493
val funSym = defn.FunctionSymbol(numArgs, isContextual, isImpure)
15031494
val tycon = TypeTree(funSym.typeRef)
@@ -1507,19 +1498,28 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
15071498

15081499
args match {
15091500
case ValDef(_, _, _) :: _ =>
1510-
typedDependent(args.asInstanceOf[List[untpd.ValDef]])(
1501+
val fixThis = new untpd.UntypedTreeMap:
1502+
// pretype all references of this so that they do not refer to the
1503+
// refined type being constructed
1504+
override def transform(tree: untpd.Tree)(using Context): untpd.Tree = tree match
1505+
case This(id) => untpd.TypedSplice(typedExpr(tree))
1506+
case _ => super.transform(tree)
1507+
1508+
val untpd.Function(fixedArgs: List[untpd.ValDef] @unchecked, fixedResult) =
1509+
fixThis.transform(tree): @unchecked
1510+
typedDependent(fixedArgs, fixedResult)(
15111511
using ctx.fresh.setOwner(newRefinedClassSymbol(tree.span)).setNewScope)
15121512
case _ =>
15131513
if erasedParams.contains(true) then
15141514
typedFunctionType(desugar.makeFunctionWithValDefs(tree, pt), pt)
15151515
else
15161516
val funSym = defn.FunctionSymbol(numArgs, isContextual, isImpure)
1517-
val result = typed(cpy.AppliedTypeTree(tree)(untpd.TypeTree(funSym.typeRef), args :+ body), pt)
1517+
val funTpt = typed(cpy.AppliedTypeTree(tree)(untpd.TypeTree(funSym.typeRef), args :+ result), pt)
15181518
// if there are any erased classes, we need to re-do the typecheck.
1519-
result match
1519+
funTpt match
15201520
case r: AppliedTypeTree if r.args.exists(_.tpe.isErasedClass) =>
15211521
typedFunctionType(desugar.makeFunctionWithValDefs(tree, pt), pt)
1522-
case _ => result
1522+
case _ => funTpt
15231523
}
15241524
}
15251525

tests/neg/i23111.check

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- [E086] Syntax Error: tests/neg/i23111.scala:2:47 --------------------------------------------------------------------
2+
2 | def bar: (a: Int, b: Int) => A.this.type = x => ??? // error
3+
| ^^^^^^^^
4+
| Wrong number of parameters, expected: 2
5+
|
6+
| longer explanation available when compiling with `-explain`
7+
-- [E086] Syntax Error: tests/neg/i23111.scala:3:45 --------------------------------------------------------------------
8+
3 | def baz: (a: Int, b: Int) => this.type = x => ??? // error
9+
| ^^^^^^^^
10+
| Wrong number of parameters, expected: 2
11+
|
12+
| longer explanation available when compiling with `-explain`

tests/neg/i23111.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
trait A:
2+
def bar: (a: Int, b: Int) => A.this.type = x => ??? // error
3+
def baz: (a: Int, b: Int) => this.type = x => ??? // error

0 commit comments

Comments
 (0)