Skip to content

Commit a562c9b

Browse files
committed
Handle prefixes and dependent parameter types when ascribing types
1 parent b1371e5 commit a562c9b

File tree

2 files changed

+34
-14
lines changed

2 files changed

+34
-14
lines changed

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

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -446,13 +446,13 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
446446
* inline annotations from their parameters. The generated `def` is appended
447447
* to `bindingsBuf`.
448448
* @param name the name of the parameter
449-
* @param paramtp the type of the parameter
449+
* @param formal the type of the parameter
450450
* @param arg the argument corresponding to the parameter
451451
* @param bindingsBuf the buffer to which the definition should be appended
452452
*/
453-
private def paramBindingDef(name: Name, paramtp: Type, arg0: Tree,
453+
private def paramBindingDef(name: Name, formal: Type, arg0: Tree,
454454
bindingsBuf: mutable.ListBuffer[ValOrDefDef])(using Context): ValOrDefDef = {
455-
val isByName = paramtp.dealias.isInstanceOf[ExprType]
455+
val isByName = formal.dealias.isInstanceOf[ExprType]
456456
val arg = arg0 match {
457457
case Typed(arg1, tpt) if tpt.tpe.isRepeatedParam && arg1.tpe.derivesFrom(defn.ArrayClass) =>
458458
wrapArray(arg1, arg0.tpe.elemType)
@@ -461,19 +461,19 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
461461
val argtpe = arg.tpe.dealiasKeepAnnots.translateFromRepeated(toArray = false)
462462
val argIsBottom = argtpe.isBottomTypeAfterErasure
463463
val bindingType =
464-
if argIsBottom then paramtp
464+
if argIsBottom then formal
465465
else if isByName then ExprType(argtpe.widen)
466466
else argtpe.widen
467467
var bindingFlags: FlagSet = InlineProxy
468-
if paramtp.widenExpr.hasAnnotation(defn.InlineParamAnnot) then
468+
if formal.widenExpr.hasAnnotation(defn.InlineParamAnnot) then
469469
bindingFlags |= Inline
470470
if isByName then
471471
bindingFlags |= Method
472472
val boundSym = newSym(InlineBinderName.fresh(name.asTermName), bindingFlags, bindingType).asTerm
473473
val binding = {
474474
var newArg = arg.changeOwner(ctx.owner, boundSym)
475475
if bindingFlags.is(Inline) && argIsBottom then
476-
newArg = Typed(newArg, TypeTree(paramtp)) // type ascribe RHS to avoid type errors in expansion. See i8612.scala
476+
newArg = Typed(newArg, TypeTree(formal)) // type ascribe RHS to avoid type errors in expansion. See i8612.scala
477477
if isByName then DefDef(boundSym, newArg)
478478
else ValDef(boundSym, newArg)
479479
}.withSpan(boundSym.span)
@@ -487,30 +487,28 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
487487
* proxies to this-references. Issue an error if some arguments are missing.
488488
*/
489489
private def computeParamBindings(
490-
tp: Type, targs: List[Tree], argss: List[List[Tree]], paramSubst: Type => Type): Boolean =
490+
tp: Type, targs: List[Tree], argss: List[List[Tree]], formalss: List[List[Type]]): Boolean =
491491
tp match
492492
case tp: PolyType =>
493493
tp.paramNames.lazyZip(targs).foreach { (name, arg) =>
494494
paramSpan(name) = arg.span
495495
paramBinding(name) = arg.tpe.stripTypeVar
496496
}
497-
computeParamBindings(
498-
tp.resultType, targs.drop(tp.paramNames.length), argss,
499-
paramSubst.andThen(_.substParams(tp, targs.map(_.tpe.stripTypeVar))))
497+
computeParamBindings(tp.resultType, targs.drop(tp.paramNames.length), argss, formalss)
500498
case tp: MethodType =>
501499
if argss.isEmpty then
502500
report.error(i"missing arguments for inline method $inlinedMethod", call.srcPos)
503501
false
504502
else
505-
tp.paramNames.lazyZip(tp.paramInfos).lazyZip(argss.head).foreach { (name, paramtp, arg) =>
503+
tp.paramNames.lazyZip(formalss.head).lazyZip(argss.head).foreach { (name, formal, arg) =>
506504
paramSpan(name) = arg.span
507505
paramBinding(name) = arg.tpe.dealias match
508506
case _: SingletonType if isIdempotentPath(arg) =>
509507
arg.tpe
510508
case _ =>
511-
paramBindingDef(name, paramSubst(paramtp), arg, bindingsBuf).symbol.termRef
509+
paramBindingDef(name, formal, arg, bindingsBuf).symbol.termRef
512510
}
513-
computeParamBindings(tp.resultType, targs, argss.tail, paramSubst)
511+
computeParamBindings(tp.resultType, targs, argss.tail, formalss.tail)
514512
case _ =>
515513
assert(targs.isEmpty)
516514
assert(argss.isEmpty)
@@ -698,8 +696,16 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) {
698696
)
699697
}
700698

699+
def paramTypess(call: Tree, acc: List[List[Type]]): List[List[Type]] = call match
700+
case Apply(fn, args) =>
701+
fn.tpe.widen.match
702+
case mt: MethodType => paramTypess(fn, mt.instantiateParamInfos(args.tpes) :: acc)
703+
case _ => Nil
704+
case TypeApply(fn, _) => paramTypess(fn, acc)
705+
case _ => acc
706+
701707
// Compute bindings for all parameters, appending them to bindingsBuf
702-
if !computeParamBindings(inlinedMethod.info, callTypeArgs, callValueArgss, identity) then
708+
if !computeParamBindings(inlinedMethod.info, callTypeArgs, callValueArgss, paramTypess(call, Nil)) then
703709
return call
704710

705711
// make sure prefix is executed if it is impure

tests/pos/i11864.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ object test2:
1919
val y = bar[Int](???)
2020
y: Option[Int]
2121

22+
object test3:
23+
inline def bar(ev: Ev)(x: ev.Out): Option[ev.Out] = Some(x)
24+
val a: Ev { type Out = Int } = ???
25+
def test =
26+
val y = bar(a)(???)
27+
y: Option[Int]
28+
29+
object test4:
30+
inline def bar(ev: Ev, x: ev.Out): Option[ev.Out] = Some(x)
31+
val a: Ev { type Out = Int } = ???
32+
def test =
33+
val y = bar(a, ???)
34+
y: Option[Int]
35+
2236
final class CallbackTo[+A] {
2337
inline def map[B](f: A => B)(using erased ev: CallbackTo.MapGuard[B]): CallbackTo[ev.Out] = ???
2438
}

0 commit comments

Comments
 (0)