diff options
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 29 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/TypeAssigner.scala | 4 | ||||
-rw-r--r-- | tests/pos/t252.scala | 12 |
3 files changed, 34 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 947d46ee0..8fe47582b 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -423,7 +423,7 @@ class Namer { typer: Typer => private def typeSig(sym: Symbol): Type = original match { case original: ValDef => if (sym is Module) moduleValSig(sym) - else valOrDefDefSig(original, sym, Nil, identity)(localContext(sym).setNewScope) + else valOrDefDefSig(original, sym, Nil, Nil, identity)(localContext(sym).setNewScope) case original: DefDef => val typer1 = new Typer nestedTyper(sym) = typer1 @@ -572,7 +572,7 @@ class Namer { typer: Typer => * @param paramFn A wrapping function that produces the type of the * defined symbol, given its final return type */ - def valOrDefDefSig(mdef: ValOrDefDef, sym: Symbol, typeParams: List[Symbol], paramFn: Type => Type)(implicit ctx: Context): Type = { + def valOrDefDefSig(mdef: ValOrDefDef, sym: Symbol, typeParams: List[Symbol], paramss: List[List[Symbol]], paramFn: Type => Type)(implicit ctx: Context): Type = { def inferredType = { /** A type for this definition that might be inherited from elsewhere: @@ -660,14 +660,20 @@ class Namer { typer: Typer => case TypeTree(untpd.EmptyTree) => inferredType case TypedSplice(tpt: TypeTree) if !isFullyDefined(tpt.tpe, ForceDegree.none) => - typedAheadExpr(mdef.rhs, tpt.tpe) - typr.println(i"determine closure result type to be ${tpt.tpe}") + val rhsType = typedAheadExpr(mdef.rhs, tpt.tpe).tpe + mdef match { + case mdef: DefDef if mdef.name == nme.ANON_FUN => + val hygienicType = avoid(rhsType, paramss.flatten) + hygienicType <:< tpt.tpe + typr.println(i"lifting $rhsType over $paramss -> $hygienicType = ${tpt.tpe}") + case _ => + } WildcardType case _ => WildcardType } paramFn(typedAheadType(mdef.tpt, tptProto).tpe) - } + } /** The type signature of a DefDef with given symbol */ def defDefSig(ddef: DefDef, sym: Symbol)(implicit ctx: Context) = { @@ -676,12 +682,13 @@ class Namer { typer: Typer => vparamss foreach completeParams val isConstructor = name == nme.CONSTRUCTOR def typeParams = tparams map symbolOfTree + val paramSymss = { + val pss = vparamss.nestedMap(symbolOfTree) + if (isConstructor && // Make sure constructor has one non-implicit parameter list + (pss.isEmpty || pss.head.nonEmpty && (pss.head.head is Implicit))) Nil :: pss + else pss + } def wrapMethType(restpe: Type): Type = { - var paramSymss = vparamss.nestedMap(symbolOfTree) - // Make sure constructor has one non-implicit parameter list - if (isConstructor && - (paramSymss.isEmpty || paramSymss.head.nonEmpty && (paramSymss.head.head is Implicit))) - paramSymss = Nil :: paramSymss val restpe1 = // try to make anonymous functions non-dependent, so that they can be used in closures if (name == nme.ANON_FUN) avoid(restpe, paramSymss.flatten) else restpe @@ -692,7 +699,7 @@ class Namer { typer: Typer => typedAheadType(ddef.tpt, defn.UnitType) wrapMethType(ctx.effectiveResultType(sym, typeParams, NoType)) } - else valOrDefDefSig(ddef, sym, typeParams, wrapMethType) + else valOrDefDefSig(ddef, sym, typeParams, paramSymss, wrapMethType) } def typeDefSig(tdef: TypeDef, sym: Symbol)(implicit ctx: Context): Type = { diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala index 84198b954..4370c36d2 100644 --- a/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -87,6 +87,10 @@ trait TypeAssigner { parent1 } else tp1 + case tp: TypeVar if ctx.typerState.constraint.contains(tp) => + val lo = ctx.typerState.constraint.fullLowerBound(tp.origin) + val lo1 = avoid(lo, syms) + if (lo1 ne lo) lo1 else tp case _ => mapOver(tp) } diff --git a/tests/pos/t252.scala b/tests/pos/t252.scala index d51b5511e..ac4e97106 100644 --- a/tests/pos/t252.scala +++ b/tests/pos/t252.scala @@ -11,6 +11,18 @@ abstract class Base { } abstract class Derived extends Base { + + val t: T = ??? + + // trying a simple dependent closure body first + def cont1[X, Y](x: X)(f: X => Y): Y = f(x) + cont1(t)(x => x.module) + + // trying an indirectly dependent closure body first + def cont2[X, Y](x: X)(f: X => Int => Y): Y = f(x)(1) + cont2(t)(x => z => x.module) + + // trying the original, harder case next def f(inputs: List[tType]): Unit = { for (t <- inputs; m = t.module) { } } |