diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index b56b2d56f875..41db7d88ffdd 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -4417,6 +4417,8 @@ object Types { private final class RecThisImpl(binder: RecType) extends RecThis(binder) + // @sharable private var skid: Int = 0 + // ----- Skolem types ----------------------------------------------- /** A skolem type reference with underlying type `info`. @@ -4434,6 +4436,10 @@ object Types { def withName(name: Name): this.type = { myRepr = name; this } + //skid += 1 + //val id = skid + //assert(id != 10) + private var myRepr: Name = null def repr(using Context): Name = { if (myRepr == null) myRepr = SkolemName.fresh() diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index cc1012993bd6..6f65d81c1635 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -601,24 +601,20 @@ trait Inferencing { this: Typer => def constraint = state.constraint type InstantiateQueue = mutable.ListBuffer[(TypeVar, Boolean)] val toInstantiate = new InstantiateQueue - for (tvar <- qualifying) - if (!tvar.isInstantiated && constraint.contains(tvar)) { + for tvar <- qualifying do + if !tvar.isInstantiated && constraint.contains(tvar) then constrainIfDependentParamRef(tvar, tree) - // Needs to be checked again, since previous interpolations could already have // instantiated `tvar` through unification. val v = vs(tvar) - if (v == null) { + if v == null then typr.println(i"interpolate non-occurring $tvar in $state in $tree: $tp, fromBelow = ${tvar.hasLowerBound}, $constraint") toInstantiate += ((tvar, tvar.hasLowerBound)) - } + else if v.intValue != 0 then + typr.println(i"interpolate $tvar in $state in $tree: $tp, fromBelow = ${v.intValue == 1}, $constraint") + toInstantiate += ((tvar, v.intValue == 1)) else - if (v.intValue != 0) { - typr.println(i"interpolate $tvar in $state in $tree: $tp, fromBelow = ${v.intValue == 1}, $constraint") - toInstantiate += ((tvar, v.intValue == 1)) - } - else typr.println(i"no interpolation for nonvariant $tvar in $state") - } + typr.println(i"no interpolation for nonvariant $tvar in $state") /** Instantiate all type variables in `buf` in the indicated directions. * If a type variable A is instantiated from below, and there is another @@ -694,7 +690,7 @@ trait Inferencing { this: Typer => val arg = findArg(call) if !arg.isEmpty then - var argType = arg.tpe.widenExpr.widenTermRefExpr + var argType = arg.tpe.widenIfUnstable if !argType.isSingleton then argType = SkolemType(argType) argType <:< tvar case _ => diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala index 8ed463d2eea9..f7e33bd4a5f7 100644 --- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala +++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala @@ -348,7 +348,17 @@ trait TypeAssigner { } } else { - val argTypes = args.tpes + // Make sure arguments don't contain the type `pt` itself. + // make a copy of the argument if that's the case. + // This is done to compensate for the fact that normally every + // reference to a polytype would have to be a fresh copy of that type, + // but we want to avoid that because it would increase compilation cost. + // See pos/i6682a.scala for a test case where the defensive copying matters. + val ensureFresh = new TypeMap: + def apply(tp: Type) = mapOver( + if tp eq pt then pt.newLikeThis(pt.paramNames, pt.paramInfos, pt.resType) + else tp) + val argTypes = args.tpes.mapConserve(ensureFresh) if (sameLength(argTypes, paramNames)) pt.instantiate(argTypes) else wrongNumberOfTypeArgs(fn.tpe, pt.typeParams, args, tree.srcPos) } diff --git a/tests/pos/i12803.scala b/tests/pos/i12803.scala new file mode 100644 index 000000000000..2b370c70fca6 --- /dev/null +++ b/tests/pos/i12803.scala @@ -0,0 +1,12 @@ +trait X { + type Y +} + +trait E[A] + +trait Test { + val x: X + def wrap(x: X): E[x.Y] = ??? + def run[I](i: E[I]): Unit = ??? + run(wrap(x)) +}