diff --git a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala index 9caa97158d..149ac49254 100644 --- a/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala +++ b/compiler/shared/main/scala/mlscript/compiler/ClassLifter.scala @@ -747,7 +747,7 @@ class ClassLifter(logDebugMsg: Boolean = false) { val nTerms = termList.map(liftTerm(_)(using emptyCtx, nCache, globFuncs, nOuter)).unzip clsList.foreach(x => liftTypeDef(x)(using nCache, globFuncs, nOuter)) retSeq = retSeq.appended(NuTypeDef( - kind, nName, nTps.map((None, _)), kind match + kind, nName, nTps.map((TypeParamInfo(None, false, N, N), _)), kind match case Mod => None case _ => S(Tup(nParams)) , None, None, nPars._1, None, None, TypingUnit(nFuncs._1 ++ nTerms._1))(None, None, Nil)) diff --git a/shared/src/main/scala/mlscript/ConstraintSolver.scala b/shared/src/main/scala/mlscript/ConstraintSolver.scala index 54b7e91210..10a40e71c7 100644 --- a/shared/src/main/scala/mlscript/ConstraintSolver.scala +++ b/shared/src/main/scala/mlscript/ConstraintSolver.scala @@ -29,12 +29,9 @@ class ConstraintSolver extends NormalForms { self: Typer => ErrorReport( msg"${info.decl.kind.str.capitalize} `${info.decl.name}` does not contain member `${fld.name}`" -> fld.toLoc :: Nil, newDefs) - def lookupMember(clsNme: Str, rfnt: Var => Opt[FieldType], fld: Var) - (implicit ctx: Ctx, raise: Raise) + def lookupMember(clsNme: Str, rfnt: Var => Opt[FieldType], fld: Var)(implicit ctx: Ctx, raise: Raise) : Either[Diagnostic, NuMember] - = { - val info = ctx.tyDefs2.getOrElse(clsNme, ???/*TODO*/) - + = ctx.tyDefs2.get(clsNme).toRight(ErrorReport(msg"Cannot find class ${clsNme}" -> N :: Nil, newDefs)) flatMap { info => if (info.isComputing) { ??? // TODO support? @@ -109,7 +106,7 @@ class ConstraintSolver extends NormalForms { self: Typer => Nil) S(p.ty) case S(m) => - S(err(msg"Access to ${m.kind.str} member not yet supported", fld.toLoc).toUpper(noProv)) + S(err(msg"Access to ${m.kind.str} member ${fld.name} not yet supported", fld.toLoc).toUpper(noProv)) case N => N } @@ -131,17 +128,20 @@ class ConstraintSolver extends NormalForms { self: Typer => implicit val shadows: Shadows = Shadows.empty info.tparams.foreach { case (tn, _tv, vi) => - val targ = rfnt(Var(info.decl.name + "#" + tn.name)) match { + val targ = rfnt(tparamField(TypeName(info.decl.name), tn, vi.visible)) match { // * TODO to avoid infinite recursion due to ever-expanding type args, // * we should set the shadows of the targ to be the same as that of the parameter it replaces... - case S(fty) if vi === S(VarianceInfo.co) => fty.ub - case S(fty) if vi === S(VarianceInfo.contra) => fty.lb.getOrElse(BotType) + case S(fty) if vi.varinfo === S(VarianceInfo.co) => + println(s"Lookup: Found $fty") + fty.ub + case S(fty) if vi.varinfo === S(VarianceInfo.contra) => + println(s"Lookup: Found $fty") + fty.lb.getOrElse(BotType) case S(fty) => - TypeBounds.mk( - fty.lb.getOrElse(BotType), - fty.ub, - ) + println(s"Lookup: Found $fty") + TypeBounds.mk(fty.lb.getOrElse(BotType), fty.ub) case N => + println(s"Lookup: field not found, creating new bounds") TypeBounds( // _tv.lowerBounds.foldLeft(BotType: ST)(_ | _), // _tv.upperBounds.foldLeft(TopType: ST)(_ & _), @@ -192,6 +192,9 @@ class ConstraintSolver extends NormalForms { self: Typer => }() + private val DummyTV: TV = freshVar(noProv, N, S(""), Nil, Nil, false)(-1) + + // * Each type has a shadow which identifies all variables created from copying // * variables that existed at the start of constraining. // * The intent is to make the total number of shadows in a given constraint @@ -337,6 +340,25 @@ class ConstraintSolver extends NormalForms { self: Typer => lhsCons.foreach(c => rec(c._1, c._2, false)) }() + // * finish when a type appears at both sides + lazy val both = lhsCs.exists(s => s.lnf match { + case LhsTop => false + case LhsRefined(lbs, ltt, lr, ltr) => + rhs.cs.exists(c => c.lnf match { + case LhsTop => false + case LhsRefined(rbs, rtt, rr, rtr) => + // println(ltt,rtt) + // println(ltt.headOption,rtt.headOption,ltt.headOption.map(x=>rtt.headOption.map(y=>x==y)),ltt.headOption.map(x=>rtt.headOption.map(y=>y==x))) + // println(ltt.headOption,rtt.headOption,ltt.headOption.map(x=>rtt.headOption.map(y=>x compare y)),ltt.headOption.map(x=>rtt.headOption.map(y=>y compare x))) + // println(ltt&rtt) + ltt.exists(rtt.contains) + }) + }) + + if (newDefs && both /* && false */) { + println("DNF finished with same type at both sides") + } else + // * Same remark as in the `rec` method [note:1] // assert(lvl >= rhs.level) @@ -344,10 +366,14 @@ class ConstraintSolver extends NormalForms { self: Typer => def local(): Unit = { // * Used to return early in simple cases - vars.headOption match { + vars.maxByOption(_.level) match { + // case S(v) if v.level >= (rhs.level max _lhs.level) => + // rec(v, rhs.toType() | Conjunct(lnf, vars - v, rnf, nvars).toType().neg(), true) case S(v) => + // TODO rec(v, rhs.toType() | Conjunct(lnf, vars - v, rnf, nvars).toType().neg(), true) - case N => + // case N => + case _ => implicit val etf: ExpandTupleFields = true val fullRhs = nvars.iterator.map(DNF.mkDeep(MaxLevel, Nil, _, true)) .foldLeft(rhs | DNF.mkDeep(MaxLevel, Nil, rnf.toType(), false))(_ | _) @@ -398,12 +424,12 @@ class ConstraintSolver extends NormalForms { self: Typer => println(s"Factorized: " + fact) // Finally, we enter the "annoying constraint" resolution routine: - annoying(Nil, lnf, fact, RhsBot) + annoying(Nil, Nil, lnf, fact, Nil, RhsBot) } else { // Alternatively, without factorization (does not actually make a difference most of the time): - annoying(Nil, lnf, possible.map(_.toType()), RhsBot) + annoying(Nil, Nil, lnf, possible.map(_.toType()), Nil, RhsBot) } @@ -420,62 +446,66 @@ class ConstraintSolver extends NormalForms { self: Typer => which are those that involve either unions and intersections at the wrong polarities or negations. This works by constructing all pairs of "conjunct <: disjunct" implied by the conceptual "DNF <: CNF" form of the constraint. */ - def annoying(ls: Ls[SimpleType], done_ls: LhsNf, rs: Ls[SimpleType], done_rs: RhsNf) + def annoying(ls: Ls[ST], vars_ls: Ls[TV], done_ls: LhsNf, rs: Ls[ST], vars_rs: Ls[TV], done_rs: RhsNf) (implicit cctx: ConCtx, prevCctxs: Ls[ConCtx], shadows: Shadows, ctx: Ctx, dbgHelp: Str = "Case") : Unit = { annoyingCalls += 1 consumeFuel() - annoyingImpl(ls, done_ls, rs, done_rs) + annoyingImpl(ls, vars_ls, done_ls, rs, done_rs, vars_rs) } // TODO improve by moving things to the right side *before* branching out in the search! - def annoyingImpl(ls: Ls[SimpleType], done_ls: LhsNf, rs: Ls[SimpleType], done_rs: RhsNf) + def annoyingImpl(ls: Ls[ST], vars_ls: Ls[TV], done_ls: LhsNf, rs: Ls[ST], done_rs: RhsNf, vars_rs: Ls[TV]) (implicit cctx: ConCtx, prevCctxs: Ls[ConCtx], ctx: Ctx, shadows: Shadows, dbgHelp: Str = "Case") : Unit = trace(s"${lvl}. A $done_ls % $ls rec(tv, mkRhs(ls), done_ls.isTop && ls.forall(_.isTop)) - case (_, (tv: TypeVariable) :: rs) => rec(mkLhs(rs), tv, done_rs.isBot && rs.forall(_.isBot)) - case (TypeBounds(lb, ub) :: ls, _) => annoying(ub :: ls, done_ls, rs, done_rs) - case (_, TypeBounds(lb, ub) :: rs) => annoying(ls, done_ls, lb :: rs, done_rs) + // case ((tv: TypeVariable) :: ls, _) => rec(tv, mkRhs(ls), done_ls.isTop && ls.forall(_.isTop)) + // case (_, (tv: TypeVariable) :: rs) => rec(mkLhs(rs), tv, done_rs.isBot && rs.forall(_.isBot)) + case ((tv: TypeVariable) :: ls, _) => annoying(ls, tv :: vars_ls, done_ls, rs, vars_rs, done_rs) + case (_, (tv: TypeVariable) :: rs) => annoying(ls, vars_ls, done_ls, rs, tv :: vars_rs, done_rs) + + case (TypeBounds(lb, ub) :: ls, _) => annoying(ub :: ls, vars_ls, done_ls, rs, vars_rs, done_rs) + case (_, TypeBounds(lb, ub) :: rs) => annoying(ls, vars_ls, done_ls, lb :: rs, vars_rs, done_rs) case (ComposedType(true, ll, lr) :: ls, _) => - mkCase("1"){ implicit dbgHelp => annoying(ll :: ls, done_ls, rs, done_rs) } - mkCase("2"){ implicit dbgHelp => annoying(lr :: ls, done_ls, rs, done_rs) } + mkCase("1"){ implicit dbgHelp => annoying(ll :: ls, vars_ls, done_ls, rs, vars_rs, done_rs) } + mkCase("2"){ implicit dbgHelp => annoying(lr :: ls, vars_ls, done_ls, rs, vars_rs, done_rs) } case (_, ComposedType(false, rl, rr) :: rs) => - mkCase("1"){ implicit dbgHelp => annoying(ls, done_ls, rl :: rs, done_rs) } - mkCase("2"){ implicit dbgHelp => annoying(ls, done_ls, rr :: rs, done_rs) } + mkCase("1"){ implicit dbgHelp => annoying(ls, vars_ls, done_ls, rl :: rs, vars_rs, done_rs) } + mkCase("2"){ implicit dbgHelp => annoying(ls, vars_ls, done_ls, rr :: rs, vars_rs, done_rs) } case (_, ComposedType(true, rl, rr) :: rs) => - annoying(ls, done_ls, rl :: rr :: rs, done_rs) + annoying(ls, vars_ls, done_ls, rl :: rr :: rs, vars_rs, done_rs) case (ComposedType(false, ll, lr) :: ls, _) => - annoying(ll :: lr :: ls, done_ls, rs, done_rs) - case (p @ ProxyType(und) :: ls, _) => annoying(und :: ls, done_ls, rs, done_rs) - case (_, p @ ProxyType(und) :: rs) => annoying(ls, done_ls, und :: rs, done_rs) + annoying(ll :: lr :: ls, vars_ls, done_ls, rs, vars_rs, done_rs) + case (p @ ProxyType(und) :: ls, _) => annoying(und :: ls, vars_ls, done_ls, rs, vars_rs, done_rs) + case (_, p @ ProxyType(und) :: rs) => annoying(ls, vars_ls, done_ls, und :: rs, vars_rs, done_rs) // ^ TODO retain the proxy provs wrapping each ConstructedType... for better errors later on? - case (n @ NegType(ty) :: ls, _) => annoying(ls, done_ls, ty :: rs, done_rs) - case (_, n @ NegType(ty) :: rs) => annoying(ty :: ls, done_ls, rs, done_rs) + case (n @ NegType(ty) :: ls, _) => annoying(ls, vars_ls, done_ls, ty :: rs, vars_rs, done_rs) + case (_, n @ NegType(ty) :: rs) => annoying(ty :: ls, vars_ls, done_ls, rs, vars_rs, done_rs) case (ExtrType(true) :: ls, rs) => () // Bot in the LHS intersection makes the constraint trivial case (ls, ExtrType(false) :: rs) => () // Top in the RHS union makes the constraint trivial - case (ExtrType(false) :: ls, rs) => annoying(ls, done_ls, rs, done_rs) - case (ls, ExtrType(true) :: rs) => annoying(ls, done_ls, rs, done_rs) + case (ExtrType(false) :: ls, rs) => annoying(ls, vars_ls, done_ls, rs, vars_rs, done_rs) + case (ls, ExtrType(true) :: rs) => annoying(ls, vars_ls, done_ls, rs, vars_rs, done_rs) // case ((tr @ TypeRef(_, _)) :: ls, rs) => annoying(tr.expand :: ls, done_ls, rs, done_rs) - case ((tr @ TypeRef(_, _)) :: ls, rs) => annoying(ls, (done_ls & (tr, pol = true)) getOrElse - (return println(s"OK $done_ls & $tr =:= ${BotType}")), rs, done_rs) + case ((tr @ TypeRef(_, _)) :: ls, rs) => annoying(ls, vars_ls, (done_ls & (tr, pol = true)) getOrElse + (return println(s"OK $done_ls & $tr =:= ${BotType}")), rs, vars_rs, done_rs) // case (ls, (tr @ TypeRef(_, _)) :: rs) => annoying(ls, done_ls, tr.expand :: rs, done_rs) - case (ls, (tr @ TypeRef(_, _)) :: rs) => annoying(ls, done_ls, rs, done_rs | (tr, pol = false) getOrElse + case (ls, (tr @ TypeRef(_, _)) :: rs) => annoying(ls, vars_ls, done_ls, rs, vars_rs, done_rs | (tr, pol = false) getOrElse (return println(s"OK $done_rs & $tr =:= ${TopType}"))) /* @@ -489,22 +519,45 @@ class ConstraintSolver extends NormalForms { self: Typer => lastWords(s"unexpected Without in negative position not at the top level: ${w}") */ - case ((l: BaseTypeOrTag) :: ls, rs) => annoying(ls, (done_ls & (l, pol = true))(ctx, etf = true) getOrElse - (return println(s"OK $done_ls & $l =:= ${BotType}")), rs, done_rs) - case (ls, (r: BaseTypeOrTag) :: rs) => annoying(ls, done_ls, rs, done_rs | r getOrElse + case ((l: BaseTypeOrTag) :: ls, rs) => annoying(ls, vars_ls, (done_ls & (l, pol = true))(ctx, etf = true) getOrElse + (return println(s"OK $done_ls & $l =:= ${BotType}")), rs, vars_rs, done_rs) + case (ls, (r: BaseTypeOrTag) :: rs) => annoying(ls, vars_ls, done_ls, rs, vars_rs, done_rs | r getOrElse (return println(s"OK $done_rs | $r =:= ${TopType}"))) - case ((l: RecordType) :: ls, rs) => annoying(ls, done_ls & l, rs, done_rs) + case ((l: RecordType) :: ls, rs) => annoying(ls, vars_ls, done_ls & l, rs, vars_rs, done_rs) case (ls, (r @ RecordType(Nil)) :: rs) => () - case (ls, (r @ RecordType(f :: Nil)) :: rs) => annoying(ls, done_ls, rs, done_rs | f getOrElse + case (ls, (r @ RecordType(f :: Nil)) :: rs) => annoying(ls, vars_ls, done_ls, rs, vars_rs, done_rs | f getOrElse (return println(s"OK $done_rs | $f =:= ${TopType}"))) - case (ls, (r @ RecordType(fs)) :: rs) => annoying(ls, done_ls, r.toInter :: rs, done_rs) + case (ls, (r @ RecordType(fs)) :: rs) => annoying(ls, vars_ls, done_ls, r.toInter :: rs, vars_rs, done_rs) // TODO statically prevent these cases by refining `annoyingImpl`'s parameter types case (_, (_: PolymorphicType) :: _) | ((_: PolymorphicType) :: _, _) => die case (_, (_: ConstrainedType) :: _) | ((_: ConstrainedType) :: _, _) => die case (Nil, Nil) => + + def mkRhs(ls: Ls[ST], tv: TV): ST = { + def tys = (vars_ls.iterator.filterNot(_ is tv) ++ done_ls.toTypes).map(_.neg()) ++ + vars_rs.iterator ++ done_rs.toTypes + tys.reduceOption(_ | _).getOrElse(BotType) + } + def mkLhs(rs: Ls[ST], tv: TV): ST = { + def tys = vars_ls.iterator ++ done_ls.toTypes ++ + (vars_rs.iterator.filterNot(_ is tv) ++ done_rs.toTypes).map(_.neg()) + tys.reduceOption(_ & _).getOrElse(TopType) + } + + (vars_ls.maxByOption(_.level), vars_rs.maxByOption(_.level)) match { + case (S(tv1), S(tv2)) => + if (tv1.level <= tv2.level) + return rec(tv1, mkRhs(ls, tv1), done_ls.isTop && ls.forall(_.isTop)) + else + return rec(mkLhs(rs, tv2), tv2, done_rs.isBot && rs.forall(_.isBot)) + case (S(tv), N) => return rec(tv, mkRhs(ls, tv), done_ls.isTop && ls.forall(_.isTop)) + case (N, S(tv)) => return rec(mkLhs(rs, tv), tv, done_rs.isBot && rs.forall(_.isBot)) + case (N, N) => + } + // TODO improve: // Most of the `rec` calls below will yield ugly errors because we don't maintain // the original constraining context! @@ -516,14 +569,16 @@ class ConstraintSolver extends NormalForms { self: Typer => case (LhsRefined(_, ts, _, trs), RhsBases(pts, _, _)) if ts.exists(pts.contains) => () case (LhsRefined(bo, ts, r, trs), _) if trs.nonEmpty => - annoying(trs.valuesIterator.map { tr => tr.expand }.toList, - LhsRefined(bo, ts, r, SortedMap.empty), Nil, done_rs) + annoying(trs.valuesIterator.map { tr => tr.expand(true) }.toList, Nil, + LhsRefined(bo, ts, r, SortedMap.empty), Nil, Nil, done_rs) case (_, RhsBases(pts, bf, trs)) if trs.nonEmpty => - annoying(Nil, done_ls, trs.valuesIterator.map(_.expand).toList, RhsBases(pts, bf, SortedMap.empty)) + annoying(Nil, Nil, done_ls, + trs.valuesIterator.map(_.expand(false)).toList, + Nil, RhsBases(pts, bf, SortedMap.empty)) case (_, RhsBases(pts, S(L(ov: Overload)), trs)) => - ov.alts.foreach(alt => annoying(Nil, done_ls, Nil, RhsBases(pts, S(L(alt)), trs))) + ov.alts.foreach(alt => annoying(Nil, Nil, done_ls, Nil, Nil, RhsBases(pts, S(L(alt)), trs))) // From this point on, trs should be empty! case (LhsRefined(_, _, _, trs), _) if trs.nonEmpty => die @@ -536,7 +591,7 @@ class ConstraintSolver extends NormalForms { self: Typer => , RhsBases(_, S(L(f1@FunctionType(l1, r1))), _)) => rec(f0, f1, true) case (LhsRefined(S(f: FunctionType), ts, r, trs), RhsBases(pts, _, _)) => - annoying(Nil, LhsRefined(N, ts, r, trs), Nil, done_rs) + annoying(Nil, Nil, LhsRefined(N, ts, r, trs), Nil, Nil, done_rs) // * Note: We could avoid the need for this rule by adding `Eql` to *all* class tag parent sets, // * but I chose not to for performance reasons (better keep parent sets small). @@ -585,10 +640,10 @@ class ConstraintSolver extends NormalForms { self: Typer => if (pts.exists(p => (p.id === pt.id) || l.allTags.contains(p.id))) println(s"OK $pt <: ${pts.mkString(" | ")}") // else f.fold(reportError())(f => annoying(Nil, done_ls, Nil, f)) - else annoying(Nil, LhsRefined(N, ts, r, trs), Nil, RhsBases(Nil, bf, trs2)) + else annoying(Nil, Nil, LhsRefined(N, ts, r, trs), Nil, Nil, RhsBases(Nil, bf, trs2)) case (lr @ LhsRefined(bo, ts, r, _), rf @ RhsField(n, t2)) => // Reuse the case implemented below: (this shortcut adds a few more annoying calls in stats) - annoying(Nil, lr, Nil, RhsBases(Nil, S(R(rf)), SortedMap.empty)) + annoying(Nil, Nil, lr, Nil, Nil, RhsBases(Nil, S(R(rf)), SortedMap.empty)) case (LhsRefined(N, ts, r, _), RhsBases(ots, S(R(RhsField(fldNme, fldTy))), trs)) if newDefs => val fty = lookupField(() => done_ls.toType(sort = true), N, r.fields.toMap.get, ts, fldNme) rec(fty.ub, fldTy.ub, false) @@ -628,14 +683,14 @@ class ConstraintSolver extends NormalForms { self: Typer => rec(b.inner.ub, ar.inner.ub, false) case (LhsRefined(S(b: ArrayBase), ts, r, _), _) => reportError() case (LhsRefined(S(ov: Overload), ts, r, trs), _) => - annoying(Nil, LhsRefined(S(ov.approximatePos), ts, r, trs), Nil, done_rs) // TODO remove approx. with ambiguous constraints + annoying(Nil, Nil, LhsRefined(S(ov.approximatePos), ts, r, trs), Nil, Nil, done_rs) // TODO remove approx. with ambiguous constraints case (LhsRefined(S(Without(b, ns)), ts, r, _), RhsBases(pts, N | S(L(_)), _)) => rec(b, done_rs.toType(), true) case (_, RhsBases(pts, S(L(Without(base, ns))), _)) => // rec((pts.map(_.neg()).foldLeft(done_ls.toType())(_ & _)).without(ns), base) // ^ This less efficient version creates a slightly different error message // (see test in Annoying.mls) - annoying(pts.map(_.neg()), done_ls, base :: Nil, RhsBot) + annoying(pts.map(_.neg()), Nil, done_ls, base :: Nil, Nil, RhsBot) } } @@ -669,7 +724,11 @@ class ConstraintSolver extends NormalForms { self: Typer => : SimpleType = { val originalVars = ty.getVars - val res = extrude(ty, lowerLvl, pol, upperLvl)(ctx, MutMap.empty, MutSortMap.empty, reason) + + // * FIXME ctx.extrCache and ctx.extrCache2 should be indexed by the level of the extrusion! + // TODO somehow handle extrCache2 + val res = extrude(ty, lowerLvl, pol, upperLvl)(ctx, MutSortMap.empty, reason) + val newVars = res.getVars -- originalVars if (newVars.nonEmpty) trace(s"RECONSTRAINING TVs") { newVars.foreach { @@ -725,6 +784,104 @@ class ConstraintSolver extends NormalForms { self: Typer => trace(s"$lvl. C $lhs allComponents(l :: r :: ls, rs, done_ls, done_rs) + case NegType(st) :: ls => allComponents(ls, st :: rs, done_ls, done_rs) + case ProvType(st) :: ls => allComponents(st :: ls, rs, done_ls, done_rs) + case (tv: TV) :: ls if tv is startTV => allComponents(ls, rs, done_ls, done_rs) + case (tv: TV) :: ls if tv.level > maxTv.level => + val oldTv = maxTv + val wasLeft = isLeft + maxTv = tv + isLeft = true + // if (oldTv is DummyTV) allComponents(ls, rs, done_ls, done_rs) + if (wasLeft) allComponents(ls, rs, oldTv :: done_ls, done_rs) + else allComponents(ls, rs, done_ls, oldTv :: done_rs) + case st :: ls => allComponents(ls, rs, st :: done_ls, done_rs) + case Nil => rs match { + case ComposedType(true, l, r) :: rs => allComponents(ls, l :: r :: rs, done_ls, done_rs) + case NegType(st) :: rs => allComponents(st :: ls, rs, done_ls, done_rs) + case ProvType(st) :: rs => allComponents(ls, st :: rs, done_ls, done_rs) + case (tv: TV) :: rs if tv is startTV => allComponents(ls, rs, done_ls, done_rs) + case (tv: TV) :: rs if tv.level > maxTv.level => + val oldTv = maxTv + val wasLeft = isLeft + maxTv = tv + isLeft = false + // if (oldTv is DummyTV) allComponents(ls, rs, done_ls, done_rs) + if (wasLeft) allComponents(ls, rs, oldTv :: done_ls, done_rs) + else allComponents(ls, rs, done_ls, oldTv :: done_rs) + case r :: rs => allComponents(Nil, rs, done_ls, r :: done_rs) + case Nil => (done_ls, done_rs) + } + } + val (ls, rs) = allComponents(lhs :: Nil, rhs :: Nil, Nil, Nil) + // if (maxTv isnt DummyTV) + // if (isLeft) rec(maxTv, (ls.iterator.map(_.neg()) ++ rs).reduce(_ | _), true) + // else rec((ls.iterator ++ rs.iterator.map(_.neg())).reduce(_ & _), maxTv, true) + + // System.out.println(s"Components: $ls << $rs") + + + + /* + if (maxTv is startTV) (maxTv, if (startLeft) rhs else lhs) + else if (isLeft) (maxTv, (ls.iterator.map(_.neg()) ++ rs).reduce(_ | _)) + else (maxTv, (ls.iterator ++ rs.iterator.map(_.neg())).reduce(_ & _)) + */ + + if (isLeft) { + val rhs = (ls.iterator.map(_.neg()) ++ rs).reduce(_ | _) // TODO optimize + if (rhs.level > maxTv.level) { + println(s"wrong level: ${rhs.level}") + if (constrainedTypes && rhs.level <= lvl) { + println(s"STASHING $maxTv bound in extr ctx") + val buf = ctx.extrCtx.getOrElseUpdate(maxTv, Buffer.empty) + buf += false -> rhs + cache -= lhs -> rhs + () + } else { + val rhs2 = extrudeAndCheck(rhs, lhs.level, false, MaxLevel, + cctx._1 :: prevCctxs.unzip._1 ::: prevCctxs.unzip._2) + println(s"EXTR RHS ~> $rhs2 to ${lhs.level}") + println(s" where ${rhs2.showBounds}") + // println(s" and ${rhs.showBounds}") + rec(lhs, rhs2, true) + } + } else rec(maxTv, rhs, true) + } else { + val lhs = (ls.iterator ++ rs.iterator.map(_.neg())).reduce(_ & _) // TODO optimize + if (lhs.level > maxTv.level) { + println(s"wrong level: ${lhs.level}") + if (constrainedTypes && lhs.level <= lvl) { + println(s"STASHING $maxTv bound in extr ctx") + val buf = ctx.extrCtx.getOrElseUpdate(maxTv, Buffer.empty) + buf += true -> lhs + cache -= lhs -> rhs + () + } else { + val lhs2 = extrudeAndCheck(lhs, rhs.level, true, MaxLevel, + cctx._2 :: prevCctxs.unzip._2 ::: prevCctxs.unzip._1) + println(s"EXTR LHS ~> $lhs2 to ${rhs.level}") + println(s" where ${lhs2.showBounds}") + // println(s" and ${lhs.showBounds}") + rec(lhs2, rhs, true) + } + } else rec(lhs, maxTv, true) + } + + } + // shadows.previous.foreach { sh => // println(s">> $sh ${sh.hashCode}") // } @@ -745,7 +902,90 @@ class ConstraintSolver extends NormalForms { self: Typer => // println(s" where ${FunctionType(lhs, rhs)(primProv).showBounds}") else { + /* + @tailrec + def findTV(cur: TV, lr: Bool, todo: Ls[ST], l: Ls[ST], r: Ls[ST]): (Ls[ST], Ls[ST]) = todo match { + case (tv: TypeVariable) :: todo if tv.level > cur.level => + if (lr) findTV(tv, true, cur :: l, r) + else findTV(tv, true, l, cur :: r) + case ComposedType(true, l, r) :: todo => + findTV(l :: r :: todo, done) + case ProxyType(st) :: todo => + findTV(st :: todo, l, r) + case NegType(st) :: todo => + findTV(todo, st :: l, r) + case st :: todo => + findTV(todo, l, st :: r) + case Nil => N + } + val (tv, lr, ls, rs) = findTV(DummyTV, rhs :: Nil, Nil, Nil) + if (tv isnt DummyTV) + if (lr) return () + else return () + */ + /* + val maxLevel = + val ucs = lhs.components(true) + ucs.iterator.collect { case tv: TV => tv }.maxByOption(_.level) match { + case S(tv) if tv.level >= lhs.level max rhs.level => + println(s"NEW $tv UB (${rhs.level})") + val newBound = (cctx._1 ::: cctx._2.reverse).foldRight(rhs)((c, ty) => + if (c.prov is noProv) ty else mkProxy(ty, c.prov)) + tv.upperBounds ::= newBound // update the bound + tv.lowerBounds.foreach(rec(_, rhs, true)) // propagate from the bound + case _ => + } + val ics = lhs.components(false) + */ + // lhs.components(true) + // val cs = (lhs & NegType(rhs)(noProv)).components(true) + val lhs_rhs = lhs -> rhs + /* + lhs_rhs match { + // case (_: TV, _) | (_, _: TV) => + case (lhs: TV, rhs) if lhs.level >= rhs.level => + case (_, rhs: TV) if lhs.level <= rhs.level => + case _ => + var maxTv = DummyTV + var isLeft = true + @tailrec + def allComponents(ls: Ls[ST], rs: Ls[ST], done_ls: Ls[ST], done_rs: Ls[ST]): (Ls[ST], Ls[ST]) = ls match { + case ComposedType(true, l, r) :: ls => allComponents(l :: r :: ls, rs, done_ls, done_rs) + case NegType(st) :: ls => allComponents(ls, st :: rs, done_ls, done_rs) + case ProvType(st) :: ls => allComponents(st :: ls, rs, done_ls, done_rs) + case (tv: TV) :: ls if tv.level > maxTv.level => + val oldTv = maxTv + val wasLeft = isLeft + maxTv = tv + isLeft = true + if (oldTv is DummyTV) allComponents(ls, rs, done_ls, done_rs) + else if (wasLeft) allComponents(ls, rs, oldTv :: done_ls, done_rs) + else allComponents(ls, rs, done_ls, oldTv :: done_rs) + case st :: ls => allComponents(ls, rs, st :: done_ls, done_rs) + case Nil => rs match { + case ComposedType(false, l, r) :: ls => allComponents(ls, l :: r :: rs, done_ls, done_rs) + case NegType(st) :: rs => allComponents(st :: ls, rs, done_ls, done_rs) + case ProvType(st) :: ls => allComponents(ls, st :: rs, done_ls, done_rs) + case (tv: TV) :: rs if tv.level > maxTv.level => + val oldTv = maxTv + val wasLeft = isLeft + maxTv = tv + isLeft = false + if (oldTv is DummyTV) allComponents(ls, rs, done_ls, done_rs) + else if (wasLeft) allComponents(ls, rs, oldTv :: done_ls, done_rs) + else allComponents(ls, rs, done_ls, oldTv :: done_rs) + case r :: rs => allComponents(Nil, rs, done_ls, r :: done_rs) + case Nil => (done_ls, done_rs) + } + } + val (ls, rs) = allComponents(lhs :: Nil, rhs :: Nil, Nil, Nil) + if (maxTv isnt DummyTV) + if (isLeft) return rec(maxTv, (ls.iterator.map(_.neg()) ++ rs).reduce(_ | _), true) + else return rec((ls.iterator ++ rs.iterator.map(_.neg())).reduce(_ & _), maxTv, true) + } + */ + (lhs_rhs match { case (_: ProvType, _) | (_, _: ProvType) => shadows // * Note: contrary to Simple-sub, we do have to remember subtyping tests performed @@ -826,7 +1066,6 @@ class ConstraintSolver extends NormalForms { self: Typer => case (lhs, tv @ AssignedVariable(rhs)) => rec(lhs, rhs, true) - case (lhs: TypeVariable, rhs) if rhs.level <= lhs.level => println(s"NEW $lhs UB (${rhs.level})") val newBound = (cctx._1 ::: cctx._2.reverse).foldRight(rhs)((c, ty) => @@ -842,8 +1081,47 @@ class ConstraintSolver extends NormalForms { self: Typer => rhs.upperBounds.foreach(rec(lhs, _, true)) // propagate from the bound - case (lhs: TypeVariable, rhs) => - val tv = lhs + case (lhs: TypeVariable, _rhs) => + // val tv = lhs + /* + /* + def findBetterTV(todo: Ls[ST], done: Ls[ST]): Opt[(TV, Ls[ST])] = todo match { + case (tv: TypeVariable) :: todo if tv.level > lhs.level => + S(tv, todo ::: done) + case ComposedType(true, l, r) :: todo => + findBetterTV(l :: r :: todo, done) + case ProxyType(st) :: todo => + findBetterTV(st :: todo, done) + case st :: todo => + findBetterTV(todo, st :: done) + case Nil => N + } + findBetterTV(rhs :: Nil, Nil) match { + case S((tv, ts)) => + rec(ts.foldLeft(lhs: ST)(_ & _), tv, true) + case N => + } + */ + def findBetterTV(todo: Ls[ST], l: Ls[ST], r: Ls[ST]): Opt[(ST, ST)] = todo match { + case (tv: TypeVariable) :: todo if tv.level > lhs.level => + S(tv, todo ::: done) + case ComposedType(true, l, r) :: todo => + findBetterTV(l :: r :: todo, done) + case ProxyType(st) :: todo => + findBetterTV(st :: todo, l, r) + case NegType(st) :: todo => + findBetterTV(todo, st :: l, r) + case st :: todo => + findBetterTV(todo, l, st :: r) + case Nil => N + } + findBetterTV(rhs :: Nil, Nil, Nil) + .foreach { case (l, r) => rec(l, r, true) } + */ + /* + val (tv, rhs) = constrainMaxTv(lhs, true) + if (rhs.level <= tv.level) return rec(tv, rhs, true) + println(s"wrong level: ${rhs.level}") if (constrainedTypes && rhs.level <= lvl) { println(s"STASHING $tv bound in extr ctx") @@ -859,9 +1137,15 @@ class ConstraintSolver extends NormalForms { self: Typer => // println(s" and ${rhs.showBounds}") rec(lhs, rhs2, true) } + */ + constrainMaxTv(lhs, true) case (lhs, rhs: TypeVariable) => - val tv = rhs + // val tv = rhs + /* + val (tv, lhs) = constrainMaxTv(rhs, false) + if (lhs.level <= tv.level) return rec(lhs, tv, true) + println(s"wrong level: ${lhs.level}") if (constrainedTypes && lhs.level <= lvl) { println(s"STASHING $tv bound in extr ctx") @@ -877,7 +1161,8 @@ class ConstraintSolver extends NormalForms { self: Typer => // println(s" and ${lhs.showBounds}") rec(lhs2, rhs, true) } - + */ + constrainMaxTv(rhs, false) case (TupleType(fs0), TupleType(fs1)) if fs0.size === fs1.size => // TODO generalize (coerce compatible tuples) fs0.lazyZip(fs1).foreach { case ((ln, l), (rn, r)) => @@ -935,8 +1220,11 @@ class ConstraintSolver extends NormalForms { self: Typer => val tvv = td.getVariancesOrDefault td.tparamsargs.unzip._2.lazyZip(tr1.targs).lazyZip(tr2.targs).foreach { (tv, targ1, targ2) => val v = tvv(tv) - if (!v.isContravariant) rec(targ1, targ2, false) - if (!v.isCovariant) rec(targ2, targ1, false) + // * old defs, just to make things compile + val t1 = targ1 match { case w: WildcardArg => TypeBounds(w.lb, w.ub)(w.prov) ; case st: ST => st } + val t2 = targ2 match { case w: WildcardArg => TypeBounds(w.lb, w.ub)(w.prov) ; case st: ST => st } + if (!v.isContravariant) rec(t1, t2, false) + if (!v.isCovariant) rec(t2, t1, false) } case N => /* @@ -953,33 +1241,44 @@ class ConstraintSolver extends NormalForms { self: Typer => */ ctx.tyDefs2.get(tr1.defn.name) match { case S(lti) => - lti.tparams.map(_._2).lazyZip(tr1.targs).lazyZip(tr2.targs).foreach { - (tv, targ1, targ2) => - val v = lti.varianceOf(tv) - if (!v.isContravariant) rec(targ1, targ2, false) - if (!v.isCovariant) rec(targ2, targ1, false) + lti.tparams.map(_._2).lazyZip(tr1.targs).lazyZip(tr2.targs).foreach { case (tv, ta1, ta2) => + val v = lti.varianceOf(tv) + (ta1, ta2) match { + case (WildcardArg(l0, r0), WildcardArg(l1, r1)) => + if (!v.isContravariant) rec(l1, l0, false) + if (!v.isCovariant) rec(r0, r1, false) + case (WildcardArg(l0, r0), rhs: ST) => + if (!v.isContravariant) rec(rhs, l0, false) + if (!v.isCovariant) rec(r0, rhs, false) + case (lhs: ST, WildcardArg(l1, r1)) => + if (!v.isContravariant) rec(l1, lhs, false) + if (!v.isCovariant) rec(lhs, r1, false) + case (targ1: ST, targ2: ST) => + if (!v.isContravariant) rec(targ1, targ2, false) + if (!v.isCovariant) rec(targ2, targ1, false) + } } case N => ??? // TODO } } } else { - if (tr1.mayHaveTransitiveSelfType) rec(tr1.expand, tr2.expand, true) + if (tr1.mayHaveTransitiveSelfType) rec(tr1.expand(true), tr2.expand(false), true) else (tr1.mkClsTag, tr2.mkClsTag) match { case (S(tag1), S(tag2)) if !(tag1 <:< tag2) => reportError() case _ => - rec(tr1.expand, tr2.expand, true) + rec(tr1.expand(true), tr2.expand(false), true) } } - case (tr: TypeRef, _) => rec(tr.expand, rhs, true) + case (tr: TypeRef, _) => rec(tr.expand(true), rhs, true) case (err @ ClassTag(ErrTypeId, _), tr: TypeRef) => // rec(tr.copy(targs = tr.targs.map(_ => err))(noProv), tr, true) // * ^ Nicely propagates more errors to the result, // * but can incur vast amounts of unnecessary constraining in the context of recursive types! () case (_, tr: TypeRef) => - rec(lhs, tr.expand, true) + rec(lhs, tr.expand(false), true) case (ClassTag(ErrTypeId, _), _) => () case (_, ClassTag(ErrTypeId, _)) => () @@ -1313,9 +1612,9 @@ class ConstraintSolver extends NormalForms { self: Typer => * `upperLvl` tracks the lowest such current quantification level. */ private final def extrude(ty: SimpleType, lowerLvl: Int, pol: Boolean, upperLvl: Level) - (implicit ctx: Ctx, cache: MutMap[TypeVarOrRigidVar->Bool, TypeVarOrRigidVar], cache2: MutSortMap[TraitTag, TraitTag], reason: Ls[Ls[ST]]) + (implicit ctx: Ctx, cache2: MutSortMap[TraitTag, TraitTag], reason: Ls[Ls[ST]]) : SimpleType = - // (trace(s"EXTR[${printPol(S(pol))}] $ty || $lowerLvl .. $upperLvl ${ty.level} ${ty.level <= lowerLvl}"){ + (trace(s"EXTR[${printPol(S(pol))}] $ty || $lowerLvl .. $upperLvl ${ty.level} ${ty.level <= lowerLvl}"){ if (ty.level <= lowerLvl) ty else ty match { case t @ TypeBounds(lb, ub) => if (pol) extrude(ub, lowerLvl, true, upperLvl) else extrude(lb, lowerLvl, false, upperLvl) case t @ FunctionType(l, r) => FunctionType(extrude(l, lowerLvl, !pol, upperLvl), extrude(r, lowerLvl, pol, upperLvl))(t.prov) @@ -1328,9 +1627,9 @@ class ConstraintSolver extends NormalForms { self: Typer => ArrayType(ar.update(extrude(_, lowerLvl, !pol, upperLvl), extrude(_, lowerLvl, pol, upperLvl)))(t.prov) case w @ Without(b, ns) => Without(extrude(b, lowerLvl, pol, upperLvl), ns)(w.prov) case tv @ AssignedVariable(ty) => - cache.getOrElse(tv -> true, { + ctx.extrCache.getOrElse(tv -> true, { val nv = freshVar(tv.prov, S(tv), tv.nameHint)(lowerLvl) - cache += tv -> true -> nv + ctx.extrCache.set(tv -> true, nv) val tyPos = extrude(ty, lowerLvl, true, upperLvl) val tyNeg = extrude(ty, lowerLvl, false, upperLvl) if (tyPos === tyNeg) @@ -1343,25 +1642,27 @@ class ConstraintSolver extends NormalForms { self: Typer => } nv }) + /* // !!!!!!!!!!!!!!!!!!!!!!!!!!! not valid in the presence of skolems and reconstraining?! case tv: TypeVariable if tv.level > upperLvl => - assert(!cache.contains(tv -> false), (tv, cache)) + assert(!ctx.extrCache.contains(tv -> false), (tv, ctx.extrCache.cache.get(lvl))) // * If the TV's level is strictly greater than `upperLvl`, // * it means the TV is quantified by a type being copied, // * so all we need to do is copy this TV along (it is not extruded). // * We pick `tv -> true` (and not `tv -> false`) arbitrarily. if (tv.lowerBounds.isEmpty && tv.upperBounds.isEmpty) tv - else cache.getOrElse(tv -> true, { + else ctx.extrCache.getOrElse(tv -> true, { val nv = freshVar(tv.prov, S(tv), tv.nameHint)(tv.level) - cache += tv -> true -> nv + ctx.extrCache.set(tv -> true, nv) nv.lowerBounds = tv.lowerBounds.map(extrude(_, lowerLvl, true, upperLvl)) nv.upperBounds = tv.upperBounds.map(extrude(_, lowerLvl, false, upperLvl)) nv }) + */ case t @ SpliceType(fs) => t.updateElems(extrude(_, lowerLvl, pol, upperLvl), extrude(_, lowerLvl, !pol, upperLvl), extrude(_, lowerLvl, pol, upperLvl), t.prov) - case tv: TypeVariable => cache.getOrElse(tv -> pol, { + case tv: TypeVariable => ctx.extrCache.getOrElse(tv -> pol, { val nv = freshVar(tv.prov, S(tv), tv.nameHint)(lowerLvl) - cache += tv -> pol -> nv + ctx.extrCache.set(tv -> pol, nv) if (pol) { tv.upperBounds ::= nv nv.lowerBounds = tv.lowerBounds.map(extrude(_, lowerLvl, pol, upperLvl)) @@ -1393,21 +1694,40 @@ class ConstraintSolver extends NormalForms { self: Typer => } else die // shouldn't happen case _: ClassTag | _: TraitTag | _: Extruded => ty case tr @ TypeRef(d, ts) => - TypeRef(d, tr.mapTargs(S(pol)) { - case (N, targ) => - // * Note: the semantics of TypeBounds is inappropriuate for this use (known problem; FIXME later) - TypeBounds.mk(extrude(targ, lowerLvl, false, upperLvl), extrude(targ, lowerLvl, true, upperLvl)) // Q: ? subtypes? - // * A sanity-checking version, making sure the type range is correct (LB subtype of UB): - /* - val a = extrude(targ, lowerLvl, false, upperLvl) - val b = extrude(targ, lowerLvl, true, upperLvl) - implicit val r: Raise = throw _ - implicit val p: TP = noProv - constrain(a, b) - TypeBounds.mk(a, b) - */ - case (S(pol), targ) => extrude(targ, lowerLvl, pol, upperLvl) - })(tr.prov) + val (tparamsargs, tvv, acceptsWildcards) = ctx.tyDefs2.get(d.name) match { + case S(lti) => + (lti.tparams.map(tp => (tp._1, tp._2)), (tv: TV) => lti.varianceOf(tv), lti.kind isnt Als) + case N => + ctx.tyDefs.get(d.name) match { + case S(td) => + val vces = td.tvarVariances.getOrElse(VarianceStore.empty.withDefaultValue(VarianceInfo.in)) + (td.tparamsargs, (tv: TV) => vces(tv), false) + case N => + // (tv: TV) => N + ??? + } + } + assert(tparamsargs.sizeCompare(ts) === 0) + val newTargs = (tparamsargs lazyZip ts).map { case ((_, tv), ta) => + tvv(tv) match { + case VarianceInfo(true, true) if acceptsWildcards => + WildcardArg(BotType, TopType)(noProv) + case VarianceInfo(co, contra) => + ta match { + case WildcardArg(lb, ub) => + if (co) extrude(ub, lowerLvl, pol, upperLvl) + else if (contra) extrude(lb, lowerLvl, !pol, upperLvl) + else WildcardArg.mk(extrude(lb, lowerLvl, !pol, upperLvl), extrude(ub, lowerLvl, pol, upperLvl), tr.prov) + case st: ST => + if (co) extrude(st, lowerLvl, pol, upperLvl) + else if (contra) extrude(st, lowerLvl, !pol, upperLvl) + else if (acceptsWildcards) + WildcardArg.mk(extrude(st, lowerLvl, !pol, upperLvl), extrude(st, lowerLvl, pol, upperLvl), tr.prov) + else TypeBounds.mk(extrude(st, lowerLvl, false, upperLvl), extrude(st, lowerLvl, true, upperLvl)) + } + } + } + TypeRef(d, newTargs)(tr.prov) case PolymorphicType(polymLevel, body) => PolymorphicType(polymLevel, extrude(body, lowerLvl, pol, upperLvl = // upperLvl min polymLevel // * for some crazy reason, this stopped type checking @@ -1420,7 +1740,7 @@ class ConstraintSolver extends NormalForms { self: Typer => case o @ Overload(alts) => o.mapAlts(extrude(_, lowerLvl, !pol, upperLvl))(extrude(_, lowerLvl, pol, upperLvl)) } - // }(r => s"=> $r")) + }(r => s"=> $r")) def err(msg: Message, loco: Opt[Loc])(implicit raise: Raise): SimpleType = { @@ -1507,11 +1827,33 @@ class ConstraintSolver extends NormalForms { self: Typer => case tv @ AssignedVariable(ty) => freshened.getOrElse(tv, { - val nv = freshVar(tv.prov, S(tv), tv.nameHint)(if (tv.level > below) tv.level else lvl) + val nv = freshVar(tv.prov, S(tv), tv.nameHint)(if (tv.level > below) tv.level else { + assert(lvl <= below, "this condition should be false for the result to be correct") + lvl + }) freshened += tv -> nv val ty2 = freshen(ty) - nv.assignedTo = S(ty2) - nv + val l = ty2.level + if (l <= nv.level) { + // * Normal case. + nv.assignedTo = S(ty2) + nv + } else { + // * Ouch... Freak case. + // * Because tv could be recursive and refer to itself, + // * in the general case we must do the freshening from scratch. + // * This is obviously horrible and could lead to pathological complexity; + // * but I believe it only occurs in freak cases related to `freshen` being (ab)used + // * to instantiate some skolems to type arguments whose levels happen to be bigger than ctx.lvl. + // * As of this commit, it seems this case is only triggered by shared/src/test/diff/nu/Eval.mls. + // * Eventually we'll want to fix this by making ctx.lvl agree + // * with whatever is substituted by freshening. + val nv = freshVar(tv.prov, S(tv), tv.nameHint)(l) + freshened += tv -> nv + val ty2 = freshen(ty) + nv.assignedTo = S(ty2) + nv + } }) // * Note: I forgot why I though this was unsound... @@ -1598,7 +1940,10 @@ class ConstraintSolver extends NormalForms { self: Typer => freshen(id) case _: ClassTag | _: TraitTag | _: SkolemTag | _: Extruded => ty case w @ Without(b, ns) => Without(freshen(b), ns)(w.prov) - case tr @ TypeRef(d, ts) => TypeRef(d, ts.map(freshen(_)))(tr.prov) + case tr @ TypeRef(d, ts) => TypeRef(d, ts.map { + case w@WildcardArg(lb, ub) => WildcardArg(freshen(lb), freshen(ub))(w.prov) + case t: ST => freshen(t) + })(tr.prov) case pt @ PolymorphicType(polyLvl, bod) if pt.level <= above => pt // is this really useful? case pt @ PolymorphicType(polyLvl, bod) => if (lvl > polyLvl) freshen(pt.raiseLevelToImpl(lvl, leaveAlone)) diff --git a/shared/src/main/scala/mlscript/NewLexer.scala b/shared/src/main/scala/mlscript/NewLexer.scala index 0c6bc7d8e7..fbb27e408d 100644 --- a/shared/src/main/scala/mlscript/NewLexer.scala +++ b/shared/src/main/scala/mlscript/NewLexer.scala @@ -464,7 +464,7 @@ object NewLexer { "val", "var", // "is", - // "as", + "as", "of", // "and", // "or", @@ -498,7 +498,8 @@ object NewLexer { "undefined", "abstract", "constructor", - "virtual" + "virtual", + "restricts", ) def printToken(tl: TokLoc): Str = tl match { diff --git a/shared/src/main/scala/mlscript/NewParser.scala b/shared/src/main/scala/mlscript/NewParser.scala index a7837178e4..b77906319f 100644 --- a/shared/src/main/scala/mlscript/NewParser.scala +++ b/shared/src/main/scala/mlscript/NewParser.scala @@ -770,6 +770,9 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo case (KEYWORD("super"), l0) :: _ => consume exprCont(Super().withLoc(S(l0)), prec, allowNewlines = false) + case (IDENT("?", true), l0) :: _ => + consume + exprCont(Var("?").withLoc(S(l0)), prec, allowNewlines = false) case (IDENT("~", _), l0) :: _ => consume val rest = expr(prec, allowSpace = true) @@ -1080,7 +1083,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo else App(App(v, PlainTup(acc)), PlainTup(rhs)) }, prec, allowNewlines) } - case (KEYWORD(":"), l0) :: _ if prec <= NewParser.prec(':') => + case (KEYWORD("as" | ":"), l0) :: _ if prec <= NewParser.prec(':') => consume R(Asc(acc, typ(0))) case (KEYWORD("where"), l0) :: _ if prec <= 1 => @@ -1278,35 +1281,59 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo } // TODO support line-broken param lists; share logic with args/argsOrIf - def typeParams(implicit fe: FoundErr, et: ExpectThen): Ls[(Opt[VarianceInfo], TypeName)] = { + def typeParams(implicit fe: FoundErr, et: ExpectThen): Ls[(TypeParamInfo, TypeName)] = { + val visinfo = yeetSpaces match { + case (KEYWORD("type"), l0) :: _ => + consume + S(l0) + case _ => N + } val vinfo = yeetSpaces match { case (KEYWORD("in"), l0) :: (KEYWORD("out"), l1) :: _ => consume - S(VarianceInfo.in, l0 ++ l1) + S(VarianceInfo.in -> (l0++l1)) case (KEYWORD("in"), l0) :: _ => consume - S(VarianceInfo.contra, l0) + S(VarianceInfo.contra -> l0) case (KEYWORD("out"), l0) :: _ => consume - S(VarianceInfo.co, l0) - case _ => N + S(VarianceInfo.co -> l0) + case _ => + N } yeetSpaces match { case (IDENT(nme, false), l0) :: _ => consume val tyNme = TypeName(nme).withLoc(S(l0)) + + @inline def getTypeName(kw: String) = yeetSpaces match { + case (KEYWORD(k), l0) :: _ if k === kw => consume + yeetSpaces match { + case (IDENT(nme, false), l1) :: _ => + consume; S(TypeName(nme).withLoc(S(l1))) + case _ => err(msg"dangling $kw keyword" -> S(l0) :: Nil); N + } + case _ => N + } + val lb = getTypeName("restricts") + val ub = getTypeName("extends") + // TODO update `TypeParamInfo` to use lb and ub yeetSpaces match { case (COMMA, l0) :: _ => consume - vinfo.map(_._1) -> tyNme :: typeParams + TypeParamInfo(vinfo.map(_._1), visinfo.isDefined, lb, ub) -> tyNme :: typeParams case _ => - vinfo.map(_._1) -> tyNme :: Nil + TypeParamInfo(vinfo.map(_._1), visinfo.isDefined, lb, ub) -> tyNme :: Nil } case _ => - vinfo match { - case S((_, loc)) => + (visinfo, vinfo) match { + case (S(l1), S(_ -> l2)) => + err(msg"dangling type member and variance information" -> S(l1 ++ l2) :: Nil) + case (_, S(_ -> loc)) => err(msg"dangling variance information" -> S(loc) :: Nil) - case N => + case (S(loc), _) => + err(msg"dangling visible type member" -> S(loc) :: Nil) + case (N, N) => } Nil } @@ -1373,7 +1400,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo case (NEWLINE, _) :: _ => // TODO: | ... assert(seqAcc.isEmpty) acc.reverse - case (IDENT(nme, true), _) :: _ if nme =/= "-" => // TODO: | ... + case (IDENT(nme, true), _) :: _ if nme =/= "-" && nme =/= "?" => // TODO: | ... assert(seqAcc.isEmpty) acc.reverse case _ => diff --git a/shared/src/main/scala/mlscript/NormalForms.scala b/shared/src/main/scala/mlscript/NormalForms.scala index 4378747145..19c0377317 100644 --- a/shared/src/main/scala/mlscript/NormalForms.scala +++ b/shared/src/main/scala/mlscript/NormalForms.scala @@ -22,9 +22,13 @@ class NormalForms extends TyperDatatypes { self: Typer => mergeSortedMap(trs1, trs2) { (tr1, tr2) => assert(tr1.defn === tr2.defn) assert(tr1.targs.size === tr2.targs.size) - TypeRef(tr1.defn, (tr1.targs lazyZip tr2.targs).map((ta1, ta2) => - if (pol) TypeBounds.mk(ta1 & ta2, ta1 | ta2) else TypeBounds.mk(ta1 | ta2, ta1 & ta2) - ))(noProv) + TypeRef(tr1.defn, (tr1.targs lazyZip tr2.targs).map { + case (l: WildcardArg, r: WildcardArg) => + if (pol) WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) else WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) + case (l: WildcardArg, r: ST) => if (pol) WildcardArg.mk(l.lb | r, l.ub & r) else WildcardArg.mk(l.lb & r, l.ub | r) + case (l: ST, r: WildcardArg) => if (pol) WildcardArg.mk(l | r.lb, l & r.ub) else WildcardArg.mk(l & r.lb, l | r.ub) + case (l: ST, r: ST) => if (pol) WildcardArg.mk(l | r, l & r) else WildcardArg.mk(l & r, l | r) + })(noProv) } @@ -223,11 +227,25 @@ class NormalForms extends TyperDatatypes { self: Typer => val thatTarg = thatTargs.head thatTargs = thatTargs.tail vce match { - case S(true) => otherTarg & thatTarg - case S(false) => otherTarg | thatTarg - case N => - if (pol) TypeBounds.mk(otherTarg | thatTarg, otherTarg & thatTarg) - else TypeBounds.mk(otherTarg & thatTarg, otherTarg | thatTarg) + case S(true) => (otherTarg, thatTarg) match { + case (l: WildcardArg, r: WildcardArg) => WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) + case (l: WildcardArg, r: ST) => l.ub & r + case (l: ST, r: WildcardArg) => l & r.ub + case (l: ST, r: ST) => l & r + } + case S(false) => (otherTarg, thatTarg) match { + case (l: WildcardArg, r: WildcardArg) => WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) + case (l: WildcardArg, r: ST) => l.lb | r + case (l: ST, r: WildcardArg) => l | r.lb + case (l: ST, r: ST) => l | r + } + case N => (otherTarg, thatTarg) match { + case (l: WildcardArg, r: WildcardArg) => + if (pol) WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) else WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) + case (l: WildcardArg, r: ST) => if (pol) WildcardArg.mk(l.lb | r, l.ub & r) else WildcardArg.mk(l.lb & r, l.ub | r) + case (l: ST, r: WildcardArg) => if (pol) WildcardArg.mk(l | r.lb, l & r.ub) else WildcardArg.mk(l & r.lb, l | r.ub) + case (l: ST, r: ST) => if (pol) WildcardArg.mk(l | r, l & r) else WildcardArg.mk(l & r, l | r) + } } } TypeRef(that.defn, newTargs)(that.prov) @@ -268,8 +286,23 @@ class NormalForms extends TyperDatatypes { self: Typer => case (LhsTop, _) => false case (LhsRefined(b1, ts1, rt1, trs1), LhsRefined(b2, ts2, rt2, trs2)) => b2.forall(b2 => b1.exists(_ <:< b2)) && - ts2.forall(ts1) && rt1 <:< rt2 && - trs2.valuesIterator.forall(tr2 => trs1.valuesIterator.exists(_ <:< tr2)) + ts2.forall { + case sk: SkolemTag => ts1(sk) + case tt: TraitTag => ts1(tt) + // case Extruded(true, sk) => true + // case _ => false + case Extruded(pol, sk) => !pol + // case Extruded(pol, sk) => !pol || ts1.exists { // find ? <: bot + // case Extruded(true, _) => true + // case _ => false + // } + } && rt1 <:< rt2 && + // ts2.forall(ts1) && rt1 <:< rt2 && + trs2.valuesIterator.forall(tr2 => trs1.valuesIterator.exists(_ <:< tr2)) || ts1.exists { + // case Extruded(false, _) => true + case Extruded(true, _) => true + case _ => false + } } def isTop: Bool = isInstanceOf[LhsTop.type] } @@ -347,11 +380,25 @@ class NormalForms extends TyperDatatypes { self: Typer => val thatTarg = thatTargs.head thatTargs = thatTargs.tail vce match { - case S(true) => otherTarg | thatTarg - case S(false) => otherTarg & thatTarg - case N => - if (pol) TypeBounds.mk(otherTarg & thatTarg, otherTarg | thatTarg) - else TypeBounds.mk(otherTarg | thatTarg, otherTarg & thatTarg) + case S(true) => (otherTarg, thatTarg) match { + case (l: WildcardArg, r: WildcardArg) => WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) + case (l: WildcardArg, r: ST) => l.lb | r + case (l: ST, r: WildcardArg) => l | r.lb + case (l: ST, r: ST) => l | r + } + case S(false) => (otherTarg, thatTarg) match { + case (l: WildcardArg, r: WildcardArg) => WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) + case (l: WildcardArg, r: ST) => l.ub & r + case (l: ST, r: WildcardArg) => l & r.ub + case (l: ST, r: ST) => l & r + } + case N => (otherTarg, thatTarg) match { + case (l: WildcardArg, r: WildcardArg) => + if (pol) WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) else WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) + case (l: WildcardArg, r: ST) => if (pol) WildcardArg.mk(l.lb & r, l.ub | r) else WildcardArg.mk(l.lb | r, l.ub & r) + case (l: ST, r: WildcardArg) => if (pol) WildcardArg.mk(l & r.lb, l | r.ub) else WildcardArg.mk(l | r.lb, l & r.ub) + case (l: ST, r: ST) => if (pol) WildcardArg.mk(l & r, l | r) else WildcardArg.mk(l | r, l & r) + } } } TypeRef(that.defn, newTargs)(that.prov) @@ -835,7 +882,7 @@ class NormalForms extends TyperDatatypes { self: Typer => // * TODO later: when proper TypeRef-based simplif. is implemented, can remove this special case if (preserveTypeRefs && !primitiveTypes.contains(defn.name) || !tr.canExpand) { of(polymLvl, cons, LhsRefined(tr.mkClsTag, ssEmp, RecordType.empty, SortedMap(defn -> tr))) - } else mk(polymLvl, cons, tr.expandOrCrash, pol) + } else mk(polymLvl, cons, tr.expandOrCrash(pol), pol) case TypeBounds(lb, ub) => mk(polymLvl, cons, if (pol) ub else lb, pol) case PolymorphicType(lvl, bod) => mk(lvl, cons, bod, pol) case ConstrainedType(cs, bod) => mk(polymLvl, cs ::: cons, bod, pol) @@ -879,7 +926,7 @@ class NormalForms extends TyperDatatypes { self: Typer => case tr @ TypeRef(defn, targs) => if (preserveTypeRefs && !primitiveTypes.contains(defn.name) || !tr.canExpand) { CNF(Disjunct(RhsBases(Nil, N, SortedMap.single(defn -> tr)), ssEmp, LhsTop, ssEmp) :: Nil) - } else mk(polymLvl, cons, tr.expandOrCrash, pol) + } else mk(polymLvl, cons, tr.expandOrCrash(pol), pol) case TypeBounds(lb, ub) => mk(polymLvl, cons, if (pol) ub else lb, pol) case PolymorphicType(lvl, bod) => mk(lvl, cons, bod, pol) case ConstrainedType(cs, bod) => mk(lvl, cs ::: cons, bod, pol) diff --git a/shared/src/main/scala/mlscript/NuTypeDefs.scala b/shared/src/main/scala/mlscript/NuTypeDefs.scala index 0ce7f326c5..b9856956fc 100644 --- a/shared/src/main/scala/mlscript/NuTypeDefs.scala +++ b/shared/src/main/scala/mlscript/NuTypeDefs.scala @@ -13,7 +13,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => type Params = Ls[Var -> FieldType] - type TyParams = Ls[(TN, TV, Opt[VarianceInfo])] + type TyParams = Ls[(TN, TV, TypeParamInfo)] sealed abstract class NuDeclInfo @@ -174,8 +174,9 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => // TODO dedup with the one in TypedNuCls lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map { - case (nme @ TypeName(name), tv, _) => - td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = true)(level) + case (nme @ TypeName(name), tv, TypeParamInfo(_, v, _, _)) => + tparamField(td.nme, nme, v).name -> + NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = true)(level) } ++ parentTP def freshenAbove(lim: Int, rigidify: Bool) @@ -239,8 +240,8 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => /** Includes class-name-coded type parameter fields. */ lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map { - case (nme @ TypeName(name), tv, _) => - td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = true)(level) + case (nme @ TypeName(name), tv, TypeParamInfo(_, v, _, _)) => + tparamField(td.nme, nme, v).name -> NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = true)(level) } ++ parentTP // TODO @@ -283,7 +284,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => } // TODO check consistency with explicitVariances - val res = store ++ tparams.iterator.collect { case (_, tv, S(vi)) => tv -> vi } + val res = store ++ tparams.iterator.collect { case (_, tv, TypeParamInfo(S(vi), _, _, _)) => tv -> vi } _variances = S(res) @@ -356,9 +357,9 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => def isPublic = true // TODO lazy val virtualMembers: Map[Str, NuMember] = members ++ tparams.map { - case (nme @ TypeName(name), tv, _) => - td.nme.name+"#"+name -> NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = false)(level) - } + case (nme @ TypeName(name), tv, TypeParamInfo(_, v, _, _)) => + tparamField(td.nme, nme, v).name -> NuParam(nme, FieldType(S(tv), tv)(provTODO), isPublic = false)(level) + } def freshenAbove(lim: Int, rigidify: Bool) (implicit ctx: Ctx, freshened: MutMap[TV,ST]) @@ -586,7 +587,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => fd.copy()(fd.declareLoc, fd.virtualLoc, fd.mutLoc, fd.signature, outer, fd.genField, fd.annotations) } case td: NuTypeDef => - if (td.nme.name in reservedTypeNames) + if (td.nme.name.in(reservedTypeNames)) err(msg"Type name '${td.nme.name}' is reserved", td.toLoc) td } @@ -929,19 +930,23 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => lazy val tparams: TyParams = ctx.nest.nextLevel { implicit ctx => decl match { case td: NuTypeDef => - td.tparams.map(tp => - (tp._2, freshVar( + td.tparams.map(tp => { + val fv = freshVar( TypeProvenance(tp._2.toLoc, "type parameter", S(tp._2.name), isType = true), - N, S(tp._2.name)), tp._1)) + N, S(tp._2.name)) + // TODO assign the correct bounds (`typeType` causes cycle) + // fv.lowerBounds = tp._1.lb.toList.map(TypeRef(_, Nil)(provTODO)) + // fv.upperBounds = tp._1.ub.toList.map(TypeRef(_, Nil)(provTODO)) + (tp._2, fv, tp._1) }) case fd: NuFunDef => fd.tparams.map { tn => (tn, freshVar( TypeProvenance(tn.toLoc, "method type parameter", originName = S(tn.name), isType = true), - N, S(tn.name)), N) + N, S(tn.name)), TypeParamInfo(N, false, N, N)) } } } @@ -950,7 +955,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => } lazy val explicitVariances: VarianceStore = - MutMap.from(tparams.iterator.map(tp => tp._2 -> tp._3.getOrElse(VarianceInfo.in))) + MutMap.from(tparams.iterator.map(tp => tp._2 -> tp._3.varinfo.getOrElse(VarianceInfo.in))) def varianceOf(tv: TV)(implicit ctx: Ctx): VarianceInfo = // TODO make use of inferred vce if result is completed @@ -1109,7 +1114,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => err(msg"${raw.kind.str} $rawName expects ${ raw.tparams.size.toString} type parameter(s); got ${pta.size.toString}", Loc(v :: pta)) } - refreshHelper2(raw: PolyNuDecl, v: Var, parTargs.map(_.map(typeType(_)))) + refreshHelper2(raw: PolyNuDecl, v: Var, parTargs.map(_.map(typeType(_))), true) } def complete()(implicit raise: Raise): TypedNuDecl = result.getOrElse { @@ -1480,8 +1485,11 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => val allMembers = ( trtMembers.iterator.map(d => d.name -> d) - ++ ttu.implementedMembers.map(d => d.name -> d) - ++ typedSignatureMembers + ++ ttu.implementedMembers.map { + case als: TypedNuAls => als.name -> NuParam(TypeName(als.name), + FieldType(S(als.body), als.body)(als.body.prov), true)(als.level) + case td => td.name -> td + } ++ typedSignatureMembers ).toMap // check trait overriding @@ -1541,7 +1549,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => val finalType = thisTV val tparamMems = tparams.map { case (tp, tv, vi) => // TODO use vi - val fldNme = td.nme.name + "#" + tp.name + val fldNme = tparamField(td.name, tp.name, vi.visible) val skol = SkolemTag(tv)(tv.prov) NuParam(TypeName(fldNme).withLocOf(tp), FieldType(S(skol), skol)(tv.prov), isPublic = true)(lvl) } @@ -1681,7 +1689,14 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => println(s"baseClsImplemMembers ${baseClsImplemMembers}") - val newImplems = ttu.implementedMembers + val newImplems = ttu.implementedMembers.map { + // * transform type alias member to type member + case als: TypedNuAls => + if (tparamFields.map(_._1.name).contains(als.name)) + err(msg"Class type member '${als.name}' already exists", als.toLoc) + NuParam(TypeName(als.name), FieldType(S(als.body), als.body)(als.body.prov), true)(als.level) + case td => td + } val clsSigns = typedSignatureMembers.map(_._2) @@ -1889,7 +1904,7 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => } - def refreshHelper2(raw: PolyNuDecl, v: Var, parTargs: Opt[Ls[ST]]) + def refreshHelper2(raw: PolyNuDecl, v: Var, parTargs: Opt[Ls[SimpleTypeOrWildcard]], pol: Bool) (implicit ctx: Ctx): (MutMap[TV, ST], Map[Str, NuParam]) = { val freshened: MutMap[TV, ST] = MutMap.empty val rawName = v.name @@ -1901,8 +1916,26 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => case tv: TV => println(s"Passing ${tn.name} :: ${_tv} <=< ${tv}") tv - case _ => - println(s"Assigning ${tn.name} :: ${_tv} := $targ where ${targ.showBounds}") + case wc: WildcardArg => + println(s"Assigning ${tn.name} :: ${_tv} := $wc") + val tv = + freshVar(_tv.prov, S(_tv), _tv.nameHint, + lbs = _tv.lowerBounds, + ubs = _tv.upperBounds, + )(targ.level) + println(s"Set ${tv} ~> ${_tv}") + assert(tv.assignedTo.isEmpty) + assert(tv.lowerBounds.isEmpty, tv.lowerBounds) + assert(tv.upperBounds.isEmpty, tv.upperBounds) + // TODO use pol + tv.assignedTo = S( + if (pol) TypeBounds(wc.lb, wc.ub)(wc.prov) else TypeBounds(wc.ub, wc.lb)(wc.prov) + ) + + println(s"Assigned ${tv.assignedTo}") + tv + case st: ST => + println(s"Assigning ${tn.name} :: ${_tv} := $st where ${st.showBounds}") val tv = freshVar(_tv.prov, S(_tv), _tv.nameHint, lbs = _tv.lowerBounds, @@ -1915,13 +1948,14 @@ class NuTypeDefs extends ConstraintSolver { self: Typer => // * When we support bounded types, bounds check will be needed at the type definition site assert(tv.lowerBounds.isEmpty, tv.lowerBounds) assert(tv.upperBounds.isEmpty, tv.upperBounds) - tv.assignedTo = S(targ) + tv.assignedTo = S(st) - // println(s"Assigned ${tv.assignedTo}") + println(s"Assigned ${tv.assignedTo}") tv }) freshened += _tv -> tv - rawName+"#"+tn.name -> NuParam(tn, FieldType(S(tv), tv)(provTODO), isPublic = true)(ctx.lvl) + tparamField(rawName, tn.name, vi.visible) -> + NuParam(tn, FieldType(S(tv), tv)(provTODO), isPublic = true)(ctx.lvl) } freshened -> parTP.toMap diff --git a/shared/src/main/scala/mlscript/TypeDefs.scala b/shared/src/main/scala/mlscript/TypeDefs.scala index a33177486b..c186444bc4 100644 --- a/shared/src/main/scala/mlscript/TypeDefs.scala +++ b/shared/src/main/scala/mlscript/TypeDefs.scala @@ -110,9 +110,11 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => } } - - def tparamField(clsNme: TypeName, tparamNme: TypeName): Var = - Var(clsNme.name + "#" + tparamNme.name) + def tparamField(clsNme: TypeName, tparamNme: TypeName, visible: Bool): Var = + Var(tparamField(clsNme.name, tparamNme.name, visible)) + + def tparamField(clsNme: String, tparamNme: String, visible: Bool): String = + if (!visible) clsNme + "#" + tparamNme else tparamNme def clsNameToNomTag(td: NuTypeDef)(prov: TypeProvenance, ctx: Ctx): ClassTag = { require((td.kind is Cls) || (td.kind is Mod), td.kind) @@ -158,7 +160,7 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => { ty match { case tr @ TypeRef(td, targs) => - fieldsOf(tr.expandWith(paramTags, selfTy = false), paramTags) + fieldsOf(tr.expandWith(paramTags, selfTy = false, pol = true), paramTags) case ComposedType(false, l, r) => mergeMap(fieldsOf(l, paramTags), fieldsOf(r, paramTags))(_ && _) case RecordType(fs) => fs.toMap @@ -231,7 +233,7 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => case TypeRef(tn, _) if travsersed(L(tn)) => err(msg"illegal cycle involving type ${tn}", prov.loco) false - case tr @ TypeRef(tn, targs) => checkCycle(tr.expand)(travsersed + L(tn)) + case tr @ TypeRef(tn, targs) => checkCycle(tr.expand(true))(travsersed + L(tn)) case ComposedType(_, l, r) => checkCycle(l) && checkCycle(r) case NegType(u) => checkCycle(u) case p: ProxyType => checkCycle(p.underlying) @@ -275,8 +277,8 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => false } tap (_ => parentsClasses += tr) } else - checkParents(tr.expand) - case Trt => checkParents(tr.expand) + checkParents(tr.expand(true)) + case Trt => checkParents(tr.expand(true)) case Mod => err(msg"cannot inherit from a module", prov.loco) false @@ -343,7 +345,8 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => case _ => val fields = fieldsOf(td.bodyTy, paramTags = true) val tparamTags = td.tparamsargs.map { case (tp, tv) => - tparamField(td.nme, tp) -> FieldType(Some(tv), tv)(tv.prov) } + // `false` means using `C#A` (old type member names) + tparamField(td.nme, tp, false) -> FieldType(Some(tv), tv)(tv.prov) } val ctor = k match { case Cls => val nomTag = clsNameToNomTag(td)(originProv(td.nme.toLoc, "class", td.nme.name), ctx) @@ -384,13 +387,16 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => } def checkRegular(ty: SimpleType)(implicit reached: Map[Str, Ls[SimpleType]]): Bool = ty match { case tr @ TypeRef(defn, targs) => reached.get(defn.name) match { - case None => checkRegular(tr.expandWith(false, selfTy = false))(reached + (defn.name -> targs)) + case None => checkRegular(tr.expandWith(false, selfTy = false, pol = true))(reached + (defn.name -> targs.map { + case w: WildcardArg => TypeBounds(w.lb, w.ub)(w.prov) + case st: ST => st + })) case Some(tys) => // Note: this check *has* to be relatively syntactic because // the termination of constraint solving relies on recursive type occurrences // obtained from unrolling a recursive type to be *equal* to the original type // and to have the same has hashCode (see: the use of a cache MutSet) - if (defn === td.nme && tys =/= targs) { + if (defn === td.nme && tys =/= targs.map{ case w: WildcardArg => TypeBounds(w.lb, w.ub)(w.prov) ; case st: ST => st }) { err(msg"Type definition is not regular: it occurs within itself as ${ expandType(tr).show(Typer.newDefs) }, but is defined as ${ @@ -525,7 +531,10 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => MethodSet(tr.defn, Nil, Map.empty, Map.empty) case S(td2) => implicit val thisCtx: Ctx = ctx.nest - val targsMap = td2.tparams.iterator.map(_.name).zip(tr.targs).toMap + val targsMap = td2.tparams.iterator.map(_.name).zip(tr.targs.map { + case w: WildcardArg => TypeBounds(w.lb, w.ub)(w.prov) + case st: ST => st + }).toMap val declared = MutMap.empty[Str, Opt[Loc]] val defined = MutMap.empty[Str, Opt[Loc]] @@ -584,9 +593,10 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => // If the method is already in the environment, // it means it belongs to a previously-defined class/trait (not the one being typed), // in which case we need to perform a substitution on the corresponding method body... - val targsMap3 = td2.targs.lazyZip(tr.targs).toMap[ST, ST] + - (td2.thisTv -> td.thisTv) + - (td.thisTv -> td.thisTv) + val targsMap3 = td2.targs.lazyZip(tr.targs.map { + case w: WildcardArg => TypeBounds(w.lb, w.ub)(w.prov) + case st: ST => st + }).toMap[ST, ST] + (td2.thisTv -> td.thisTv) + (td.thisTv -> td.thisTv) // Subsitute parent this TVs to current this TV. PolymorphicType(mt.bodyPT.level, subst(mt.bodyPT.body, targsMap3) match { // Try to wnwrap one layer of prov, which would have been wrapped by `MethodType.bodyPT`, @@ -610,7 +620,7 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => } nme.name -> mthTy } - MethodSet(td2.nme, filterTR(tr.expand).map(rec(_)(thisCtx)), + MethodSet(td2.nme, filterTR(tr.expand(true)).map(rec(_)(thisCtx)), td2.mthDecls.iterator.map(go).toMap, td2.mthDefs.iterator.map(go).toMap) } val mds = rec(TypeRef(td.nme, rigidtargs)(tp(td.toLoc, "type definition")), true)(ctx) @@ -652,7 +662,7 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => * false polarity if contravariant position visit * both if invariant position visit */ - def updateVariance(ty: SimpleType, curVariance: VarianceInfo)(implicit tyDef: TypeDef, visited: MutSet[Bool -> TypeVariable]): Unit = { + def updateVariance(ty: SimpleTypeOrWildcard, curVariance: VarianceInfo)(implicit tyDef: TypeDef, visited: MutSet[Bool -> TypeVariable]): Unit = { def fieldVarianceHelper(fieldTy: FieldType): Unit = { fieldTy.lb.foreach(lb => updateVariance(lb, curVariance.flip)) updateVariance(fieldTy.ub, curVariance) @@ -716,6 +726,9 @@ class TypeDefs extends NuTypeDefs { Typer: Typer => case TypeBounds(lb, ub) => updateVariance(lb, VarianceInfo.contra) updateVariance(ub, VarianceInfo.co) + case WildcardArg(lb, ub) => + updateVariance(lb, VarianceInfo.contra) + updateVariance(ub, VarianceInfo.co) case ArrayType(inner) => fieldVarianceHelper(inner) case TupleType(fields) => fields.foreach { case (_ , fieldTy) => fieldVarianceHelper(fieldTy) diff --git a/shared/src/main/scala/mlscript/TypeSimplifier.scala b/shared/src/main/scala/mlscript/TypeSimplifier.scala index f444498dad..caf6e7e35f 100644 --- a/shared/src/main/scala/mlscript/TypeSimplifier.scala +++ b/shared/src/main/scala/mlscript/TypeSimplifier.scala @@ -95,7 +95,8 @@ trait TypeSimplifier { self: Typer => case ProvType(ty) => process(ty, parent, canDistribForall = canDistribForall) case tr @ TypeRef(defn, targs) if builtinTypes.contains(defn) && tr.canExpand => - process(tr.expandOrCrash, parent) + assert(tr.targs.isEmpty) + process(tr.expandOrCrash(true), parent) case RecordType(fields) => RecordType.mk(fields.flatMap { case (v @ Var(fnme), fty) => // * We make a pass to transform the LB and UB of variant type parameter fields into their extrema @@ -127,7 +128,7 @@ trait TypeSimplifier { self: Typer => else v -> default :: Nil } case S(trt: TypedNuTrt) => // TODO factor w/ above & generalize - trt.tparams.iterator.find(_._1.name === postfix).flatMap(_._3).getOrElse(VarianceInfo.in) match { + trt.tparams.iterator.find(_._1.name === postfix).flatMap(_._3.varinfo).getOrElse(VarianceInfo.in) match { case VarianceInfo(true, true) => Nil case VarianceInfo(co, contra) => if (co) v -> FieldType(S(BotType), process(fty.ub, N))(fty.prov) :: Nil @@ -223,7 +224,10 @@ trait TypeSimplifier { self: Typer => val trs2 = trs.map { case (d, tr @ TypeRef(defn, targs)) => - d -> TypeRef(defn, tr.mapTargs(pol)((pol, ta) => go(ta, pol)))(tr.prov) + d -> TypeRef(defn, tr.mapTargs2(pol)((pol, ta) => ta match { + case w@WildcardArg(lb, ub) => WildcardArg(go(lb, pol.map(!_)), go(ub, pol))(w.prov) + case st: ST => go(st, pol) + }))(tr.prov) } val traitPrefixes = @@ -248,8 +252,11 @@ trait TypeSimplifier { self: Typer => // * Reconstruct a TypeRef from its current structural components val typeRef = TypeRef(td.nme, td.tparamsargs.zipWithIndex.map { case ((tp, tv), tpidx) => - val fieldTagNme = tparamField(clsTyNme, tp) - val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { ta => FieldType(S(ta), ta)(noProv) }) + val fieldTagNme = tparamField(clsTyNme, tp, false) // `false` means using `C#A` (old def type member names) + val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { + case wc@WildcardArg(lb, ub) => FieldType(S(lb), ub)(wc.prov) + case ta: ST => FieldType(S(ta), ta)(noProv) + }) fromTyRef.++(rcd2.fields.iterator.filter(_._1 === fieldTagNme).map(_._2)) .foldLeft((BotType: ST, TopType: ST)) { case ((acc_lb, acc_ub), FieldType(lb, ub)) => @@ -257,40 +264,15 @@ trait TypeSimplifier { self: Typer => }.pipe { case (lb, ub) => vs(tv) match { - case VarianceInfo(true, true) => TypeBounds.mk(BotType, TopType) - case VarianceInfo(false, false) => - // * FIXME: this usage of type bounds is wrong! - // * We're here using it as though it meant a bounded wildcard, - // * for the purpose of type pretty-printing... - // * But this is inconsistent with other uses of these types as *absolute* type ranges! - TypeBounds.mk(lb, ub) - // * However, the fix is to make all TR arguments actual bounded wildcards - // * which is not easy as it requires extensive refactoring - // * - // * Note that the version below doesn't work because the refinement redundancy tests - // * below require non-polar types to compare against, so TypeBounds is inadequate. - /* - pol match { - case N => ??? - TypeBounds.mk(lb, ub) - case S(true) => - TypeBounds.mk(lb, ub) - case S(false) => - TypeBounds.mk(ub, lb) - } - */ - // * FIXME In fact, the use of such subtyping checks should render - // * all uses of TypeBounds produced by the simplifier inadequate! - // * We should find a proper solution to this at some point... - // * (Probably by only using proper wildcards in the type simplifier.) - case VarianceInfo(co, contra) => - if (co) ub else lb + case VarianceInfo(true, true) => WildcardArg.mk(BotType, TopType) + case VarianceInfo(false, false) => WildcardArg.mk(lb, ub) + case VarianceInfo(co, contra) => if (co) ub else lb } } })(noProv) println(s"typeRef ${typeRef}") - val clsFields = fieldsOf(typeRef.expandWith(paramTags = true, selfTy = false), paramTags = true) + val clsFields = fieldsOf(typeRef.expandWith(paramTags = true, selfTy = false, pol.getOrElse(die /* TODO */)), paramTags = true) println(s"clsFields ${clsFields.mkString(", ")}") val cleanPrefixes = ps.map(_.name.capitalize) + clsNme ++ traitPrefixes @@ -358,8 +340,11 @@ trait TypeSimplifier { self: Typer => // * Reconstruct a TypeRef from its current structural components val typeRef = TypeRef(cls.td.nme, cls.tparams.zipWithIndex.map { case ((tp, tv, vi), tpidx) => - val fieldTagNme = tparamField(clsTyNme, tp) - val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { ta => FieldType(S(ta), ta)(noProv) }) + val fieldTagNme = tparamField(clsTyNme, tp, vi.visible) + val fromTyRef = trs2.get(clsTyNme).map(_.targs(tpidx) |> { + case wc@WildcardArg(lb, ub) => FieldType(S(lb), ub)(wc.prov) + case ta: ST => FieldType(S(ta), ta)(noProv) + }) fromTyRef.++(rcd2.fields.iterator.filter(_._1 === fieldTagNme).map(_._2)) .foldLeft((BotType: ST, TopType: ST)) { case ((acc_lb, acc_ub), FieldType(lb, ub)) => @@ -367,16 +352,15 @@ trait TypeSimplifier { self: Typer => }.pipe { case (lb, ub) => cls.varianceOf(tv) match { - case VarianceInfo(true, true) => TypeBounds.mk(BotType, TopType) - case VarianceInfo(false, false) => TypeBounds.mk(lb, ub) - case VarianceInfo(co, contra) => - if (co) ub else lb + case VarianceInfo(true, true) => WildcardArg.mk(BotType, TopType) + case VarianceInfo(false, false) => WildcardArg.mk(lb, ub) + case VarianceInfo(co, contra) => if (co) ub else lb } } })(noProv) println(s"typeRef ${typeRef}") - val clsFields = fieldsOf(typeRef.expandWith(paramTags = true, selfTy = false), paramTags = true) + val clsFields = fieldsOf(typeRef.expandWith(paramTags = true, selfTy = false, pol = pol.getOrElse(die /* TODO */)), paramTags = true) println(s"clsFields ${clsFields.mkString(", ")}") val cleanPrefixes = ps.map(_.name.capitalize) + clsNme ++ traitPrefixes @@ -1056,7 +1040,10 @@ trait TypeSimplifier { self: Typer => RecordType(fs.mapValues(_.update(transform(_, pol.contravar, semp), transform(_, pol, semp))))(noProv))(noProv) case ProxyType(underlying) => transform(underlying, pol, parents, canDistribForall) case tr @ TypeRef(defn, targs) => - TypeRef(defn, tr.mapTargs(pol)((pol, ty) => transform(ty, pol, semp)))(tr.prov) + TypeRef(defn, tr.mapTargs2(pol)((pol, ty) => ty match { + case w@WildcardArg(lb, ub) => WildcardArg(transform(lb, pol.contravar, semp), transform(ub, pol.covar, semp))(w.prov) + case ty: ST => transform(ty, pol, semp) + }))(tr.prov) case wo @ Without(base, names) => if (names.isEmpty) transform(base, pol, semp, canDistribForall) else if (pol.base === S(true)) transform(base, pol, semp, canDistribForall).withoutPos(names) @@ -1233,7 +1220,12 @@ trait TypeSimplifier { self: Typer => case (ProxyType(underlying1), _) => unify(underlying1, ty2) case (_, ProxyType(underlying2)) => unify(ty1, underlying2) case (TypeRef(defn1, targs1), TypeRef(defn2, targs2)) => - (defn1 === defn2 || nope) && targs1.lazyZip(targs2).forall(unify) + (defn1 === defn2 || nope) && targs1.lazyZip(targs2).forall { + case (WildcardArg(l1, u1), WildcardArg(l2, u2)) => unify(l1, l2) && unify(u1, u2) + case (WildcardArg(l1, u1), ta2: ST) => nope // TODO correctly unify wildcard + case (ta1: ST, WildcardArg(l2, u2)) => nope // TODO correctly unify wildcard + case (ta1: ST, ta2: ST) => unify(ta1, ta2) + } case _ => nope } } diff --git a/shared/src/main/scala/mlscript/Typer.scala b/shared/src/main/scala/mlscript/Typer.scala index c3d03f82b5..93d1e6a849 100644 --- a/shared/src/main/scala/mlscript/Typer.scala +++ b/shared/src/main/scala/mlscript/Typer.scala @@ -46,6 +46,37 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne type GenLambdas >: Bool def doGenLambdas(implicit gl: GenLambdas): Bool = gl === true + + class ExtrCache( + val cache: MutMap[Level, MutMap[TypeVarOrRigidVar->Bool, TypeVarOrRigidVar]], + ) { + private var cycle: Int = 0 + // TODO maybe find a better way + def clearAbove()(implicit lvl: Level): Unit = + if (cycle > 1024) { + cache.keys.foreach(k => if (k > lvl) cache.remove(k)) + cycle = 0 + } + + def getOrElse(k: TypeVarOrRigidVar->Bool, df: => TypeVarOrRigidVar)(implicit lvl: Level): TypeVarOrRigidVar = + cache.get(lvl).flatMap(_.get(k)).getOrElse(df) + + def set(k: TypeVarOrRigidVar->Bool, v: TypeVarOrRigidVar)(implicit lvl: Level): Unit = { + cycle += 1 + cache.get(lvl) match { + case None => cache += lvl -> MutMap(k -> v) + case Some(cc) => cc += k -> v + } + clearAbove() // TODO + } + + def contains(k: TypeVarOrRigidVar->Bool)(implicit lvl: Level): Bool = + cache.get(lvl).map(_.contains(k)).getOrElse(false) + } + + object ExtrCache { + def empty: ExtrCache = new ExtrCache(MutMap.empty) + } /** `env`: maps the names of all global and local bindings to their types * Keys of `mthEnv`: @@ -70,6 +101,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne tyDefs2: MutMap[Str, DelayedTypeInfo], inRecursiveDef: Opt[Var], // TODO rm extrCtx: ExtrCtx, + extrCache: ExtrCache, ) { def +=(b: Str -> TypeInfo): Unit = { env += b @@ -210,7 +242,8 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne tyDefs = Map.from(builtinTypes.map(t => t.nme.name -> t)), tyDefs2 = MutMap.empty, inRecursiveDef = N, - MutSortMap.empty, + extrCtx = MutSortMap.empty, + extrCache = ExtrCache.empty ) def init: Ctx = if (!newDefs) initBase else { val res = initBase.copy( @@ -287,10 +320,11 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne "anything" -> TopType, "nothing" -> BotType) private val preludeLoc = Loc(0, 0, Origin("", 0, new FastParseHelpers(""))) + // private val DummyTV: TV = freshVar() val nuBuiltinTypes: Ls[NuTypeDef] = Ls( NuTypeDef(Cls, TN("Object"), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), - NuTypeDef(Trt, TN("Eql"), (S(VarianceInfo.contra), TN("A")) :: Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), + NuTypeDef(Trt, TN("Eql"), (TypeParamInfo(S(VarianceInfo.contra), false, N, N), TN("A")) :: Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), NuTypeDef(Cls, TN("Num"), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), NuTypeDef(Cls, TN("Int"), Nil, N, N, N, Var("Num") :: Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), NuTypeDef(Cls, TN("Bool"), Nil, N, N, S(Union(TN("true"), TN("false"))), Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), @@ -300,13 +334,13 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne NuTypeDef(Als, TN("undefined"), Nil, N, N, S(Literal(UnitLit(true))), Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), NuTypeDef(Als, TN("null"), Nil, N, N, S(Literal(UnitLit(false))), Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), NuTypeDef(Cls, TN("Annotation"), Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), - NuTypeDef(Cls, TN("Code"), (S(VarianceInfo.co) -> TN("T")) :: (S(VarianceInfo.co) -> TN("C")) :: Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), - NuTypeDef(Cls, TN("Var"), (S(VarianceInfo.in) -> TN("T")) :: (S(VarianceInfo.in) -> TN("C")) :: Nil, N, N, N, TyApp(Var("Code"), TN("T") :: TN("C") :: Nil) :: Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil) + NuTypeDef(Cls, TN("Code"), (TypeParamInfo(S(VarianceInfo.co), false, N, N) -> TN("T")) :: (TypeParamInfo(S(VarianceInfo.co), false, N, N) -> TN("C")) :: Nil, N, N, N, Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil), + NuTypeDef(Cls, TN("Var"), (TypeParamInfo(S(VarianceInfo.in), false, N, N) -> TN("T")) :: (TypeParamInfo(S(VarianceInfo.in), false, N, N) -> TN("C")) :: Nil, N, N, N, TyApp(Var("Code"), TN("T") :: TN("C") :: Nil) :: Nil, N, N, TypingUnit(Nil))(N, S(preludeLoc), Nil) // Not yet implemented, so we do not define it yet // NuTypeDef(Mod, TN("tailrec"), Nil, N, N, N, Var("Annotation") :: Nil, N, N, TypingUnit(Nil))(N, N, Nil), ) val builtinTypes: Ls[TypeDef] = - TypeDef(Cls, TN("?"), Nil, TopType, Nil, Nil, Set.empty, N, Nil) :: // * Dummy for pretty-printing unknown type locations + // TypeDef(Cls, TN("?"), Nil, TopType, Nil, Nil, Set.empty, N, Nil) :: // * Dummy for pretty-printing unknown type locations TypeDef(Cls, TN("int"), Nil, TopType, Nil, Nil, sing(TN("number")), N, Nil) :: TypeDef(Cls, TN("number"), Nil, TopType, Nil, Nil, semp, N, Nil) :: TypeDef(Cls, TN("bool"), Nil, TopType, Nil, Nil, semp, N, Nil) :: @@ -343,7 +377,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne val primitiveTypes: Set[Str] = builtinTypes.iterator.map(_.nme.name).flatMap(n => n.decapitalize :: n.capitalize :: Nil).toSet + "Object" + "Num" + "Str" - val reservedTypeNames: Set[Str] = primitiveTypes + "Eql" + val reservedTypeNames: Set[Str] = primitiveTypes + "Eql" + "?" def singleTup(ty: ST): ST = if (funkyTuples) ty else TupleType((N, ty.toUpper(ty.prov) ) :: Nil)(noProv) def pair(ty1: ST, ty2: ST): ST = @@ -486,7 +520,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne case Cls | Mod | Als | Trt => () case _ => err(msg"${k.str} ${nme} cannot be used as a type", loc); () } - def typeNamed(loc: Opt[Loc], name: Str): (() => ST) \/ (TypeDefKind, Int) = + def typeNamed(loc: Opt[Loc], name: Str, lift: Bool): (() => ST) \/ (TypeDefKind, Int) = newDefsInfo.get(name) .orElse(ctx.tyDefs.get(name).map(td => (td.kind, td.tparamsargs.size))) .orElse(ctx.get(name).flatMap { @@ -503,9 +537,24 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne case fd: NuFunDef => N } - case _ => N + case _ => + N }) - .toRight(() => err("type identifier not found: " + name, loc)(raise)) + .toRight(ctx.get(name) match { + case Some(VarSymbol(ty, vr)) => () => if (lift) { + println(s"ty var: $vr : $ty") // select type from variable + ty + } else err( + (msg"cannot lift variable $name to type" -> loc) :: + ty.prov.loco.toList.map(_ => (msg"as defined in" -> ty.prov.loco)) + )(raise) + case Some(CompletedTypeInfo(ty@TypedNuFun(_,_,_))) => () => if (lift) + ty.typeSignature + else err( + (msg"cannot lift expression $name to type" -> loc) :: + ty.toLoc.toList.map(_ => (msg"as defined in" -> ty.toLoc)) + )(raise) + case r => () => err(s"type identifier not found: " + name, loc)(raise) }) val localVars = mutable.Map.empty[TypeVar, TypeVariable] def tyTp(loco: Opt[Loc], desc: Str, originName: Opt[Str] = N) = TypeProvenance(loco, desc, originName, isType = true) @@ -575,11 +624,12 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } case tn @ TypeTag(name) => rec(TypeName(name.decapitalize)) // TODO rm this hack // case tn @ TypeTag(name) => rec(TypeName(name)) + case wc @ TypeName("?") => err(msg"Invalid use of wildcard type `?` here", wc.toLoc) case tn @ TypeName(name) => val tyLoc = ty.toLoc val tpr = tyTp(tyLoc, "type reference") vars.getOrElse(name, { - typeNamed(tyLoc, name) match { + typeNamed(tyLoc, name, true) match { case R((_, tpnum)) => if (tpnum === 0) TypeRef(tn, Nil)(tpr) else ctx.tyDefs2.get(name) match { @@ -597,7 +647,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } case L(e) => if (name.isEmpty || !name.head.isLower) e() - else (typeNamed(tyLoc, name.capitalize), ctx.tyDefs.get(name.capitalize)) match { + else (typeNamed(tyLoc, name.capitalize, false), ctx.tyDefs.get(name.capitalize)) match { case (R((kind, _)), S(td)) => kind match { case Cls => clsNameToNomTag(td)(tyTp(tyLoc, "class tag"), ctx) case Trt => trtNameToNomTag(td)(tyTp(tyLoc, "trait tag"), ctx) @@ -620,9 +670,15 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } case AppliedType(base, targs) => val prov = tyTp(ty.toLoc, "applied type reference") - typeNamed(ty.toLoc, base.name) match { + typeNamed(ty.toLoc, base.name, false) match { case R((_, tpnum)) => - val realTargs = if (targs.size === tpnum) targs.map(rec) else { + val realTargs = if (targs.size === tpnum) targs.map{ + case b@Bounds(lb, ub) if newDefs => WildcardArg(rec(lb), rec(ub))(tyTp(b.toLoc, "wildcard")) + case w@TypeName("?") if newDefs => + val prov: TypeProvenance = tyTp(w.toLoc, "wildcard") + WildcardArg(ExtrType(true)(prov), ExtrType(false)(prov))(prov) + case ty => rec(ty) + } else { err(msg"Wrong number of type arguments – expected ${tpnum.toString}, found ${ targs.size.toString}", ty.toLoc)(raise) (targs.iterator.map(rec) ++ Iterator.continually(freshVar(noProv, N))).take(tpnum).toList @@ -632,11 +688,18 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } case Selection(base, nme) => implicit val gl: GenLambdas = false - // val base_ty = typeTerm(base) val base_ty = rec(base) + def constrTB(ty: ST): TypeBounds = { + implicit val prov: TypeProvenance = tyTp(nme.toLoc, "type selection") + val lb = freshVar(prov, N, S(nme.name)) + val ub = freshVar(prov, N, S(nme.name)) + val res = RecordType.mk((nme.toVar, FieldType(S(lb), ub)(prov)) :: Nil)(prov) + println(s"Type selection : ${ty} <=< ${res}") + constrain(ty, res) + TypeBounds(lb, ub)(prov) + } def go(b_ty: ST, rfnt: Var => Opt[FieldType]): ST = b_ty.unwrapAll match { - case ct: TypeRef => die // TODO actually - case ClassTag(Var(clsNme), _) => + case ct@ClassTag(Var(clsNme), _) => // TODO we should still succeed even if the member is not completed... lookupMember(clsNme, rfnt, nme.toVar) match { case R(cls: TypedNuCls) => @@ -645,11 +708,9 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne case R(als: TypedNuAls) => if (als.tparams.nonEmpty) ??? // TODO als.body - case R(m) => err(msg"Illegal selection of ${m.kind.str} member in type position", nme.toLoc) - case L(d) => err(d) + case _ => constrTB(ct) // fallback } - case _ => - err(msg"Illegal prefix of type selection: ${b_ty.expPos}", base.toLoc) + case b_ty => constrTB(b_ty) } go(base_ty, _ => N) case Recursive(uv, body) => @@ -802,7 +863,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } // TODO also prevent rebinding of "not" - val reservedVarNames: Set[Str] = Set("|", "&", "~", "neg", "and", "or", "is") + val reservedVarNames: Set[Str] = Set("|", "&", "~", "neg", "and", "or", "is", "?") object ValidVar { def unapply(v: Var)(implicit raise: Raise): S[Str] = S { @@ -870,8 +931,8 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne * - we always generalize lambdas found in arguments, record/tuple fields, etc. */ def typeTerm(term: Term)(implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType], genLambdas: GenLambdas): SimpleType - = trace[ST](s"$lvl. Typing ${if (ctx.inPattern) "pattern" else "term"} $term") { - // = trace[ST](s"$lvl. Typing ${if (ctx.inPattern) "pattern" else "term"} $term ${extrCtx.map(_.size)}") { + = trace[ST](s"$lvl. Typing ${if (ctx.inPattern) "pattern" else "term"} ${term.showDbg}") { + // = trace[ST](s"$lvl. Typing ${if (ctx.inPattern) "pattern" else "term"} ${term.showDbg} ${extrCtx.map(_.size)}") { implicit val prov: TypeProvenance = ttp(term) def con(lhs: SimpleType, rhs: SimpleType, res: SimpleType)(implicit ctx: Ctx): SimpleType = { @@ -907,6 +968,9 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne case v @ Var("_") => if (ctx.inPattern || funkyTuples) freshVar(tp(v.toLoc, "wildcard"), N) else err(msg"Widlcard in expression position.", v.toLoc) + + case w @ Var("?") => + err(msg"Cannot use ? as expression", w.toLoc) case Ann(ann, receiver) => val annType = typeTerm(ann) @@ -923,6 +987,19 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne ty_ty } + case Asc(c @ CaseOf(s, cs), ty) => + // TODO hygiene: + // * Pushing the ascribed type inside the branch could lead to wrongly capturing pattern-bound variables. + // * In the future this won't happen, since we'll get properly uniqued names/symbols from pretyper. + typeTerm(CaseOf(s, cs.map(t => Asc(t, ty))).withLocOf(c)) + + case Asc(i @ If(ifb, els), ty) => + // TODO hygiene: like above + val i2 = If(ifb.map(t => Asc(t, ty)), els.map(t => Asc(t, ty))).withLocOf(i) + val res_ty = typeTerm(i2) + i.desugaredTerm = i2.desugaredTerm + res_ty + case Asc(trm, ty) => val trm_ty = typePolymorphicTerm(trm) val ty_ty = typeType(ty)(ctx.copy(inPattern = false), raise, vars) @@ -1343,6 +1420,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne else if (newDefs && !isrec) { // if (isrec) ??? val rhs_ty = typeTerm(rhs) + // val rhs_ty = typeMonomorphicTerm(rhs) val newCtx = ctx.nest newCtx += nme.name -> VarSymbol(rhs_ty, nme) typeTerm(bod)(newCtx, raise, vars, genLambdas) @@ -1384,7 +1462,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne (if (ctx.inQuote) ctx.enterQuotedScope else ctx) |> { implicit ctx => val s_ty = typeMonomorphicTerm(s) if (newDefs) con(s_ty, ObjType.withProv(prov), TopType) - val (tys, cs_ty) = typeArms(s |>? { + val (tys, cs_ty) = typeArms(s_ty, s |>? { case v: Var => v case Asc(v: Var, _) => v }, cs) @@ -1392,6 +1470,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne val req = tys.foldRight(BotType: SimpleType) { case ((a_ty, tv), req) => a_ty & tv | req & a_ty.neg() } + println(s"finishing case $s_ty <: $req") con(s_ty, req, cs_ty) } case elf: If => @@ -1595,7 +1674,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } }(r => s"$lvl. : ${r}") - def typeArms(scrutVar: Opt[Var], arms: CaseBranches) + def typeArms(s_ty: ST, scrutVar: Opt[Var], arms: CaseBranches) (implicit ctx: Ctx, raise: Raise, vars: Map[Str, SimpleType], genLambdas: GenLambdas) : Ls[SimpleType -> SimpleType] -> SimpleType = arms match { case NoCases => Nil -> BotType @@ -1613,11 +1692,11 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne solveQuoteContext(ctx, newCtx) res case Case(pat, bod, rest) => - val (tagTy, patTy) : (ST, ST) = pat match { + val (tagTy, patTy, patTyIntl) : (ST, ST, ST) = pat match { case lit: Lit => val t = ClassTag(lit, if (newDefs) lit.baseClassesNu else lit.baseClassesOld)(tp(pat.toLoc, "literal pattern")) - t -> t + (t, t, t) case v @ Var(nme) => val tpr = tp(pat.toLoc, "type pattern") ctx.tyDefs.get(nme) match { @@ -1633,30 +1712,35 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne val prov = tp(pat.toLoc, "class pattern") + def tprmToRcd(tparams: TyParams): (SimpleType, SimpleType) = { + val (flds, fldsIntl) = tparams.map { + case (tn, tv, vi) => + val nvLB = freshVar(tv.prov, S(tv), tv.nameHint) + val nvUB = freshVar(tv.prov, S(tv), tv.nameHint) + nvLB.upperBounds ::= nvUB + val sk = SkolemTag(freshVar(tv.prov, S(tv), tv.nameHint)(lvl + 1))(provTODO) + val v = Var(tparamField(nme, tn.name, vi.visible)).withLocOf(tn) + val vce = vi.varinfo.getOrElse(VarianceInfo.in) + (v, FieldType.mk(vce, nvLB, nvUB)(provTODO)) -> + (v, FieldType.mk(vce, nvLB | sk, nvUB & sk)(provTODO)) + }.unzip + (RecordType.mk(flds)(provTODO), RecordType.mk(fldsIntl)(provTODO)) + } + lti match { case dti: DelayedTypeInfo => - val tag = clsNameToNomTag(dti.decl match { case decl: NuTypeDef => decl; case _ => die })(prov, ctx) - val ty = - RecordType.mk(dti.tparams.map { - case (tn, tv, vi) => - val nv = freshVar(tv.prov, S(tv), tv.nameHint) - (Var(nme+"#"+tn.name).withLocOf(tn), - FieldType.mk(vi.getOrElse(VarianceInfo.in), nv, nv)(provTODO)) - })(provTODO) - println(s"Match arm $nme: $tag & $ty") - tag -> ty + val delc = dti.decl match { case decl: NuTypeDef => decl; case _ => die } + val tag = clsNameToNomTag(delc)(prov, ctx) + val (ty, tyIntl) = tprmToRcd(dti.tparams) + println(s"Match arm $nme: $tag & $ty intl $tyIntl") + (tag, ty, tyIntl) case CompletedTypeInfo(cls: TypedNuCls) => val tag = clsNameToNomTag(cls.td)(prov, ctx) - val ty = - RecordType.mk(cls.tparams.map { - case (tn, tv, vi) => - val nv = freshVar(tv.prov, S(tv), tv.nameHint) - (Var(nme+"#"+tn.name).withLocOf(tn), - FieldType.mk(vi.getOrElse(cls.varianceOf(tv)), nv, nv)(provTODO)) - })(provTODO) - println(s"Match arm $nme: $tag & $ty") - tag -> ty - case CompletedTypeInfo(_) => bail() + val (ty, tyIntl) = tprmToRcd(cls.tparams) + println(s"Match arm $nme: $tag & $ty intl $tyIntl") + (tag, ty, tyIntl) + case CompletedTypeInfo(_) => + die } case _ => @@ -1665,9 +1749,9 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } case Some(td) => td.kind match { - case Als | Mod | Mxn => val t = err(msg"can only match on classes and traits", pat.toLoc)(raise); t -> t - case Cls => val t = clsNameToNomTag(td)(tp(pat.toLoc, "class pattern"), ctx); t -> t - case Trt => val t = trtNameToNomTag(td)(tp(pat.toLoc, "trait pattern"), ctx); t -> t + case Als | Mod | Mxn => val t = err(msg"can only match on classes and traits", pat.toLoc)(raise); (t, t, t) + case Cls => val t = clsNameToNomTag(td)(tp(pat.toLoc, "class pattern"), ctx); (t, t, t) + case Trt => val t = trtNameToNomTag(td)(tp(pat.toLoc, "trait pattern"), ctx); (t, t, t) } } } @@ -1675,21 +1759,33 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne val (req_ty, bod_ty, (tys, rest_ty)) = scrutVar match { case S(v) => if (newDefs) { - newCtx += v.name -> VarSymbol(tagTy & patTy, v) - val bod_ty = typeTerm(bod)(newCtx, raise, vars, genLambdas) - (tagTy -> patTy, bod_ty, typeArms(scrutVar, rest)) - } else { + val res = freshVar(provTODO, N, N) + newCtx.copy(lvl = newCtx.lvl + 1) |> { implicit ctx => + val scrt = s_ty.unwrapProxies match { + case _ : TypeVariable => TopType + case scrt => scrt + } + println(s"var rfn: ${v.name} :: ${scrt} & ${tagTy} & ${patTyIntl}") + newCtx += v.name -> VarSymbol(scrt & tagTy & patTyIntl, v) + val bod_ty = typeTerm(bod)(ctx, raise, vars, genLambdas) + implicit val tp: TP = provTODO + constrain(bod_ty, res) + } + (tagTy -> patTy, res, typeArms(s_ty, scrutVar, rest)) + } else { // * oldDefs: val tv = freshVar(tp(v.toLoc, "refined scrutinee"), N, // S(v.name), // this one seems a bit excessive ) newCtx += v.name -> VarSymbol(tv, v) val bod_ty = typeTerm(bod)(newCtx, raise, vars, genLambdas) - (patTy -> tv, bod_ty, typeArms(scrutVar, rest)) + (patTy -> tv, bod_ty, typeArms(s_ty, scrutVar, rest)) } case N => + // TODO still do local reasoning here? val bod_ty = typeTerm(bod)(newCtx, raise, vars, genLambdas) - (tagTy -> TopType, bod_ty, typeArms(scrutVar, rest)) + (tagTy -> TopType, bod_ty, typeArms(s_ty, scrutVar, rest)) } + println(s"finishing branch: [$req_ty] + $tys and [$bod_ty] | $rest_ty") solveQuoteContext(ctx, newCtx) (req_ty :: tys) -> (bod_ty | rest_ty) } @@ -1857,7 +1953,7 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne } class ExpCtx(val tps: Map[TV, TN]) { - def apply(tparams: Ls[(TN, TV, Opt[VarianceInfo])]): ExpCtx = + def apply(tparams: Ls[(TN, TV, TypeParamInfo)]): ExpCtx = new ExpCtx(tps ++ tparams.iterator.map{case (tn, tv, vi) => tv -> tn}) } @@ -1996,7 +2092,8 @@ class Typer(var dbg: Boolean, var verbose: Bool, var explainErrors: Bool, val ne case TypeRef(td, Nil) => td case tr @ TypeRef(td, targs) => AppliedType(td, tr.mapTargs(S(true)) { case ta @ ((S(true), TopType) | (S(false), BotType)) => Bounds(Bot, Top) - case (_, ty) => go(ty) + case (_, WildcardArg(lb, ub)) => Bounds(go(lb), go(ub)) + case (_, ty: ST) => go(ty) }) case TypeBounds(lb, ub) => Bounds(go(lb), go(ub)) case Without(base, names) => Rem(go(base), names.toList) diff --git a/shared/src/main/scala/mlscript/TyperDatatypes.scala b/shared/src/main/scala/mlscript/TyperDatatypes.scala index 755ba9bfe0..b36eca7127 100644 --- a/shared/src/main/scala/mlscript/TyperDatatypes.scala +++ b/shared/src/main/scala/mlscript/TyperDatatypes.scala @@ -156,8 +156,56 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => def unapply(ot: OtherTypeLike): S[TypedTypingUnit] = S(ot.self) } + sealed trait SimpleTypeOrWildcard { + def prov: TypeProvenance + def level: Level + def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level + def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): SimpleTypeOrWildcard + + def <: ST, Bool] = MutMap.empty): Bool = + (this, that) match { case (l: ST, r: ST) => l <:< r ; case _ => false } + + // def &?(that: SimpleTypeOrWildcard): SimpleTypeOrWildcard = (this, that) match { + // case (l: WildcardArg, r: WildcardArg) => WildcardArg(l.lb | r.lb, l.ub & r.ub)(l.prov) + // case (l: WildcardArg, r: ST) => WildcardArg(l.lb | r, l.ub & r)(l.prov) + // case (l: ST, r: WildcardArg) => WildcardArg(r.lb | l, r.ub & l)(r.prov) + // case (l: ST, r: ST) => l & r + // } + + // def |?(that: SimpleTypeOrWildcard): SimpleTypeOrWildcard = (this, that) match { + // case (l: WildcardArg, r: WildcardArg) => WildcardArg(l.lb & r.lb, l.ub | r.ub)(l.prov) + // case (l: WildcardArg, r: ST) => WildcardArg(l.lb & r, l.ub | r)(l.prov) + // case (l: ST, r: WildcardArg) => WildcardArg(r.lb & l, r.ub | l)(r.prov) + // case (l: ST, r: ST) => l | r + // } + } + + // * As in `Foo[Nat..Int]` or `Foo[?]` which is syntax sugar for `Foo[nothing..anything]` + // TODO generate when finding Bounds in class type argument positions + // TODO treat specially in `def expand` to turn into proper TypeBounds: turn Foo[?] into #Foo & { A: Bot..Top } + // TODO separate this from the SimpleType hierarchy; make it a subtype of SimpleTypeOrWildcard + case class WildcardArg(lb: ST, ub: ST)(val prov: TP) extends SimpleTypeOrWildcard { + def level: Level = lb.level max ub.level + def levelBelow(ubnd: Level)(implicit cache: MutSet[TV]): Level = + lb.levelBelow(ubnd) max ub.levelBelow(ubnd) + override def toString: Str = s"? :> $lb <: $ub" + + def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): WildcardArg = + WildcardArg(lb.freshenAbove(lim,rigidify), ub.freshenAbove(lim,rigidify))(prov) + } + object WildcardArg { + def mk(lb: ST, ub: ST, prov: TP = noProv)(implicit ctx: Ctx): SimpleTypeOrWildcard = + if ((lb is ub) + || lb === ub + || !lb.mentionsTypeBounds && !ub.mentionsTypeBounds && lb <:< ub && ub <:< lb + ) lb else (lb, ub) match { + case _ => WildcardArg(lb, ub)(prov) + } + } + /** A general type form (TODO: rename to AnyType). */ - sealed abstract class SimpleType extends TypeLike with SimpleTypeImpl { + sealed abstract class SimpleType extends TypeLike with SimpleTypeImpl with SimpleTypeOrWildcard { val prov: TypeProvenance def level: Level def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level @@ -316,7 +364,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => elems.map{ case L(l) => l.levelBelow(ub) case R(r) => r.levelBelow(ub) }.max lazy val inner: FieldType = elems.map { - case L(l) => l match { case a: ArrayBase => a.inner case _ => ??? } + case L(l) => l match { case a: ArrayBase => a.inner case _ => die } case R(r) => r }.reduceLeft(_ || _) @@ -332,9 +380,9 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => override def toString = if (pol) "⊥" else "⊤" } - /** Represents a type variable skolem that was extruded outsdie its polym level. + /** Represents a type variable skolem that was extruded outside its polym level. * The goal is to retain precise information to produce good errors, - * but still have this be functionally equivalent to `ExtrType(pol)`. */ + * but still have this be functionally equivalent to `ExtrType(!pol)`. */ case class Extruded(pol: Bool, underlying: SkolemTag)(val prov: TypeProvenance, val reason: Ls[Ls[ST]]) extends AbstractTag with TypeVarOrRigidVar { val level: Level = MinLevel val id = underlying.id @@ -399,7 +447,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => type TR = TypeRef val TR: TypeRef.type = TypeRef - case class TypeRef(defn: TypeName, targs: Ls[SimpleType])(val prov: TypeProvenance) extends SimpleType with TypeRefImpl { + case class TypeRef(defn: TypeName, targs: Ls[SimpleTypeOrWildcard])(val prov: TypeProvenance) extends SimpleType with TypeRefImpl { def level: Level = targs.iterator.map(_.level).maxOption.getOrElse(MinLevel) def levelBelow(ub: Level)(implicit cache: MutSet[TV]): Level = targs.iterator.map(_.levelBelow(ub)).maxOption.getOrElse(MinLevel) override def freshenAbove(lim: Int, rigidify: Bool)(implicit ctx: Ctx, freshened: MutMap[TV, ST]): TypeRef = @@ -416,6 +464,8 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => def compare(that: TypeTag): Int = (this, that) match { case (obj1: ObjectTag, obj2: ObjectTag) => obj1.id compare obj2.id case (SkolemTag(id1), SkolemTag(id2)) => id1 compare id2 + case (Extruded(true, id1), Extruded(false, id2)) => -1 + case (Extruded(false, id1), Extruded(true, id2)) => 1 case (Extruded(_, id1), Extruded(_, id2)) => id1 compare id2 case (_: ObjectTag, _: SkolemTag | _: Extruded) => -1 case (_: SkolemTag | _: Extruded, _: ObjectTag) => 1 @@ -478,12 +528,12 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => override def toString = s"$lb..$ub" } object TypeBounds { - final def mkSimple(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv): SimpleType = (lb, ub) match { + def mkSimple(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv): SimpleType = (lb, ub) match { case (TypeBounds(lb, _), ub) => mkSimple(lb, ub, prov) case (lb, TypeBounds(_, ub)) => mkSimple(lb, ub, prov) case _ => TypeBounds(lb, ub)(prov) } - final def mk(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv)(implicit ctx: Ctx): SimpleType = + def mk(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv)(implicit ctx: Ctx): SimpleType = if ((lb is ub) || lb === ub || !lb.mentionsTypeBounds && !ub.mentionsTypeBounds && lb <:< ub && ub <:< lb @@ -495,7 +545,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => * (in particular, the `transform` function may replace TV bounds `TypeBound` bundles, * and creating these `TypeBound`s should NOT rely on the bounds still being there at the time * the bundle is constructed). */ - final def mkSafe(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv)(implicit ctx: Ctx): SimpleType = + def mkSafe(lb: SimpleType, ub: SimpleType, prov: TypeProvenance = noProv)(implicit ctx: Ctx): SimpleType = if ((lb is ub) || lb === ub ) lb else (lb, ub) match { @@ -555,7 +605,7 @@ abstract class TyperDatatypes extends TyperHelpers { Typer: Typer => private var _assignedTo: Opt[ST] = N def assignedTo: Opt[ST] = _assignedTo def assignedTo_=(value: Opt[ST]): Unit = { - require(value.forall(_.level <= level)) + require(value.forall(_.level <= level), (this, value)) _assignedTo = value } diff --git a/shared/src/main/scala/mlscript/TyperHelpers.scala b/shared/src/main/scala/mlscript/TyperHelpers.scala index e76d3a5a5b..9bccf738fe 100644 --- a/shared/src/main/scala/mlscript/TyperHelpers.scala +++ b/shared/src/main/scala/mlscript/TyperHelpers.scala @@ -344,7 +344,10 @@ abstract class TyperHelpers { Typer: Typer => case ProvType(underlying) => ProvType(f(underlying))(prov) case WithType(bse, rcd) => WithType(f(bse), RecordType(rcd.fields.mapValues(_.update(f, f)))(rcd.prov))(prov) case ProxyType(underlying) => f(underlying) // TODO different? - case TypeRef(defn, targs) => TypeRef(defn, targs.map(f(_)))(prov) + case TypeRef(defn, targs) => TypeRef(defn, targs.map { + case w@WildcardArg(lb, ub) => WildcardArg(f(lb), f(ub))(w.prov) + case st: ST => f(st) + })(prov) case PolymorphicType(plvl, und) => PolymorphicType(plvl, f(und)) case ConstrainedType(cs, bod) => ConstrainedType(cs.map(lu => f(lu._1) -> f(lu._2)), f(bod)) @@ -367,7 +370,10 @@ abstract class TyperHelpers { Typer: Typer => case ProvType(underlying) => ProvType(f(pol, underlying))(prov) case WithType(bse, rcd) => WithType(f(pol, bse), RecordType(rcd.fields.mapValues(_.update(f(pol.map(!_), _), f(pol, _))))(rcd.prov))(prov) case ProxyType(underlying) => f(pol, underlying) // TODO different? - case tr @ TypeRef(defn, targs) => TypeRef(defn, tr.mapTargs(pol)(f))(prov) + case tr @ TypeRef(defn, targs) => TypeRef(defn, tr.mapTargs2(pol)((pol, st) => st match { + case st: ST => f(pol, st) + case wc@WildcardArg(lb, ub) => WildcardArg(f(pol.map(!_), lb), f(pol, ub))(wc.prov) + }))(prov) case PolymorphicType(plvl, und) => if (smart) PolymorphicType.mk(plvl, f(pol, und)) else PolymorphicType(plvl, f(pol, und)) case ConstrainedType(cs, bod) => @@ -452,6 +458,11 @@ abstract class TyperHelpers { Typer: Typer => case _ => NegType(this)(prov) } + // def components(pol: Bool): Ls[ST] = unwrapProvs match { + // case ComposedType(`pol`, l, r) => l.components(pol) ++ r.components(pol) + // case _ => this :: Nil + // } + /** This is used to know when two types can be assumed to be mutual subtypes * based on a simple equality check. This may not hold when the types involve `TypeBound`s. * Indeed, say `type Foo[A] = A -> A`; @@ -552,9 +563,9 @@ abstract class TyperHelpers { Typer: Typer => case (_, NegType(und)) => (this & und) <:< BotType case (NegType(und), _) => TopType <:< (that | und) case (tr: TypeRef, _) - if (primitiveTypes contains tr.defn.name) && tr.canExpand => tr.expandOrCrash <:< that + if (primitiveTypes contains tr.defn.name) && tr.canExpand => tr.expandOrCrash(true) <:< that case (_, tr: TypeRef) - if (primitiveTypes contains tr.defn.name) && tr.canExpand => this <:< tr.expandOrCrash + if (primitiveTypes contains tr.defn.name) && tr.canExpand => this <:< tr.expandOrCrash(false) case (tr1: TypeRef, _) => ctx.tyDefs.get(tr1.defn.name) match { case S(td1) => that match { @@ -562,7 +573,7 @@ abstract class TyperHelpers { Typer: Typer => val tvv = td1.getVariancesOrDefault td1.tparamsargs.unzip._2.lazyZip(tr1.targs).lazyZip(tr2.targs).forall { (tv, targ1, targ2) => val v = tvv(tv) - (v.isContravariant || targ1 <:< targ2) && (v.isCovariant || targ2 <:< targ1) + (v.isContravariant || targ1 <: (td1.kind is Cls) && clsNameToNomTag(td1)(noProv, ctx) <:< that @@ -636,7 +647,7 @@ abstract class TyperHelpers { Typer: Typer => case ct: ConstrainedType => ct } def unwrapAll(implicit ctx: Ctx): SimpleType = unwrapProxies match { - case tr: TypeRef if tr.canExpand => tr.expandOrCrash.unwrapAll + case tr: TypeRef if tr.canExpand => tr.expandOrCrash(false).unwrapAll case u => u } def negNormPos(f: SimpleType => SimpleType, p: TypeProvenance) @@ -645,7 +656,7 @@ abstract class TyperHelpers { Typer: Typer => case ComposedType(true, l, r) => l.negNormPos(f, p) & r.negNormPos(f, p) case ComposedType(false, l, r) => l.negNormPos(f, p) | r.negNormPos(f, p) case NegType(n) => f(n).withProv(p) - case tr: TypeRef if !preserveTypeRefs && tr.canExpand => tr.expandOrCrash.negNormPos(f, p) + case tr: TypeRef if !preserveTypeRefs && tr.canExpand => tr.expandOrCrash(false).negNormPos(f, p) case _: RecordType | _: FunctionType => BotType // Only valid in positive positions! // Because Top<:{x:S}|{y:T}, any record type negation neg{x:S}<:{y:T} for any y=/=x, // meaning negated records are basically bottoms. @@ -720,7 +731,10 @@ abstract class TyperHelpers { Typer: Typer => // case _: TypeTag => Nil case _: ObjectTag | _: Extruded => Nil case SkolemTag(id) => pol -> id :: Nil - case tr: TypeRef => tr.mapTargs(pol)(_ -> _) + case tr: TypeRef => tr.mapTargs(pol) { + case (p, st: ST) => p -> st :: Nil + case (pol, WildcardArg(l, r)) => pol.map(!_) -> l :: pol -> r :: Nil + }.flatten case Without(b, ns) => pol -> b :: Nil case TypeBounds(lb, ub) => S(false) -> lb :: S(true) -> ub :: Nil case PolymorphicType(_, und) => pol -> und :: Nil @@ -806,7 +820,10 @@ abstract class TyperHelpers { Typer: Typer => // case _: TypeTag => Nil case _: ObjectTag | _: Extruded => Nil case SkolemTag(id) => pol -> id :: Nil - case tr: TypeRef => tr.mapTargs(pol)(_ -> _) + case tr: TypeRef => tr.mapTargs(pol) { + case (p, st: ST) => p -> st :: Nil + case (p, WildcardArg(l, r)) => pol.contravar -> l :: pol.covar -> r :: Nil + }.flatten case Without(b, ns) => pol -> b :: Nil case TypeBounds(lb, ub) => PolMap.neg -> lb :: PolMap.pos -> ub :: Nil case PolymorphicType(_, und) => pol -> und :: Nil @@ -962,7 +979,7 @@ abstract class TyperHelpers { Typer: Typer => // case _: TypeTag => Nil case _: ObjectTag | _: Extruded => Nil case SkolemTag(id) => id :: Nil - case TypeRef(d, ts) => ts + case TypeRef(d, ts) => ts flatMap { case st: ST => st :: Nil ; case WildcardArg(lb, ub) => lb :: ub :: Nil } case Without(b, ns) => b :: Nil case TypeBounds(lb, ub) => lb :: ub :: Nil case PolymorphicType(_, und) => und :: Nil @@ -1050,7 +1067,7 @@ abstract class TyperHelpers { Typer: Typer => println(s" where: ${res.showBounds}") if (cannotBeDistribbed.isEmpty) S(res) else S(PolymorphicType(polymLevel, res)) - case tr: TypeRef if !traversed.contains(tr.defn) => go(tr.expand, traversed + tr.defn, polymLevel) + case tr: TypeRef if !traversed.contains(tr.defn) => go(tr.expand(false), traversed + tr.defn, polymLevel) case proxy: ProxyType => go(proxy.underlying, traversed, polymLevel) case tv @ AssignedVariable(ty) if !traversed.contains(tv) => go(ty, traversed + tv, polymLevel) @@ -1075,7 +1092,8 @@ abstract class TyperHelpers { Typer: Typer => // * Object types do not need to be completed in order to be expanded info.kind.isInstanceOf[ObjDefKind] || info.isComputed) - def expand(implicit ctx: Ctx, raise: Raise): SimpleType = { + + def expand(pol: Bool)(implicit ctx: Ctx, raise: Raise): SimpleType = { ctx.tyDefs2.get(defn.name) match { case S(info) => if (!info.kind.isInstanceOf[ObjDefKind]) { @@ -1085,30 +1103,37 @@ abstract class TyperHelpers { Typer: Typer => } case N => } - expandWith(paramTags = true, selfTy = true) + expandWith(paramTags = true, selfTy = true, pol = pol) } - def expandOrCrash(implicit ctx: Ctx): SimpleType = { + def expandOrCrash(pol: Bool)(implicit ctx: Ctx): SimpleType = { require(canExpand) - expandWith(paramTags = true, selfTy = true) + expandWith(paramTags = true, selfTy = true, pol = pol) } - def expandWith(paramTags: Bool, selfTy: Bool)(implicit ctx: Ctx): SimpleType = + def expandWith(paramTags: Bool, selfTy: Bool, pol: Bool)(implicit ctx: Ctx): SimpleType = ctx.tyDefs2.get(defn.name).map { info => lazy val mkTparamRcd = RecordType(info.tparams.lazyZip(targs).map { case ((tn, tv, vi), ta) => - val fldNme = defn.name + "#" + tn.name - // TODO also use computed variance info when available! - Var(fldNme).withLocOf(tn) -> FieldType.mk(vi.getOrElse(VarianceInfo.in), ta, ta)(provTODO) + val fldNme = tparamField(defn.name, tn.name, vi.visible) + val fld = ta match { + case w@WildcardArg(lb, ub) => FieldType(S(lb), ub)(w.prov) + case ta: ST => FieldType.mk(vi.varinfo.getOrElse(VarianceInfo.in), ta, ta)(ta.prov) + } + Var(fldNme).withLocOf(tn) -> fld })(provTODO) info.result match { case S(td: TypedNuAls) => assert(td.tparams.size === targs.size) subst(td.body, td.tparams.lazyZip(targs).map { - case (tp, ta) => SkolemTag(tp._2)(noProv) -> ta + case (tp, w: WildcardArg) => + // SkolemTag(tp._2)(noProv) -> TypeBounds(w.lb, w.ub)(w.prov) + // ??? // TODO raise proper error + lastWords("Type aliases cannot use wildcard type arguments: " + this) + case (tp, st: ST) => SkolemTag(tp._2)(noProv) -> st }.toMap) case S(td: TypedNuTrt) => assert(td.tparams.size === targs.size) // println(s"EXP ${td.sign}") - val (freshenMap, _) = refreshHelper2(td, Var(td.name).withLoc(prov.loco), S(targs)) // infer ty args if not provided + val (freshenMap, _) = refreshHelper2(td, Var(td.name).withLoc(prov.loco), S(targs), pol) // infer ty args if not provided val freshSelf = if (!selfTy) TopType else { implicit val freshened: MutMap[TV, ST] = freshenMap implicit val shadows: Shadows = Shadows.empty @@ -1120,7 +1145,7 @@ abstract class TyperHelpers { Typer: Typer => mkTparamRcd case S(td: TypedNuCls) => assert(td.tparams.size === targs.size) - val (freshenMap, _) = refreshHelper2(td, Var(td.name).withLoc(prov.loco), S(targs)) // infer ty args if not provided + val (freshenMap, _) = refreshHelper2(td, Var(td.name).withLoc(prov.loco), S(targs), pol) // infer ty args if not provided val freshSelf = if (!selfTy) TopType else { implicit val freshened: MutMap[TV, ST] = freshenMap implicit val shadows: Shadows = Shadows.empty @@ -1155,7 +1180,8 @@ abstract class TyperHelpers { Typer: Typer => lazy val tparamTags = if (paramTags) RecordType.mk(td.tparamsargs.map { case (tp, tv) => val tvv = td.getVariancesOrDefault - tparamField(defn, tp) -> FieldType( + // `false` means using `C#A` (old type member names) + tparamField(defn, tp, false) -> FieldType( Some(if (tvv(tv).isCovariant) BotType else tv), if (tvv(tv).isContravariant) TopType else tv)(prov) })(noProv) @@ -1166,7 +1192,10 @@ abstract class TyperHelpers { Typer: Typer => case Cls => clsNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags case Trt => trtNameToNomTag(td)(prov, ctx) & td.bodyTy & tparamTags case Mxn => lastWords("mixins cannot be used as types") - }, td.targs.lazyZip(targs).toMap) //.withProv(prov) + }, td.targs.lazyZip(targs.map{ + case w: WildcardArg => TypeBounds(w.lb, w.ub)(w.prov) // * old defs + case st: ST => st + }).toMap[ST, ST]) // * old defs to make things compiler //.withProv(prov) } //tap { res => println(s"Expand $this => $res") } private var tag: Opt[Opt[ClassTag]] = N def expansionFallback(implicit ctx: Ctx): Opt[ST] = mkClsTag @@ -1197,7 +1226,7 @@ abstract class TyperHelpers { Typer: Typer => tag = S(res) res } - def mapTargs[R](pol: Opt[Bool])(f: (Opt[Bool], ST) => R)(implicit ctx: Ctx): Ls[R] = { + def mapTargs[R](pol: Opt[Bool])(f: (Opt[Bool], SimpleTypeOrWildcard) => R)(implicit ctx: Ctx): Ls[R] = { // TODO factor w/ below val (tvarVariances, tparamsargs) = ctx.tyDefs.get(defn.name) match { case S(td) => @@ -1211,14 +1240,50 @@ abstract class TyperHelpers { Typer: Typer => (tparamsargs lazyZip targs).map { case ((_, tv), ta) => tvv(tv) match { case VarianceInfo(true, true) => - f(N, TypeBounds(BotType, TopType)(noProv)) + f(N, WildcardArg(BotType, TopType)(noProv)) case VarianceInfo(co, contra) => - f(if (co) pol else if (contra) pol.map(!_) else N, ta) + // f(if (co) pol else if (contra) pol.map(!_) else N, ta) + ta match { + case wa @ WildcardArg(l, b) => // TODO improve (needs refactoring...) + f(pol, wa) + case _ => + f(if (co) pol else if (contra) pol.map(!_) else N, ta) + } } }} } + def mapTargs2(pol: Opt[Bool])(f: (Opt[Bool], SimpleTypeOrWildcard) => SimpleTypeOrWildcard)(implicit ctx: Ctx): Ls[SimpleTypeOrWildcard] = { + // TODO factor w/ below + val (tvarVariances, tparamsargs) = ctx.tyDefs.get(defn.name) match { + case S(td) => + (td.tvarVariances, td.tparamsargs) + case N => + val td = ctx.tyDefs2(defn.name) + (N, td.tparams.map(tp => (tp._1, tp._2))) + } + val tvv = tvarVariances.getOrElse(VarianceStore.empty.withDefaultValue(VarianceInfo.in)) + assert(tparamsargs.sizeCompare(targs) === 0) + (tparamsargs lazyZip targs).map { case ((_, tv), ta) => + tvv(tv) match { + case VarianceInfo(true, true) => (f(pol.map(!_), BotType), f(pol, TopType)) match { + case (lb: ST, ub: ST) => WildcardArg(lb, ub)(noProv) + case _ => ??? + } + case VarianceInfo(co, contra) => + ta match { + case wa @ WildcardArg(l, b) => // TODO improve (needs refactoring...) + (f(pol.map(!_), l), f(pol, b)) match { + case (lb: ST, ub: ST) => WildcardArg(lb, ub)(wa.prov) + case _ => ??? + } + case _ => + f(if (co) pol else if (contra) pol.map(!_) else N, ta) + } + } + } + } // TODO dedup w/ above - def mapTargs[R](pol: PolMap)(f: (PolMap, ST) => R)(implicit ctx: Ctx): Ls[R] = { + def mapTargs[R](pol: PolMap)(f: (PolMap, SimpleTypeOrWildcard) => R)(implicit ctx: Ctx): Ls[R] = { val (tvarVariances, tparamsargs) = ctx.tyDefs.get(defn.name) match { case S(td) => (td.tvarVariances, td.tparamsargs) @@ -1237,12 +1302,54 @@ abstract class TyperHelpers { Typer: Typer => (tparamsargs lazyZip targs).map { case ((_, tv), ta) => tvv(tv) match { case VarianceInfo(true, true) => - f(pol.invar, TypeBounds(BotType, TopType)(noProv)) + f(pol.invar, WildcardArg(BotType, TopType)(noProv)) case VarianceInfo(co, contra) => - f(if (co) pol else if (contra) pol.contravar else pol.invar, ta) + // f(if (co) pol else if (contra) pol.contravar else pol.invar, ta) + ta match { + case wa @ WildcardArg(l, b) => // TODO improve (needs refactoring...) + f(pol, wa) + case _ => + f(if (co) pol else if (contra) pol.contravar else pol.invar, ta) + } } }} } + // TODO dedup w/ above + def mapTargs2(pol: PolMap)(f: (PolMap, SimpleTypeOrWildcard) => SimpleTypeOrWildcard)(implicit ctx: Ctx): Ls[SimpleTypeOrWildcard] = { + val (tvarVariances, tparamsargs) = ctx.tyDefs.get(defn.name) match { + case S(td) => + (td.tvarVariances, td.tparamsargs) + case N => + val td = ctx.tyDefs2.getOrElse(defn.name, + // * This should only happen in the presence of ill-formed type definitions; + // * TODO: Make sure to report this and raise a compiler internal error if the source + // * does not actually have a type error! Otherwise we could silently get wrong results... + return Nil + ) + // TODO use computed varces + (some(td.explicitVariances), td.tparams.map(tp => (tp._1, tp._2))) + } + val tvv = tvarVariances.getOrElse(VarianceStore.empty.withDefaultValue(VarianceInfo.in)) + assert(tparamsargs.sizeCompare(targs) === 0) + (tparamsargs lazyZip targs).map { case ((_, tv), ta) => + tvv(tv) match { + case VarianceInfo(true, true) => (f(pol.contravar, BotType), f(pol, TopType)) match { + case (lb: ST, ub: ST) => WildcardArg(lb, ub)(noProv) + case _ => ??? + } + case VarianceInfo(co, contra) => + ta match { + case wa @ WildcardArg(l, b) => // TODO improve (needs refactoring...) + (f(pol.contravar, l), f(pol.covar, b)) match { + case (lb: ST, ub: ST) => WildcardArg(lb, ub)(wa.prov) + case _ => ??? + } + case _ => + f(if (co) pol else if (contra) pol.contravar else pol.invar, ta) + } + } + } + } } @@ -1253,7 +1360,7 @@ abstract class TyperHelpers { Typer: Typer => class Traverser(implicit ctx: Ctx) { - def apply(pol: Opt[Bool])(st: ST): Unit = st match { + def apply(pol: Opt[Bool])(st: SimpleTypeOrWildcard): Unit = st match { case tv @ AssignedVariable(ty) => apply(pol)(ty) case tv: TypeVariable => if (pol =/= S(false)) tv.lowerBounds.foreach(apply(S(true))) @@ -1275,6 +1382,7 @@ abstract class TyperHelpers { Typer: Typer => case TypeBounds(lb, ub) => if (pol =/= S(true)) apply(S(false))(lb) if (pol =/= S(false)) apply(S(true))(ub) + case WildcardArg(lb, ub) => apply(pol.map(!_))(lb); apply(pol)(ub) case PolymorphicType(plvl, und) => apply(pol)(und) case ConstrainedType(cs, bod) => cs.foreach { @@ -1352,7 +1460,10 @@ abstract class TyperHelpers { Typer: Typer => // case _: TypeTag => () case _: ObjectTag | _: Extruded => () case SkolemTag(id) => apply(pol)(id) - case tr: TypeRef => tr.mapTargs(pol)(apply(_)(_)); () + case tr: TypeRef => tr.mapTargs(pol){(pol, t) => t match { + case WildcardArg(lb, ub) => apply(pol.contravar)(lb); apply(pol)(ub) + case st: ST => apply(pol)(st) + }}; () case Without(b, ns) => apply(pol)(b) case TypeBounds(lb, ub) => pol.traverseRange(lb, ub)(apply(_)(_)) case PolymorphicType(plvl, und) => apply(pol.enter(plvl))(und) @@ -1383,7 +1494,7 @@ abstract class TyperHelpers { Typer: Typer => def go(ty: ST, traversed: Set[AnyRef]): Opt[PolymorphicType] = //trace(s"go $ty") { if (!distributeForalls) N else ty match { case poly @ PolymorphicType(plvl, bod) => S(poly) - case tr: TypeRef if !traversed.contains(tr.defn) => go(tr.expand, traversed + tr.defn) + case tr: TypeRef if !traversed.contains(tr.defn) => go(tr.expand(false), traversed + tr.defn) case proxy: ProxyType => go(proxy.underlying, traversed) case tv @ AssignedVariable(ty) if !traversed.contains(tv) => go(ty, traversed + tv) @@ -1405,7 +1516,7 @@ abstract class TyperHelpers { Typer: Typer => object AliasOf { def unapply(ty: ST)(implicit ctx: Ctx): S[ST] = { def go(ty: ST, traversedVars: Set[TV]): S[ST] = ty match { - case tr: TypeRef if tr.canExpand => go(tr.expandOrCrash, traversedVars) + case tr: TypeRef if tr.canExpand => go(tr.expandOrCrash(false), traversedVars) case proxy: ProxyType => go(proxy.underlying, traversedVars) case tv @ AssignedVariable(ty) if !traversedVars.contains(tv) => go(ty, traversedVars + tv) diff --git a/shared/src/main/scala/mlscript/helpers.scala b/shared/src/main/scala/mlscript/helpers.scala index 92cb588759..bb30152bcd 100644 --- a/shared/src/main/scala/mlscript/helpers.scala +++ b/shared/src/main/scala/mlscript/helpers.scala @@ -744,6 +744,8 @@ trait TermImpl extends StatementImpl { self: Term => case ty @ App(v @ Var("\\"), PlainTup(lhs, rhs)) => Inter(lhs.toType_!, Neg(rhs.toType_!).withLoc(Loc(v :: rhs :: Nil))).withLoc(ty.toCoveringLoc) case App(Var("~"), rhs) => Neg(rhs.toType_!) + case App(Var(".."), PlainTup(lhs, rhs)) => + Bounds(lhs.toType_!, rhs.toType_!) case Lam(lhs, rhs) => Function(lhs.toType_!, rhs.toType_!) case App(lhs, PlainTup(fs @ _*)) => lhs.toType_! match { @@ -1174,6 +1176,12 @@ trait CaseBranchesImpl extends Located { self: CaseBranches => case NoCases => "" } + def map(f: Term => Term): CaseBranches = this match { + case Case(pat, body, rest) => Case(pat, f(body), rest.map(f)) + case Wildcard(b) => Wildcard(f(b)) + case NoCases => this + } + def showIn(implicit ctx: ShowCtx): Str = this match { case Case(pat, body, rest) => ctx.lnIndStr + pat.showIn(false) + " => " + body.showIn(false) + rest.showIn @@ -1207,6 +1215,19 @@ trait IfBodyImpl extends Located { self: IfBody => case IfOpsApp(lhs, ops) => s"${lhs.showDbg} ‹${ops.iterator.map{case(v, r) => s"· ${v.showDbg} ${r.showDbg}"}.mkString("; ")}›" case IfLet(isRec, v, r, b) => s"${if (isRec) "rec " else ""}let ${v.showDbg} = ${r.showDbg} in ${b.showDbg}" } + + def map(f: Term => Term): IfBody = this match { + case IfThen(expr, rhs) => IfThen(expr, f(rhs)) + case IfElse(expr) => IfElse(f(expr)) + case IfLet(isRec, name, rhs, body) => IfLet(isRec, name, rhs, body.map(f)) + case IfOpApp(lhs, op, rhs) => IfOpApp(lhs, op, rhs.map(f)) + case IfOpsApp(lhs, opsRhss) => IfOpsApp(lhs, opsRhss.map(_.mapSecond(_.map(f)))) + case IfBlock(lines) => IfBlock(lines.map { + case Left(ifb) => Left(ifb.map(f)) + case r: Right[_, _] => r + }) + } + def showIn(implicit ctx: ShowCtx): Str = this match { case IfThen(lhs, rhs) => s"${lhs.showIn(!lhs.isInstanceOf[SimpleTerm])} then ${rhs.showIn(false)}" diff --git a/shared/src/main/scala/mlscript/syntax.scala b/shared/src/main/scala/mlscript/syntax.scala index eb6005b2b6..5702184aa9 100644 --- a/shared/src/main/scala/mlscript/syntax.scala +++ b/shared/src/main/scala/mlscript/syntax.scala @@ -157,7 +157,7 @@ final case class AppliedType(base: TypeName, targs: List[Type]) extends Type wit final case class Selection(base: Type, name: TypeName) extends Type final case class Neg(base: Type) extends Type final case class Rem(base: Type, names: Ls[Var]) extends Type -final case class Bounds(lb: Type, ub: Type) extends Type +final case class Bounds(lb: Type, ub: Type) extends Type // TODO repurpose to use as wildcard type arg final case class WithExtension(base: Type, rcd: Record) extends Type final case class Splice(fields: Ls[Either[Type, Field]]) extends Type final case class Constrained(base: TypeLike, tvBounds: Ls[TypeVar -> Bounds], where: Ls[Bounds]) extends Type @@ -201,7 +201,7 @@ sealed trait Outer { def kind: OuterKind } final case class NuTypeDef( kind: TypeDefKind, nme: TypeName, - tparams: Ls[(Opt[VarianceInfo], TypeName)], + tparams: Ls[(TypeParamInfo, TypeName)], params: Opt[Tup], // the specialized parameters for that type ctor: Opt[Constructor], sig: Opt[Type], @@ -248,7 +248,8 @@ final case class NuFunDef( final case class Constructor(params: Tup, body: Blk) extends DesugaredStatement with ConstructorImpl // constructor(...) { ... } - +// TODO lb and ub not handled in typing +final case class TypeParamInfo(varinfo: Opt[VarianceInfo], visible: Bool, lb: Opt[TypeName], ub: Opt[TypeName]) final case class VarianceInfo(isCovariant: Bool, isContravariant: Bool) { diff --git a/shared/src/main/scala/mlscript/ucs/Desugarer.scala b/shared/src/main/scala/mlscript/ucs/Desugarer.scala index 5afc766ddb..ff82ed102f 100644 --- a/shared/src/main/scala/mlscript/ucs/Desugarer.scala +++ b/shared/src/main/scala/mlscript/ucs/Desugarer.scala @@ -192,6 +192,10 @@ class Desugarer extends TypeDefs { self: Typer => Clause.MatchAny(scrutinee)(wildcard.toLoc.toList) :: Nil // If it's not top-level, wildcard means we don't care. case Var("_") => Nil + // We cannot use wildcard (type) for patterns + case wc @ Var("?") => throw new DesugaringException({ + msg"Cannot match on wildcard ?" + }, wc.toLoc) // This case handles literals. // x is true | x is false | x is 0 | x is "text" | ... case literal: Var if literal.name === "true" || literal.name === "false" => @@ -808,7 +812,32 @@ class Desugarer extends TypeDefs { self: Typer => case _ => visited.put(field, alias) } } - + /* + val als = extraAlias.toList + assert(fields.size === als.size) + + (fields, als).zip/* .distinctBy(_._1) */.flatMap { + case (_ -> Var("_"), _) => + case (_ -> Var(alias), _) => + + } + */ + + // /* + Let(false, Var("$unapp"), App(Sel(className, Var(unapplyMtd.name)), PlainTup(scrutinee.reference)), + // Let(false, Var("$tmp"), Sel(Var("$unapp"), Var("0")), + fields.distinctBy(_._1).zipWithIndex.foldRight( + extraAlias.toList.foldRight(consequent)((lt, rs) => Let(false, Var(lt._2), Var(lt._1), rs)) + )((field, rs) => { + val (_ -> Var(alias), index) = field + if (alias === "_") rs + else + Let(false, Var(alias), Sel(Var("$unapp"), Var(index.toString)), rs) + }) + ) + // */ + + /* App(Lam(Tup( N -> Fld(FldFlags.empty, Tup( fields.distinctBy(_._1).map { @@ -822,6 +851,11 @@ class Desugarer extends TypeDefs { self: Typer => Tup(N -> Fld(FldFlags.empty, scrutinee.reference) :: Nil)) ) :: Nil) ) + */ + + // ) + // ) + case _ => mkLetFromFields(scrutinee, fields.filter(_._2.name =/= "_").toList, consequent) } Case(className, body, rec2(next)) diff --git a/shared/src/test/diff/basics/Simplesub1.fun b/shared/src/test/diff/basics/Simplesub1.fun index 5024417967..628ab239ca 100644 --- a/shared/src/test/diff/basics/Simplesub1.fun +++ b/shared/src/test/diff/basics/Simplesub1.fun @@ -220,14 +220,14 @@ x => {l: x x, r: x } //│ ║ l.+1: (f => (x => f (v => (x x) v)) (x => f (v => (x x) v))) (f => x => f) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╙── Note: use flag `:ex` to see internal error info. -//│ res: error | anything -> anything -> anything -> 'a +//│ res: error | 'a //│ where -//│ 'a :> forall 'a. anything -> 'a +//│ 'a :> anything -> 'a res 1 2 -//│ res: error | anything -> 'a +//│ res: error | 'a //│ where -//│ 'a :> forall 'a. anything -> 'a +//│ 'a :> anything -> 'a let rec trutru = g => trutru (g true) diff --git a/shared/src/test/diff/codegen/AuxiliaryConstructors.mls b/shared/src/test/diff/codegen/AuxiliaryConstructors.mls index 36b8a2c8fc..ac695bcccc 100644 --- a/shared/src/test/diff/codegen/AuxiliaryConstructors.mls +++ b/shared/src/test/diff/codegen/AuxiliaryConstructors.mls @@ -318,7 +318,7 @@ fun f(c) = //│ globalThis.f = function f(c) { //│ return ((() => { //│ let a; -//│ return a = c, a instanceof F.class ? (([x]) => x)(F.unapply(c)) : a instanceof G ? 2 : 0; +//│ return a = c, a instanceof F.class ? (($unapp) => ((x) => x)($unapp[0]))(F.unapply(c)) : a instanceof G ? 2 : 0; //│ })()); //│ }; //│ // End of generated code @@ -512,7 +512,7 @@ let hh = h(1) :e new hh(1) -//│ ╔══[ERROR] type identifier not found: hh +//│ ╔══[ERROR] Unexpected type `?a` after `new` keyword //│ ║ l.514: new hh(1) //│ ╙── ^^ //│ error diff --git a/shared/src/test/diff/codegen/FieldOverride.mls b/shared/src/test/diff/codegen/FieldOverride.mls index 0fb2afb424..10f51db49b 100644 --- a/shared/src/test/diff/codegen/FieldOverride.mls +++ b/shared/src/test/diff/codegen/FieldOverride.mls @@ -128,7 +128,7 @@ let c3 = C3(1) let c4 = c3.C4(2) c3.a c4.a -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member C4 not yet supported //│ ║ l.128: let c4 = c3.C4(2) //│ ╙── ^^^ //│ let c3: C3 diff --git a/shared/src/test/diff/codegen/IndirectRecursion.mls b/shared/src/test/diff/codegen/IndirectRecursion.mls index 0b431e1dfa..4b1f168c73 100644 --- a/shared/src/test/diff/codegen/IndirectRecursion.mls +++ b/shared/src/test/diff/codegen/IndirectRecursion.mls @@ -138,8 +138,8 @@ def z = (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v))!) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> 'a -> ? -//│ <: 'a -> ? -> ? +//│ 'a :> 'a -> #? +//│ <: 'a -> #? -> #? //│ ╙── //│ (('a -> 'b) -> 'c & ('d -> 'e) -> ('d -> 'e & 'a -> 'b)) -> 'c //│ <: z: @@ -166,8 +166,8 @@ def z = (fun f -> (fun x -> f (fun v -> (x x) v)) (fun x -> f (fun v -> (x x) v))!) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> 'a -> ? -//│ <: 'a -> ? -> ? +//│ 'a :> 'a -> #? +//│ <: 'a -> #? -> #? //│ ╙── //│ (('a -> 'b) -> 'c & ('d -> 'e) -> ('d -> 'e & 'a -> 'b)) -> 'c //│ <: z: diff --git a/shared/src/test/diff/codegen/Mixin.mls b/shared/src/test/diff/codegen/Mixin.mls index 9179f28b54..609f2adfcc 100644 --- a/shared/src/test/diff/codegen/Mixin.mls +++ b/shared/src/test/diff/codegen/Mixin.mls @@ -70,8 +70,8 @@ mixin EvalBase { Add(l, r) then this.eval(l) + this.eval(r) } //│ mixin EvalBase() { -//│ this: {eval: 'a -> Int} -//│ fun eval: (Add['a] | Lit) -> Int +//│ this: {eval: (??E & 'E) -> Int} +//│ fun eval: (Add['E] | Lit) -> Int //│ } //│ // Prelude //│ class TypingUnit1 { @@ -87,10 +87,7 @@ mixin EvalBase { //│ const qualifier1 = this; //│ return ((() => { //│ let a; -//│ return (a = e, a instanceof Lit.class ? (([n]) => n)(Lit.unapply(e)) : a instanceof Add.class ? (([ -//│ l, -//│ r -//│ ]) => qualifier1.eval(l) + qualifier1.eval(r))(Add.unapply(e)) : (() => { +//│ return (a = e, a instanceof Lit.class ? (($unapp) => ((n) => n)($unapp[0]))(Lit.unapply(e)) : a instanceof Add.class ? (($unapp) => ((l) => ((r) => qualifier1.eval(l) + qualifier1.eval(r))($unapp[1]))($unapp[0]))(Add.unapply(e)) : (() => { //│ throw new Error("non-exhaustive case expression"); //│ })()); //│ })()); @@ -142,8 +139,8 @@ mixin EvalNeg { } //│ mixin EvalNeg() { //│ super: {eval: 'a -> 'b} -//│ this: {eval: 'c -> Int} -//│ fun eval: (Neg['c] | Object & 'a & ~#Neg) -> (Int | 'b) +//│ this: {eval: (??A & 'A) -> Int} +//│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> (Int | 'b) //│ } //│ // Prelude //│ class TypingUnit3 { @@ -158,7 +155,7 @@ mixin EvalNeg { //│ eval(e) { //│ const qualifier1 = this; //│ return ((() => { -//│ return e instanceof Neg.class ? (([d]) => 0 - qualifier1.eval(d))(Neg.unapply(e)) : super.eval(e); +//│ return e instanceof Neg.class ? (($unapp) => ((d) => 0 - qualifier1.eval(d))($unapp[0]))(Neg.unapply(e)) : super.eval(e); //│ })()); //│ } //│ }); @@ -175,9 +172,9 @@ mixin EvalNegNeg { else super.eval(e) } //│ mixin EvalNegNeg() { -//│ super: {eval: (Neg[nothing] | 'a) -> 'b} -//│ this: {eval: 'c -> 'b} -//│ fun eval: (Neg[Neg['c] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b +//│ super: {eval: (Neg[??A & 'A] | 'a) -> 'b} +//│ this: {eval: (??A0 & 'A0) -> 'b} +//│ fun eval: (Neg['A & (Neg['A0] | Object & ~#Neg | ~??A)] | Object & 'a & ~#Neg) -> 'b //│ } //│ // Prelude //│ class TypingUnit4 { @@ -192,7 +189,7 @@ mixin EvalNegNeg { //│ eval(e) { //│ const qualifier1 = this; //│ return ((() => { -//│ return e instanceof Neg.class ? (([tmp0]) => tmp0 instanceof Neg.class ? (([d]) => qualifier1.eval(d))(Neg.unapply(tmp0)) : super.eval(e))(Neg.unapply(e)) : super.eval(e); +//│ return e instanceof Neg.class ? (($unapp) => ((tmp0) => tmp0 instanceof Neg.class ? (($unapp) => ((d) => qualifier1.eval(d))($unapp[0]))(Neg.unapply(tmp0)) : super.eval(e))($unapp[0]))(Neg.unapply(e)) : super.eval(e); //│ })()); //│ } //│ }); @@ -208,9 +205,8 @@ module TestLang extends EvalBase, EvalNeg, EvalNegNeg //│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int //│ } //│ where -//│ 'A <: 'b & (Neg['b] | Object & ~#Neg) -//│ 'b <: Neg['A] | Object & 'a & ~#Neg -//│ 'a <: Add['b] | Lit | Neg['b] +//│ 'A <: Neg['A] & ~#Neg | Neg['A & (Neg['A] | Object & 'a & ~#Neg | ~??A)] | Object & 'a & ~#Neg | ~??A0 +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit | Neg[Neg['A] | Object & 'a & ~#Neg | ~??A1] //│ // Prelude //│ class TypingUnit5 { //│ #TestLang; @@ -372,7 +368,7 @@ mixin Base { fun x = y } //│ ╔══[ERROR] identifier not found: y -//│ ║ l.372: fun x = y +//│ ║ l.368: fun x = y //│ ╙── ^ //│ mixin Base() { //│ fun x: error diff --git a/shared/src/test/diff/codegen/MixinCapture.mls b/shared/src/test/diff/codegen/MixinCapture.mls index cf721dcf60..da805abd98 100644 --- a/shared/src/test/diff/codegen/MixinCapture.mls +++ b/shared/src/test/diff/codegen/MixinCapture.mls @@ -26,7 +26,7 @@ mixin EvalAddLit { //│ eval(e) { //│ return ((() => { //│ let a; -//│ return (a = e, a instanceof qualifier.Lit.class ? (([n]) => n)(qualifier.Lit.unapply(e)) : (() => { +//│ return (a = e, a instanceof qualifier.Lit.class ? (($unapp) => ((n) => n)($unapp[0]))(qualifier.Lit.unapply(e)) : (() => { //│ throw new Error("non-exhaustive case expression"); //│ })()); //│ })()); diff --git a/shared/src/test/diff/codegen/Nested.mls b/shared/src/test/diff/codegen/Nested.mls index 10843c74aa..9760170426 100644 --- a/shared/src/test/diff/codegen/Nested.mls +++ b/shared/src/test/diff/codegen/Nested.mls @@ -69,7 +69,7 @@ module A { :js let bb = A.B(A.a) bb.b -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member B not yet supported //│ ║ l.70: let bb = A.B(A.a) //│ ╙── ^^ //│ let bb: error @@ -102,10 +102,10 @@ let c = b.C(1) c.outer1 let d = b.D(1) d.outer -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member C not yet supported //│ ║ l.101: let c = b.C(1) //│ ╙── ^^ -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member D not yet supported //│ ║ l.103: let d = b.D(1) //│ ╙── ^^ //│ class B(x: Int) { @@ -350,7 +350,7 @@ let es = E(1) let fff = es.F(2) let gg = fff.G(3) gg.sum -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member F not yet supported //│ ║ l.350: let fff = es.F(2) //│ ╙── ^^ //│ let es: E @@ -549,7 +549,7 @@ module G { let jj = G.H.J(42) let i = jj.ii(2) i.x -//│ ╔══[ERROR] Access to module member not yet supported +//│ ╔══[ERROR] Access to module member H not yet supported //│ ║ l.549: let jj = G.H.J(42) //│ ╙── ^^ //│ let jj: error @@ -657,7 +657,7 @@ module H { :js let j = H.J(42) j.i.x -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member J not yet supported //│ ║ l.658: let j = H.J(42) //│ ╙── ^^ //│ let j: error @@ -687,7 +687,7 @@ class I(x: Int) { let i = I(1) let ij = i.J(0) ij.incY -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member J not yet supported //│ ║ l.688: let ij = i.J(0) //│ ╙── ^^ //│ class I(x: Int) { @@ -878,10 +878,10 @@ module J { :js let m = J.M() let n = J.N(2) -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member M not yet supported //│ ║ l.879: let m = J.M() //│ ╙── ^^ -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member N not yet supported //│ ║ l.880: let n = J.N(2) //│ ╙── ^^ //│ let m: error @@ -922,7 +922,7 @@ module K { :e let m = K.L.M() m.f -//│ ╔══[ERROR] Access to module member not yet supported +//│ ╔══[ERROR] Access to module member L not yet supported //│ ║ l.923: let m = K.L.M() //│ ╙── ^^ //│ let m: error @@ -952,7 +952,7 @@ module L { :e let op = L.N.O.P(0) op.x -//│ ╔══[ERROR] Access to module member not yet supported +//│ ╔══[ERROR] Access to module member N not yet supported //│ ║ l.953: let op = L.N.O.P(0) //│ ╙── ^^ //│ let op: error @@ -979,10 +979,10 @@ module M { _ then 2 } M.N.op(M.P()) -//│ ╔══[ERROR] Access to module member not yet supported +//│ ╔══[ERROR] Access to module member N not yet supported //│ ║ l.981: M.N.op(M.P()) //│ ╙── ^^ -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member P not yet supported //│ ║ l.981: M.N.op(M.P()) //│ ╙── ^^ //│ module M { @@ -1165,7 +1165,7 @@ module N { :e N.O.P() -//│ ╔══[ERROR] Access to module member not yet supported +//│ ╔══[ERROR] Access to module member O not yet supported //│ ║ l.1167: N.O.P() //│ ╙── ^^ //│ error @@ -1181,7 +1181,7 @@ class I(x: Int) { } } I(1).J(3).a -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member J not yet supported //│ ║ l.1183: I(1).J(3).a //│ ╙── ^^ //│ class I(x: Int) { diff --git a/shared/src/test/diff/codegen/NewMatching.mls b/shared/src/test/diff/codegen/NewMatching.mls index 809dcb337d..27128e9f30 100644 --- a/shared/src/test/diff/codegen/NewMatching.mls +++ b/shared/src/test/diff/codegen/NewMatching.mls @@ -39,22 +39,7 @@ fun sum(v) = //│ globalThis.sum = function sum(v) { //│ return ((() => { //│ let a; -//│ return (a = v, a instanceof V0.class ? 0 : a instanceof V1.class ? (([a]) => a)(V1.unapply(v)) : a instanceof V2.class ? (([ -//│ a, -//│ b -//│ ]) => a + b)(V2.unapply(v)) : a instanceof Pos.class ? (([x]) => x > 0 === true ? x : -1)(Pos.unapply(v)) : a instanceof V22.class ? (([ -//│ tmp0, -//│ tmp1 -//│ ]) => tmp0 instanceof V2.class ? (([ -//│ x1, -//│ y1 -//│ ]) => tmp1 instanceof V2.class ? (([ -//│ x2, -//│ y2 -//│ ]) => x1 + y1 + x2 + y2)(V2.unapply(tmp1)) : -1)(V2.unapply(tmp0)) : -1)(V22.unapply(v)) : a instanceof Half.class ? (([ -//│ tmp2, -//│ x -//│ ]) => x)(Half.unapply(v)) : a instanceof None.class ? (([tmp3]) => 0)(None.unapply(v)) : -1); +//│ return a = v, a instanceof V0.class ? 0 : a instanceof V1.class ? (($unapp) => ((a) => a)($unapp[0]))(V1.unapply(v)) : a instanceof V2.class ? (($unapp) => ((a) => ((b) => a + b)($unapp[1]))($unapp[0]))(V2.unapply(v)) : a instanceof Pos.class ? (($unapp) => ((x) => x > 0 === true ? x : -1)($unapp[0]))(Pos.unapply(v)) : a instanceof V22.class ? (($unapp) => ((tmp0) => ((tmp1) => tmp0 instanceof V2.class ? (($unapp) => ((x1) => ((y1) => tmp1 instanceof V2.class ? (($unapp) => ((x2) => ((y2) => x1 + y1 + x2 + y2)($unapp[1]))($unapp[0]))(V2.unapply(tmp1)) : -1)($unapp[1]))($unapp[0]))(V2.unapply(tmp0)) : -1)($unapp[1]))($unapp[0]))(V22.unapply(v)) : a instanceof Half.class ? (($unapp) => ((x) => x)($unapp[1]))(Half.unapply(v)) : a instanceof None.class ? (($unapp) => 0)(None.unapply(v)) : -1; //│ })()); //│ }; //│ // End of generated code @@ -96,7 +81,7 @@ fun get1(s) = if s is Some(V1(x)) then x Some(y) then y -//│ fun get1: forall 'a. Some[Object & 'a] -> (Int | 'a) +//│ fun get1: forall 'T. Some['T & (Object & ~#V1 | V1 | ~??T)] -> (Int | ??T & 'T) //│ // Prelude //│ class TypingUnit5 {} //│ const typing_unit5 = new TypingUnit5; @@ -104,7 +89,7 @@ fun get1(s) = //│ globalThis.get1 = function get1(s) { //│ return ((() => { //│ let a; -//│ return (a = s, a instanceof Some.class ? (([tmp4]) => ((y) => tmp4 instanceof V1.class ? (([x]) => x)(V1.unapply(tmp4)) : y)(tmp4))(Some.unapply(s)) : (() => { +//│ return (a = s, a instanceof Some.class ? (($unapp) => ((tmp2) => ((y) => tmp2 instanceof V1.class ? (($unapp) => ((x) => x)($unapp[0]))(V1.unapply(tmp2)) : y)(tmp2))($unapp[0]))(Some.unapply(s)) : (() => { //│ throw new Error("non-exhaustive case expression"); //│ })()); //│ })()); @@ -113,7 +98,7 @@ fun get1(s) = get1(Some(V1(1))) get1(Some(V0())) -//│ Int | V0 +//│ Int | V0 & ??T //│ res //│ = 1 //│ res @@ -129,14 +114,14 @@ fun foo(s) = if s is Some(t) then let b = s2.value in b + t.x _ then 0 -//│ fun foo: (Object & ~#Some | Some[{x: Int}]) -> Int +//│ fun foo: (Object & ~#Some | Some[{x: Int} | ~??T]) -> Int //│ // Prelude //│ class TypingUnit8 {} //│ const typing_unit8 = new TypingUnit8; //│ // Query 1 //│ globalThis.foo = function foo(s) { //│ return ((() => { -//│ return s instanceof Some.class ? (([t]) => ((b) => b + t.x)(s2.value))(Some.unapply(s)) : 0; +//│ return s instanceof Some.class ? (($unapp) => ((t) => ((b) => b + t.x)(s2.value))($unapp[0]))(Some.unapply(s)) : 0; //│ })()); //│ }; //│ // End of generated code @@ -219,7 +204,7 @@ fun ft(x) = FooBar(x) then x _ then 0 //│ ╔══[ERROR] class FooBar expects 0 parameter but found 1 parameter -//│ ║ l.219: FooBar(x) then x +//│ ║ l.204: FooBar(x) then x //│ ╙── ^^^^^^^^^ //│ fun ft: anything -> error //│ Code generation encountered an error: @@ -265,7 +250,7 @@ fun c(x) = VVC(x, y, z) then x + y + z _ then 0 //│ ╔══[ERROR] class VVC expects 2 parameters but found 3 parameters -//│ ║ l.265: VVC(x, y, z) then x + y + z +//│ ║ l.250: VVC(x, y, z) then x + y + z //│ ╙── ^^^^^^^^^^^^ //│ class VVC(v: Int, vc: Int) //│ fun c: anything -> error diff --git a/shared/src/test/diff/ecoop23/ComparePointPoly.mls b/shared/src/test/diff/ecoop23/ComparePointPoly.mls index c90dfde588..2be737b185 100644 --- a/shared/src/test/diff/ecoop23/ComparePointPoly.mls +++ b/shared/src/test/diff/ecoop23/ComparePointPoly.mls @@ -29,8 +29,8 @@ mixin CompareNested { //│ } //│ mixin CompareNested() { //│ super: {compare: ('f, 'g) -> Bool} -//│ this: {compare: ('h, 'i) -> Bool} -//│ fun compare: ({parent: Object & ~#Some | Some['h]} & 'f, {parent: Object & ~#Some | Some['i]} & 'g) -> Bool +//│ this: {compare: (??A & 'A, ??A0 & 'A0) -> Bool} +//│ fun compare: ({parent: Object & ~#Some | Some['A]} & 'f, {parent: Object & ~#Some | Some['A0]} & 'g) -> Bool //│ } class MyPoint[out Col](val x: Int, val y: Int, val color: Col, val parent: Some[MyPoint[Col]] | None) @@ -38,11 +38,11 @@ class MyPoint[out Col](val x: Int, val y: Int, val color: Col, val parent: Some[ module CompareMyPoint extends ComparePoint, CompareColored, CompareNested //│ module CompareMyPoint { -//│ fun compare: ('a, 'b) -> Bool +//│ fun compare: ({color: Eql['a], parent: 'parent, x: Eql['b], y: Eql['c]}, {color: 'a, parent: Object & 'parent0, x: 'b, y: 'c}) -> Bool //│ } //│ where -//│ 'b <: {color: 'c, parent: Object & ~#Some | Some['b], x: 'd, y: 'e} -//│ 'a <: {color: Eql['c], parent: Object & ~#Some | Some['a], x: Eql['d], y: Eql['e]} +//│ 'parent0 <: Object & ~#Some | Some[{color: 'a, parent: Object & 'parent0, x: 'b, y: 'c} | ~??A] +//│ 'parent <: Object & ~#Some | Some[{color: Eql['a], parent: 'parent, x: Eql['b], y: Eql['c]} | ~??A0] let Red = 0 let p0 = MyPoint(0, 0, Red, None) diff --git a/shared/src/test/diff/ecoop23/ExpressionProblem.mls b/shared/src/test/diff/ecoop23/ExpressionProblem.mls index 2e36d48a6b..a3af483b1c 100644 --- a/shared/src/test/diff/ecoop23/ExpressionProblem.mls +++ b/shared/src/test/diff/ecoop23/ExpressionProblem.mls @@ -17,9 +17,9 @@ fun eval(e) = if e is Lit(n) then n Add(l, r) then eval(l) + eval(r) -//│ fun eval: forall 'a. 'a -> Int +//│ fun eval: forall 'E. (Add['E] | Lit) -> Int //│ where -//│ 'a <: Add['a] | Lit +//│ 'E <: Add['E] | Lit | ~??E mixin EvalBase { @@ -29,22 +29,22 @@ mixin EvalBase { Add(l, r) then this.eval(l) + this.eval(r) } //│ mixin EvalBase() { -//│ this: {eval: 'a -> Int} -//│ fun eval: (Add['a] | Lit) -> Int +//│ this: {eval: (??E & 'E) -> Int} +//│ fun eval: (Add['E] | Lit) -> Int //│ } module TestLang extends EvalBase //│ module TestLang { -//│ fun eval: 'a -> Int +//│ fun eval: (Add['E] | Lit) -> Int //│ } //│ where -//│ 'a <: Add['a] | Lit +//│ 'E <: Add['E] | Lit | ~??E TestLang.eval -//│ 'a -> Int +//│ (Add['E] | Lit) -> Int //│ where -//│ 'a <: Add['a] | Lit +//│ 'E <: Add['E] | Lit | ~??E //│ res //│ = [Function: eval] @@ -70,19 +70,19 @@ module TestLang extends EvalNothing, EvalAddLit //│ } //│ mixin EvalAddLit() { //│ super: {eval: 'a -> 'b} -//│ this: {eval: 'c -> Int} -//│ fun eval: (Add['c] | Lit | Object & 'a & ~#Add & ~#Lit) -> (Int | 'b) +//│ this: {eval: (??E & 'E) -> Int} +//│ fun eval: (Add['E] | Lit | Object & 'a & ~#Add & ~#Lit) -> (Int | 'b) //│ } //│ module TestLang { -//│ fun eval: 'd -> Int +//│ fun eval: (Add['E0] | Lit) -> Int //│ } //│ where -//│ 'd <: Add['d] | Lit +//│ 'E0 <: Add['E0] | Lit | ~??E TestLang.eval -//│ 'a -> Int +//│ (Add['E] | Lit) -> Int //│ where -//│ 'a <: Add['a] | Lit +//│ 'E <: Add['E] | Lit | ~??E //│ res //│ = [Function: eval] @@ -108,22 +108,24 @@ mixin EvalNeg { } //│ mixin EvalNeg() { //│ super: {eval: 'a -> 'b} -//│ this: {eval: 'c -> Int} -//│ fun eval: (Neg['c] | Object & 'a & ~#Neg) -> (Int | 'b) +//│ this: {eval: (??A & 'A) -> Int} +//│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> (Int | 'b) //│ } module TestLang extends EvalBase, EvalNeg //│ module TestLang { -//│ fun eval: 'a -> Int +//│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int //│ } //│ where -//│ 'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg +//│ 'A <: Neg['A] | Object & 'a & ~#Neg | ~??A +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit TestLang.eval -//│ 'a -> Int +//│ (Neg['A] | Object & 'a & ~#Neg) -> Int //│ where -//│ 'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg +//│ 'A <: Neg['A] | Object & 'a & ~#Neg | ~??A +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit //│ res //│ = [Function: eval] @@ -173,9 +175,9 @@ mixin EvalNegNeg_0 { // else super.eval(e) } //│ mixin EvalNegNeg_0() { -//│ super: {eval: (Neg[nothing] | 'a) -> 'b} -//│ this: {eval: 'c -> 'b} -//│ fun eval: (Neg[Neg['c] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b +//│ super: {eval: (Neg[??A & 'A] | 'a) -> 'b} +//│ this: {eval: (??A0 & 'A0) -> 'b} +//│ fun eval: (Neg['A & (Neg['A0] | Object & ~#Neg | ~??A)] | Object & 'a & ~#Neg) -> 'b //│ } // * Concise alternative, usign syntax sugar: @@ -183,9 +185,9 @@ mixin EvalNegNeg { fun eval(override Neg(Neg(d))) = this.eval(d) } //│ mixin EvalNegNeg() { -//│ super: {eval: (Neg[nothing] | 'a) -> 'b} -//│ this: {eval: 'c -> 'b} -//│ fun eval: (Neg[Neg['c] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b +//│ super: {eval: (Neg[??A & 'A] | 'a) -> 'b} +//│ this: {eval: (??A0 & 'A0) -> 'b} +//│ fun eval: (Neg['A & (Neg['A0] | Object & ~#Neg | ~??A)] | Object & 'a & ~#Neg) -> 'b //│ } module TestLang extends EvalBase, EvalNeg, EvalNegNeg @@ -193,9 +195,8 @@ module TestLang extends EvalBase, EvalNeg, EvalNegNeg //│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int //│ } //│ where -//│ 'A <: 'b & (Neg['b] | Object & ~#Neg) -//│ 'b <: Neg['A] | Object & 'a & ~#Neg -//│ 'a <: Add['b] | Lit | Neg['b] +//│ 'A <: Neg['A] & ~#Neg | Neg['A & (Neg['A] | Object & 'a & ~#Neg | ~??A)] | Object & 'a & ~#Neg | ~??A0 +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit | Neg[Neg['A] | Object & 'a & ~#Neg | ~??A1] fun mk(n) = if n is 0 then Lit(0) @@ -208,9 +209,8 @@ fun mk(n) = if n is TestLang.eval //│ (Neg['A] | Object & 'a & ~#Neg) -> Int //│ where -//│ 'A <: 'b & (Neg['b] | Object & ~#Neg) -//│ 'b <: Neg['A] | Object & 'a & ~#Neg -//│ 'a <: Add['b] | Lit | Neg['b] +//│ 'A <: Neg['A] & ~#Neg | Neg['A & (Neg['A] | Object & 'a & ~#Neg | ~??A)] | Object & 'a & ~#Neg | ~??A0 +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit | Neg[Neg['A] | Object & 'a & ~#Neg | ~??A1] //│ res //│ = [Function: eval] diff --git a/shared/src/test/diff/ecoop23/Intro.mls b/shared/src/test/diff/ecoop23/Intro.mls index dda082110c..c6d4a684a7 100644 --- a/shared/src/test/diff/ecoop23/Intro.mls +++ b/shared/src/test/diff/ecoop23/Intro.mls @@ -70,8 +70,8 @@ mixin CompareNested { } //│ mixin CompareNested() { //│ super: {compare: ('a, 'b) -> Bool} -//│ this: {compare: ('c, 'd) -> Bool} -//│ fun compare: ({parent: Object & ~#Some | Some['c]} & 'a, {parent: Object & ~#Some | Some['d]} & 'b) -> Bool +//│ this: {compare: (??A & 'A, ??A0 & 'A0) -> Bool} +//│ fun compare: ({parent: Object & ~#Some | Some['A]} & 'a, {parent: Object & ~#Some | Some['A0]} & 'b) -> Bool //│ } // * Alternatively: @@ -92,16 +92,11 @@ class MyPoint(val x: Int, val y: Int, val color: Color, val parent: Some[MyPoint module CompareMyPoint extends ComparePoint, CompareColored, CompareNested //│ module CompareMyPoint { -//│ fun compare: ('a, 'b) -> Bool +//│ fun compare: ({color: {equals: 'color -> Bool}, parent: 'parent, x: Eql['a], y: Eql['b]}, {color: 'color, parent: Object & 'parent0, x: 'a, y: 'b}) -> Bool //│ } //│ where -//│ 'b <: {color: 'color, parent: Object & ~#Some | Some['b], x: 'c, y: 'd} -//│ 'a <: { -//│ color: {equals: 'color -> Bool}, -//│ parent: Object & ~#Some | Some['a], -//│ x: Eql['c], -//│ y: Eql['d] -//│ } +//│ 'parent0 <: Object & ~#Some | Some[{color: 'color, parent: Object & 'parent0, x: 'a, y: 'b} | ~??A] +//│ 'parent <: Object & ~#Some | Some[{color: {equals: 'color -> Bool}, parent: 'parent, x: Eql['a], y: Eql['b]} | ~??A0] let p0 = MyPoint(0, 0, Red, None) diff --git a/shared/src/test/diff/ecoop23/PolymorphicVariants.mls b/shared/src/test/diff/ecoop23/PolymorphicVariants.mls index a2c301e8e0..458656b862 100644 --- a/shared/src/test/diff/ecoop23/PolymorphicVariants.mls +++ b/shared/src/test/diff/ecoop23/PolymorphicVariants.mls @@ -25,7 +25,7 @@ fun list_assoc(s, l) = if s === h.0 then Success(h.1) else list_assoc(s, t) Nil then NotFound() -//│ fun list_assoc: forall 'a 'A. (Eql['a], Cons[{0: 'a, 1: 'A}] | Nil) -> (NotFound | Success['A]) +//│ fun list_assoc: forall 'a 'b. (Eql['a], Cons[{0: 'a, 1: 'b} | ~??A] | Nil) -> (NotFound | Success['b]) // fun list_assoc(s: Str, l: Cons[{ _1: Str, _2: 'b }] | Nil): NotFound | Success['b] @@ -40,7 +40,7 @@ mixin EvalVar { Success(r) then r } //│ mixin EvalVar() { -//│ fun eval: (Cons[{0: anything, 1: 'a}] | Nil, Var) -> (Var | 'a) +//│ fun eval: (Cons[{0: anything, 1: 'a} | ~??A] | Nil, Var) -> (Var | ??A0 & 'a) //│ } class Abs[out A](x: Str, t: A) @@ -73,18 +73,20 @@ mixin EvalLambda { //│ mixin EvalLambda() { //│ super: {eval: ('a, 'b) -> 'c} //│ this: { -//│ eval: ('a, 'd) -> 'A & (Cons[[Str, 'A]], 'e) -> 'c & (Cons[[Str, Var] | 'A0], 'f) -> 'A1 +//│ eval: ('a, ??A & 'A) -> 'd & (Cons[[Str, 'd]], ??A0 & 'A0) -> 'c & (Cons[[Str, Var] | 'A1], ??A1 & 'A2) -> 'e //│ } -//│ fun eval: ('a & (Cons['A0] | Nil), Abs['f] | App['d & (Abs['e] | Object & ~#Abs)] | Object & 'b & ~#Abs & ~#App) -> (Abs['A1] | App['A] | 'c) +//│ fun eval: ('a & (Cons['A1] | Nil), Abs['A2] | App['A & (Abs['A0] | Object & ~#Abs | ~??A)] | Object & 'b & ~#Abs & ~#App) -> (Abs['e] | App['d] | 'c) //│ } module Test1 extends EvalVar, EvalLambda //│ module Test1 { -//│ fun eval: (Cons[{0: anything, 1: 'a}] | Nil, 'b) -> 'a +//│ fun eval: (Cons[{0: anything, 1: 'a} | ~??A] | Nil, Abs['A] | App['A0] | Var) -> 'b //│ } //│ where -//│ 'b <: Abs['b] | App['b & (Abs['b] | Object & ~#Abs)] | Var -//│ 'a :> Abs['a] | App['a] | Var +//│ 'A <: Abs['A] | App['A0] | Var | ~??A0 +//│ 'A0 <: Abs['A] & ~#Abs | Abs['A & (Abs['A] | App['A0] | Var | ~??A1)] | App['A0] | Var | ~??A2 +//│ 'a :> 'b +//│ 'b :> Abs['b] | App['b] | Var | ??A3 & 'a Test1.eval(Nil, Var("a")) //│ 'a @@ -108,9 +110,9 @@ Test1.eval(Cons(["c", Var("d")], Nil), App(Abs("b", Var("b")), Var("c"))) //│ = Var {} Test1.eval(Cons(["c", Abs("d", Var("d"))], Nil), App(Abs("b", Var("b")), Var("c"))) -//│ Abs['a] | 'a +//│ 'a //│ where -//│ 'a :> Abs['a] | App['a] | Var +//│ 'a :> Abs['a] | Abs[Var] & ??A | App['a] | Var //│ res //│ = Abs {} @@ -127,7 +129,7 @@ fun map_expr(f, v) = Numb then v Add(l, r) then Add(f(l), f(r)) Mul(l, r) then Mul(f(l), f(r)) -//│ fun map_expr: forall 'a 'A 'b 'A0. ('a -> 'A & 'b -> 'A0, Add['a] | Mul['b] | Numb | Var) -> (Add['A] | Mul['A0] | Numb | Var) +//│ fun map_expr: forall 'A 'a 'A0 'b. ((??A & 'A) -> 'a & (??A0 & 'A0) -> 'b, Add['A] | Mul['A0] | Numb | Var) -> (Add['a] | Mul['b] | Numb | Var) mixin EvalExpr { fun eval(sub, v) = @@ -141,16 +143,17 @@ mixin EvalExpr { } //│ mixin EvalExpr() { //│ super: {eval: ('a, Var) -> 'b} -//│ this: {eval: ('a, 'c) -> Object} -//│ fun eval: ('a, 'b & (Add['c] | Mul['c] | Numb | Var)) -> (Numb | 'b) +//│ this: {eval: ('a, ??A & 'A | ??A0 & 'A0) -> (Numb | Object & ~#Numb)} +//│ fun eval: ('a, 'b & (Add['A0] | Mul['A] | Numb | Var)) -> (Numb | 'b) //│ } module Test2 extends EvalVar, EvalExpr //│ module Test2 { -//│ fun eval: forall 'a. (Cons[{0: anything, 1: Object & 'b}] | Nil, 'a & (Add['c] | Mul['c] | Numb | Var)) -> (Numb | Var | 'b | 'c | 'a) +//│ fun eval: forall 'a. (Cons[{0: anything, 1: 'b & (Numb | Object & ~#Numb | ~??A)} | ~??A0] | Nil, 'a & (Add['A] | Mul['A0] | Numb | Var)) -> (Numb | Var | ??A & 'b | ??A1 & 'A | ??A2 & 'A0 | 'a) //│ } //│ where -//│ 'c <: Add['c] | Mul['c] | Numb | Var +//│ 'A <: Add['A] | Mul['A0] | Numb | Var | ~??A1 +//│ 'A0 <: Add['A] | Mul['A0] | Numb | Var | ~??A2 Test2.eval(Nil, Var("a")) //│ Numb | Var @@ -158,7 +161,7 @@ Test2.eval(Nil, Var("a")) //│ = Var {} Test2.eval(Cons(["c", Abs("d", Var("d"))], Nil), Var("a")) -//│ Abs[Var] | Numb | Var +//│ Abs[Var] & ??A | Numb | Var //│ res //│ = Var {} @@ -171,16 +174,16 @@ Test2.eval(Cons(["a", Numb(1)], Nil), Var("a")) :e Test2.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.172: Test2.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) +//│ ║ l.175: Test2.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── application of type `Abs[?A]` does not match type `Add[?A0] | Mul[?A1] | Numb | Var` -//│ ║ l.172: Test2.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) +//│ ║ l.175: Test2.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from reference: -//│ ║ l.125: if v is +//│ ║ l.127: if v is //│ ║ ^ //│ ╟── from reference: -//│ ║ l.135: let vv = map_expr(eta, v) +//│ ║ l.137: let vv = map_expr(eta, v) //│ ╙── ^ //│ Abs[Var] | Numb | Var | error //│ res @@ -188,65 +191,67 @@ Test2.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) //│ Error: non-exhaustive case expression Test2.eval(Cons(["a", Abs("d", Var("d"))], Nil), Add(Numb(1), Var("a"))) -//│ Abs[Var] | Add[Numb | Var] | Numb | Var +//│ Abs[Var] & ??A | Add[Numb | Var] | Numb & ??A0 | Var //│ res //│ = Add {} module Test3 extends EvalVar, EvalExpr, EvalLambda //│ module Test3 { -//│ fun eval: (Cons[{0: anything, 1: 'a}] | Nil, 'b) -> (Abs['c] | App['c] | 'c) +//│ fun eval: (Cons[{0: anything, 1: 'a} | ~??A] | Nil, Abs['A] | App['A0] | Object & 'b & ~#Abs & ~#App) -> 'c //│ } //│ where //│ 'a :> 'c -//│ <: Object -//│ 'c :> 'a | 'd -//│ 'd <: Add['b] | Mul['b] | Numb | Var -//│ 'b <: Abs['b] | App['b & (Abs['b] | Object & ~#Abs)] | Object & 'd & ~#Abs & ~#App +//│ <: Numb | Object & ~#Numb | ~??A0 +//│ 'c :> Abs['c] | App['c] | Numb | Var | ??A0 & 'a | 'b +//│ 'b <: Add[Abs['A] | App['A0] | Object & 'b & ~#Abs & ~#App | ~??A1] | Mul[Abs['A] | App['A0] | Object & 'b & ~#Abs & ~#App | ~??A2] | Numb | Var +//│ 'A <: Abs['A] | App['A0] | Object & 'b & ~#Abs & ~#App | ~??A3 +//│ 'A0 <: Abs['A] & ~#Abs | Abs['A & (Abs['A] | App['A0] | Object & 'b & ~#Abs & ~#App | ~??A4)] | App['A0] | Object & 'b & ~#Abs & ~#App | ~??A5 Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) -//│ Abs['a] | 'a +//│ 'a //│ where -//│ 'a :> Abs['a] | App['a] | Numb | Var +//│ 'a :> Abs['a] | Abs[Var] & ??A | App['a] | Numb | Var & ??A0 //│ res //│ = Abs {} Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil), App(Abs("a", Var("a")), Add(Numb(1), Var("c")))) -//│ Abs['a] | 'a +//│ 'a //│ where -//│ 'a :> Abs['a] | Add[Numb | Var] | App['a] | Numb | Var +//│ 'a :> Abs['a] | Abs[Var] & ??A | Add[Numb | Var] & ??A0 | App['a] | Numb & ??A1 | Var & ??A2 //│ res //│ = Add {} // * Incorrect version, for regression testing – EvalLambda should be mixed in after EvalExpr module Test3 extends EvalVar, EvalLambda, EvalExpr //│ module Test3 { -//│ fun eval: (Cons[{0: anything, 1: 'a}] | Nil, 'a & (Add['b] | Mul['b] | Numb | Var)) -> (Numb | 'c | 'a | 'b) +//│ fun eval: (Cons[{0: anything, 1: 'a} | ~??A] | Nil, 'b & (Add['A] | Mul['A0] | Numb | Var)) -> (??A0 & 'A | ??A1 & 'A0 | 'b) //│ } //│ where -//│ 'a :> 'b | 'c -//│ <: Object -//│ 'c :> Abs['c | 'a] | App['c | 'a] | 'a -//│ 'b <: Add['b] | Mul['b] | Numb | Var +//│ 'a :> ??A0 & 'A | ??A1 & 'A0 | 'b +//│ <: Numb | Object & ~#Numb | Object & ~??A2 | ~??A2 +//│ 'b :> Abs[??A0 & 'A | ??A1 & 'A0 | 'b] | App[??A0 & 'A | ??A1 & 'A0 | 'b] | Numb | Var | ??A0 & 'A | ??A1 & 'A0 | ??A2 & 'a +//│ 'A <: Add['A] | Mul['A0] | Numb | Var | ~??A0 +//│ 'A0 <: Add['A] | Mul['A0] | Numb | Var | ~??A1 // * Because EvalExpr does not dispatch lambdas to super and map_expr only // * handles exprs :e Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.234: Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) +//│ ║ l.239: Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── application of type `Abs[?A]` does not match type `Add[?A0] | Mul[?A1] | Numb | Var` -//│ ║ l.234: Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) +//│ ║ l.239: Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil), Abs("a", Var("a"))) //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from reference: -//│ ║ l.125: if v is +//│ ║ l.127: if v is //│ ║ ^ //│ ╟── from reference: -//│ ║ l.135: let vv = map_expr(eta, v) +//│ ║ l.137: let vv = map_expr(eta, v) //│ ╙── ^ -//│ Abs[Var] | error | 'a +//│ Abs[Var] | Numb | error | 'a //│ where -//│ 'a :> Abs['a] | App['a] | Numb | Var +//│ 'a :> Abs[Var & 'a] | App['a] | Var | ??A & (Abs[Var] | Numb) //│ res //│ Runtime error: //│ Error: non-exhaustive case expression diff --git a/shared/src/test/diff/ecoop23/SimpleRegionDSL_annot.mls b/shared/src/test/diff/ecoop23/SimpleRegionDSL_annot.mls index ba1bca5b7f..1e75c8ab20 100644 --- a/shared/src/test/diff/ecoop23/SimpleRegionDSL_annot.mls +++ b/shared/src/test/diff/ecoop23/SimpleRegionDSL_annot.mls @@ -33,8 +33,10 @@ mixin SizeBase { Translate(_, a) then this.size(a) + 1 } //│ mixin SizeBase() { -//│ this: {size: 'a -> Int} -//│ fun size: (Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]) -> Int +//│ this: { +//│ size: (??Region & 'Region | ??Region0 & 'Region0 | ??Region1 & 'Region1 | ??Region2 & 'Region2) -> Int +//│ } +//│ fun size: (Circle | Intersect['Region1] | Outside['Region] | Translate['Region2] | Union['Region0]) -> Int //│ } // ******************* Linguistic Reuse and Meta-Language Optimizations ******************* @@ -81,8 +83,8 @@ mixin SizeExt { } //│ mixin SizeExt() { //│ super: {size: 'a -> 'b} -//│ this: {size: 'c -> Int} -//│ fun size: (Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['c] | Univ) -> (Int | 'b) +//│ this: {size: (??Region & 'Region) -> Int} +//│ fun size: (Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['Region] | Univ) -> (Int | 'b) //│ } type RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang] @@ -127,8 +129,10 @@ mixin Contains { Translate(v, a) then this.contains(a, Vector(p.x - v.x, p.y - v.y)) } //│ mixin Contains() { -//│ this: {contains: ('a, 'b) -> Bool & ('c, Vector) -> 'd} -//│ fun contains: (Circle | Intersect['a] | Outside['a] | Translate['c] | Union['a], {x: Int, y: Int} & 'b) -> (Bool | 'd) +//│ this: { +//│ contains: (??Region & 'Region | ??Region0 & 'Region0 | ??Region1 & 'Region1, 'a) -> Bool & (??Region2 & 'Region2, Vector) -> 'b +//│ } +//│ fun contains: (Circle | Intersect['Region1] | Outside['Region] | Translate['Region2] | Union['Region0], {x: Int, y: Int} & 'a) -> (Bool | 'b) //│ } type BaseRegionLang = BaseLang[BaseRegionLang] @@ -173,23 +177,25 @@ mixin Text { Translate then concat("a translated region of size ", toString(this.size(e))) } //│ mixin Text() { -//│ this: {size: (Intersect[nothing] | Translate['Region] | Union[nothing] | 'a) -> Int} -//│ fun text: (Circle | Intersect[anything] | Outside['a] | Translate['Region] | Union[anything]) -> Str +//│ this: { +//│ size: (Intersect[??Region & 'Region] | Translate[??Region0 & 'Region0] | Union[??Region1 & 'Region1] | ??Region2 & 'Region2) -> Int +//│ } +//│ fun text: (Circle | Intersect['Region] | Outside['Region2] | Translate['Region0] | Union['Region1]) -> Str //│ } :e module SizeText extends Text //│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size` -//│ ║ l.173: Translate then concat("a translated region of size ", toString(this.size(e))) +//│ ║ l.177: Translate then concat("a translated region of size ", toString(this.size(e))) //│ ╙── ^^^^^ //│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size` -//│ ║ l.172: Intersect then concat("the intersection of two regions of size ", toString(this.size(e))) +//│ ║ l.176: Intersect then concat("the intersection of two regions of size ", toString(this.size(e))) //│ ╙── ^^^^^ //│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size` -//│ ║ l.171: Union then concat("the union of two regions of size ", toString(this.size(e))) +//│ ║ l.175: Union then concat("the union of two regions of size ", toString(this.size(e))) //│ ╙── ^^^^^ //│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size` -//│ ║ l.170: Outside(a) then concat("outside a region of size ", toString(this.size(a))) +//│ ║ l.174: Outside(a) then concat("outside a region of size ", toString(this.size(a))) //│ ╙── ^^^^^ //│ module SizeText { //│ fun text: (Circle | Intersect[anything] | Outside[anything] | Translate[anything] | Union[anything]) -> Str @@ -237,8 +243,11 @@ mixin IsUniv { else false } //│ mixin IsUniv() { -//│ this: {isEmpty: 'a -> 'b, isUniv: 'c -> Bool & 'd -> 'b} -//│ fun isUniv: (Intersect['c] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['a] | Scale['d] | Translate['d] | Union['c] | Univ) -> (Bool | 'b) +//│ this: { +//│ isEmpty: (??Region & 'Region) -> 'a, +//│ isUniv: (??Region0 & 'Region0 | ??Region1 & 'Region1) -> Bool & (??Region2 & 'Region2 | ??Region3 & 'Region3) -> 'a +//│ } +//│ fun isUniv: (Intersect['Region1] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region] | Scale['Region3] | Translate['Region2] | Union['Region0] | Univ) -> (Bool | 'a) //│ } mixin IsEmpty { @@ -253,8 +262,11 @@ mixin IsEmpty { else false } //│ mixin IsEmpty() { -//│ this: {isEmpty: 'a -> Bool & 'b -> 'c, isUniv: 'd -> 'c} -//│ fun isEmpty: (Intersect['a] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['d] | Scale['b] | Translate['b] | Union['a] | Univ) -> (Bool | 'c) +//│ this: { +//│ isEmpty: (??Region & 'Region | ??Region0 & 'Region0) -> Bool & (??Region1 & 'Region1 | ??Region2 & 'Region2) -> 'a, +//│ isUniv: (??Region3 & 'Region3) -> 'a +//│ } +//│ fun isEmpty: (Intersect['Region0] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region3] | Scale['Region2] | Translate['Region1] | Union['Region] | Univ) -> (Bool | 'a) //│ } module IsUnivIsEmpty extends IsUniv, IsEmpty { @@ -289,16 +301,16 @@ IsUnivIsEmpty.isEmpty(circles) class Foo() IsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles))) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.290: IsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles))) +//│ ║ l.302: IsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles))) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── application of type `Foo` does not match type `BaseLang[RegionLang] | ExtLang[RegionLang]` -//│ ║ l.290: IsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles))) +//│ ║ l.302: IsUnivIsEmpty.isEmpty(Scale(Vector(1, 2), Intersect(Foo(), circles))) //│ ║ ^^^^^ //│ ╟── Note: constraint arises from union type: -//│ ║ l.88: type RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang] +//│ ║ l.90: type RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang] //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── from type reference: -//│ ║ l.88: type RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang] +//│ ║ l.90: type RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang] //│ ╙── ^^^^^^^^^^ //│ class Foo() //│ error | false | true @@ -318,9 +330,9 @@ mixin Eliminate { } //│ mixin Eliminate() { //│ this: { -//│ eliminate: 'a -> 'b & 'c -> 'Region & 'd -> 'Region0 & 'e -> 'Region1 & 'f -> 'Region2 & 'g -> 'Region3 +//│ eliminate: (??Region & 'Region) -> 'a & (??Region0 & 'Region0) -> 'b & (??Region1 & 'Region1) -> 'c & (??Region2 & 'Region2) -> 'd & (??Region3 & 'Region3) -> 'e & (??Region4 & 'Region4) -> 'f //│ } -//│ fun eliminate: (Intersect['e] | Object & 'b & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['c & (Object & ~#Outside | Outside['a])] | Scale['g] | Translate['f] | Union['d]) -> (Intersect['Region1] | Outside['Region] | Scale['Region3] | Translate['Region2] | Union['Region0] | 'b) +//│ fun eliminate: (Intersect['Region2] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0 & (Object & ~#Outside | Outside['Region] | ~??Region0)] | Scale['Region4] | Translate['Region3] | Union['Region1]) -> (Intersect['d] | Outside['b] | Scale['f] | Translate['e] | Union['c] | 'a) //│ } module TestElim extends Eliminate { @@ -417,16 +429,16 @@ Lang.size(mk(100)) :re Lang.contains(mk(100), Vector(0, 0)) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.418: Lang.contains(mk(100), Vector(0, 0)) +//│ ║ l.430: Lang.contains(mk(100), Vector(0, 0)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[BaseRegionLang] | Outside[BaseRegionLang] | Translate[BaseRegionLang] | Union[BaseRegionLang]` -//│ ║ l.348: _ then Scale(Vector(0, 0), mk(n)) +//│ ║ l.360: _ then Scale(Vector(0, 0), mk(n)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from union type: //│ ║ l.23: type BaseLang[T] = Circle | Intersect[T] | Union[T] | Outside[T] | Translate[T] //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── from type reference: -//│ ║ l.134: type BaseRegionLang = BaseLang[BaseRegionLang] +//│ ║ l.138: type BaseRegionLang = BaseLang[BaseRegionLang] //│ ╙── ^^^^^^^^^^^^^^ //│ error | false | true //│ res @@ -437,16 +449,16 @@ Lang.contains(mk(100), Vector(0, 0)) :re Lang.text(mk(100)) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.438: Lang.text(mk(100)) +//│ ║ l.450: Lang.text(mk(100)) //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[BaseRegionLang] | Outside[BaseRegionLang] | Translate[BaseRegionLang] | Union[BaseRegionLang]` -//│ ║ l.348: _ then Scale(Vector(0, 0), mk(n)) +//│ ║ l.360: _ then Scale(Vector(0, 0), mk(n)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from union type: //│ ║ l.23: type BaseLang[T] = Circle | Intersect[T] | Union[T] | Outside[T] | Translate[T] //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── from type reference: -//│ ║ l.134: type BaseRegionLang = BaseLang[BaseRegionLang] +//│ ║ l.138: type BaseRegionLang = BaseLang[BaseRegionLang] //│ ╙── ^^^^^^^^^^^^^^ //│ Str | error //│ res diff --git a/shared/src/test/diff/ecoop23/SimpleRegionDSL_raw.mls b/shared/src/test/diff/ecoop23/SimpleRegionDSL_raw.mls index 9a2cb67690..336141134d 100644 --- a/shared/src/test/diff/ecoop23/SimpleRegionDSL_raw.mls +++ b/shared/src/test/diff/ecoop23/SimpleRegionDSL_raw.mls @@ -30,8 +30,10 @@ mixin SizeBase { Translate(_, a) then this.size(a) + 1 } //│ mixin SizeBase() { -//│ this: {size: 'a -> Int} -//│ fun size: (Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]) -> Int +//│ this: { +//│ size: (??Region & 'Region | ??Region0 & 'Region0 | ??Region1 & 'Region1 | ??Region2 & 'Region2) -> Int +//│ } +//│ fun size: (Circle | Intersect['Region1] | Outside['Region] | Translate['Region2] | Union['Region0]) -> Int //│ } // ******************* Linguistic Reuse and Meta-Language Optimizations ******************* @@ -75,16 +77,17 @@ mixin SizeExt { } //│ mixin SizeExt() { //│ super: {size: 'a -> 'b} -//│ this: {size: 'c -> Int} -//│ fun size: (Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['c] | Univ) -> (Int | 'b) +//│ this: {size: (??Region & 'Region) -> Int} +//│ fun size: (Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['Region] | Univ) -> (Int | 'b) //│ } module TestSize extends SizeBase, SizeExt //│ module TestSize { -//│ fun size: 'a -> Int +//│ fun size: (Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['Region] | Univ) -> Int //│ } //│ where -//│ 'a <: Empty | Object & (Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]) & ~#Empty & ~#Scale & ~#Univ | Scale['a] | Univ +//│ 'a <: Circle | Intersect[Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['Region] | Univ | ~??Region] | Outside[Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['Region] | Univ | ~??Region0] | Translate[Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['Region] | Univ | ~??Region1] | Union[Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['Region] | Univ | ~??Region2] +//│ 'Region <: Empty | Object & 'a & ~#Empty & ~#Scale & ~#Univ | Scale['Region] | Univ | ~??Region3 TestSize.size(Empty()) //│ Int @@ -118,16 +121,21 @@ mixin Contains { Translate(v, a) then this.contains(a, Vector(p.x - v.x, p.y - v.y)) } //│ mixin Contains() { -//│ this: {contains: ('a, 'b) -> Bool & ('c, Vector) -> 'd} -//│ fun contains: (Circle | Intersect['a] | Outside['a] | Translate['c] | Union['a], {x: Int, y: Int} & 'b) -> (Bool | 'd) +//│ this: { +//│ contains: (??Region & 'Region | ??Region0 & 'Region0 | ??Region1 & 'Region1, 'a) -> Bool & (??Region2 & 'Region2, Vector) -> 'b +//│ } +//│ fun contains: (Circle | Intersect['Region1] | Outside['Region] | Translate['Region2] | Union['Region0], {x: Int, y: Int} & 'a) -> (Bool | 'b) //│ } module TestContains extends Contains //│ module TestContains { -//│ fun contains: ('a, {x: Int, y: Int}) -> Bool +//│ fun contains: (Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2], {x: Int, y: Int}) -> Bool //│ } //│ where -//│ 'a <: Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a] +//│ 'Region <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region +//│ 'Region0 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region0 +//│ 'Region1 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region1 +//│ 'Region2 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region2 TestContains.contains(Translate(Vector(0, 0), Circle(1)), Vector(0, 0)) //│ Bool @@ -161,23 +169,25 @@ mixin Text { Translate then concat("a translated region of size ", toString(this.size(e))) } //│ mixin Text() { -//│ this: {size: (Intersect[nothing] | Translate['Region] | Union[nothing] | 'a) -> Int} -//│ fun text: (Circle | Intersect[anything] | Outside['a] | Translate['Region] | Union[anything]) -> Str +//│ this: { +//│ size: (Intersect[??Region & 'Region] | Translate[??Region0 & 'Region0] | Union[??Region1 & 'Region1] | ??Region2 & 'Region2) -> Int +//│ } +//│ fun text: (Circle | Intersect['Region] | Outside['Region2] | Translate['Region0] | Union['Region1]) -> Str //│ } :e module SizeText extends Text //│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size` -//│ ║ l.161: Translate then concat("a translated region of size ", toString(this.size(e))) +//│ ║ l.169: Translate then concat("a translated region of size ", toString(this.size(e))) //│ ╙── ^^^^^ //│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size` -//│ ║ l.160: Intersect then concat("the intersection of two regions of size ", toString(this.size(e))) +//│ ║ l.168: Intersect then concat("the intersection of two regions of size ", toString(this.size(e))) //│ ╙── ^^^^^ //│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size` -//│ ║ l.159: Union then concat("the union of two regions of size ", toString(this.size(e))) +//│ ║ l.167: Union then concat("the union of two regions of size ", toString(this.size(e))) //│ ╙── ^^^^^ //│ ╔══[ERROR] Type `#SizeText & {text: ?a -> (?b | ?c | ?d | ?e | ?f)}` does not contain member `size` -//│ ║ l.158: Outside(a) then concat("outside a region of size ", toString(this.size(a))) +//│ ║ l.166: Outside(a) then concat("outside a region of size ", toString(this.size(a))) //│ ╙── ^^^^^ //│ module SizeText { //│ fun text: (Circle | Intersect[anything] | Outside[anything] | Translate[anything] | Union[anything]) -> Str @@ -186,11 +196,14 @@ module SizeText extends Text // * Note: this inferred type got *much worse* after this commit (field access type refinement) module SizeText extends SizeBase, Text //│ module SizeText { -//│ fun size: (Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a]) -> Int -//│ fun text: 'a -> Str +//│ fun size: (Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2]) -> Int +//│ fun text: (Circle | Intersect[Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~(??Region & ??Region0)] | Outside[Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region1] | Translate[Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~(??Region2 & ??Region3)] | Union[Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~(??Region4 & ??Region5)]) -> Str //│ } //│ where -//│ 'a <: Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a] +//│ 'Region <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region +//│ 'Region0 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region6 +//│ 'Region1 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region2 +//│ 'Region2 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region4 SizeText.text(circles) //│ Str @@ -224,8 +237,11 @@ mixin IsUniv { else false } //│ mixin IsUniv() { -//│ this: {isEmpty: 'a -> 'b, isUniv: 'c -> Bool & 'd -> 'b} -//│ fun isUniv: (Intersect['c] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['a] | Scale['d] | Translate['d] | Union['c] | Univ) -> (Bool | 'b) +//│ this: { +//│ isEmpty: (??Region & 'Region) -> 'a, +//│ isUniv: (??Region0 & 'Region0 | ??Region1 & 'Region1) -> Bool & (??Region2 & 'Region2 | ??Region3 & 'Region3) -> 'a +//│ } +//│ fun isUniv: (Intersect['Region1] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region] | Scale['Region3] | Translate['Region2] | Union['Region0] | Univ) -> (Bool | 'a) //│ } mixin IsEmpty { @@ -240,27 +256,46 @@ mixin IsEmpty { else false } //│ mixin IsEmpty() { -//│ this: {isEmpty: 'a -> Bool & 'b -> 'c, isUniv: 'd -> 'c} -//│ fun isEmpty: (Intersect['a] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['d] | Scale['b] | Translate['b] | Union['a] | Univ) -> (Bool | 'c) +//│ this: { +//│ isEmpty: (??Region & 'Region | ??Region0 & 'Region0) -> Bool & (??Region1 & 'Region1 | ??Region2 & 'Region2) -> 'a, +//│ isUniv: (??Region3 & 'Region3) -> 'a +//│ } +//│ fun isEmpty: (Intersect['Region0] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region3] | Scale['Region2] | Translate['Region1] | Union['Region] | Univ) -> (Bool | 'a) //│ } module IsUnivIsEmpty extends IsUniv, IsEmpty //│ module IsUnivIsEmpty { -//│ fun isEmpty: 'a -> Bool -//│ fun isUniv: 'b -> Bool +//│ fun isEmpty: (Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ) -> Bool +//│ fun isUniv: (Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ) -> Bool //│ } //│ where -//│ 'b <: Intersect['b] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['b] | Scale['b] | Translate['b] | Union['b] | Univ -//│ 'a <: Intersect['a] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['a] | Scale['a] | Translate['a] | Union['a] | Univ +//│ 'Region <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region +//│ 'Region0 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region0 +//│ 'Region4 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region1 +//│ 'Region6 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region2 +//│ 'Region7 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region3 +//│ 'Region8 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region4 +//│ 'Region5 <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region5 +//│ 'Region1 <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region6 +//│ 'Region2 <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region7 +//│ 'Region3 <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region8 module IsUnivIsEmpty extends IsEmpty, IsUniv //│ module IsUnivIsEmpty { -//│ fun isEmpty: 'a -> Bool -//│ fun isUniv: 'b -> Bool +//│ fun isEmpty: (Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ) -> Bool +//│ fun isUniv: (Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ) -> Bool //│ } //│ where -//│ 'b <: Intersect['b] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['b] | Scale['b] | Translate['b] | Union['b] | Univ -//│ 'a <: Intersect['a] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['a] | Scale['a] | Translate['a] | Union['a] | Univ +//│ 'Region <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region +//│ 'Region0 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region0 +//│ 'Region4 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region1 +//│ 'Region6 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region2 +//│ 'Region7 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region3 +//│ 'Region8 <: Intersect['Region4] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region5] | Scale['Region6] | Translate['Region7] | Union['Region8] | Univ | ~??Region4 +//│ 'Region5 <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region5 +//│ 'Region1 <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region6 +//│ 'Region2 <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region7 +//│ 'Region3 <: Intersect['Region] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | Univ | ~??Region8 IsUnivIsEmpty.isUniv(circles) //│ Bool @@ -292,23 +327,27 @@ mixin Eliminate { } //│ mixin Eliminate() { //│ this: { -//│ eliminate: 'a -> 'b & 'c -> 'Region & 'd -> 'Region0 & 'e -> 'Region1 & 'f -> 'Region2 & 'g -> 'Region3 +//│ eliminate: (??Region & 'Region) -> 'a & (??Region0 & 'Region0) -> 'b & (??Region1 & 'Region1) -> 'c & (??Region2 & 'Region2) -> 'd & (??Region3 & 'Region3) -> 'e & (??Region4 & 'Region4) -> 'f //│ } -//│ fun eliminate: (Intersect['e] | Object & 'b & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['c & (Object & ~#Outside | Outside['a])] | Scale['g] | Translate['f] | Union['d]) -> (Intersect['Region1] | Outside['Region] | Scale['Region3] | Translate['Region2] | Union['Region0] | 'b) +//│ fun eliminate: (Intersect['Region2] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0 & (Object & ~#Outside | Outside['Region] | ~??Region0)] | Scale['Region4] | Translate['Region3] | Union['Region1]) -> (Intersect['d] | Outside['b] | Scale['f] | Translate['e] | Union['c] | 'a) //│ } module TestElim extends Eliminate //│ module TestElim { -//│ fun eliminate: 'a -> 'b +//│ fun eliminate: (Intersect['Region] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3]) -> 'a //│ } //│ where -//│ 'a <: Intersect['a] | Object & 'b & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['a & (Object & ~#Outside | Outside['a])] | Scale['a] | Translate['a] | Union['a] -//│ 'b :> Intersect['b] | Outside['b] | Scale['b] | Translate['b] | Union['b] +//│ 'Region <: Intersect['Region] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | ~??Region +//│ 'Region0 <: Intersect['Region] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0] & ~#Outside | Outside['Region0 & (Intersect['Region] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | ~??Region0)] | Scale['Region1] | Translate['Region2] | Union['Region3] | ~??Region1 +//│ 'Region1 <: Intersect['Region] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | ~??Region2 +//│ 'Region2 <: Intersect['Region] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | ~??Region3 +//│ 'Region3 <: Intersect['Region] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region0] | Scale['Region1] | Translate['Region2] | Union['Region3] | ~??Region4 +//│ 'a :> Intersect['a] | Outside['a] | Scale['a] | Translate['a] | Union['a] TestElim.eliminate(Outside(Outside(Univ()))) -//│ 'a +//│ Univ & ??Region | 'a //│ where -//│ 'a :> Intersect['a] | Outside[Univ | 'a] | Scale[Univ | 'a] | Translate[Univ | 'a] | Union[Univ | 'a] | Univ +//│ 'a :> Intersect[Univ & ??Region | 'a] | Outside[Univ & ??Region | 'a] | Scale[Univ & ??Region | 'a] | Translate[Univ & ??Region | 'a] | Union[Univ & ??Region | 'a] | Univ & ??Region //│ res //│ = Univ {} @@ -342,21 +381,36 @@ TestElim.eliminate(mk(100)) module Lang extends SizeBase, SizeExt, Contains, Text, IsUniv, IsEmpty, Eliminate //│ module Lang { -//│ fun contains: ('a, {x: Int, y: Int}) -> Bool -//│ fun eliminate: 'b -> 'c -//│ fun isEmpty: 'd -> Bool -//│ fun isUniv: 'e -> Bool -//│ fun size: 'f -> Int -//│ fun text: (Circle | Intersect['g] | Outside['g] | Translate['g] | Union['g]) -> Str +//│ fun contains: (Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2], {x: Int, y: Int}) -> Bool +//│ fun eliminate: (Intersect['Region3] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region4] | Scale['Region5] | Translate['Region6] | Union['Region7]) -> 'a +//│ fun isEmpty: (Intersect['Region8] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region9] | Scale['Region10] | Translate['Region11] | Union['Region12] | Univ) -> Bool +//│ fun isUniv: (Intersect['Region13] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region14] | Scale['Region15] | Translate['Region16] | Union['Region17] | Univ) -> Bool +//│ fun size: (Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ) -> Int +//│ fun text: (Circle | Intersect[Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~(??Region & ??Region0)] | Outside[Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~??Region1] | Translate[Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~(??Region2 & ??Region3)] | Union[Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~(??Region4 & ??Region5)]) -> Str //│ } //│ where -//│ 'g <: Empty | Object & (Circle | Intersect['g] | Outside['g] | Translate['g] | Union['g]) & ~#Empty & ~#Scale & ~#Univ | Scale['g] | Univ -//│ 'f <: Empty | Object & (Circle | Intersect['f] | Outside['f] | Translate['f] | Union['f]) & ~#Empty & ~#Scale & ~#Univ | Scale['f] | Univ -//│ 'e <: Intersect['e] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['e] | Scale['e] | Translate['e] | Union['e] | Univ -//│ 'd <: Intersect['d] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['d] | Scale['d] | Translate['d] | Union['d] | Univ -//│ 'b <: Intersect['b] | Object & 'c & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['b & (Object & ~#Outside | Outside['b])] | Scale['b] | Translate['b] | Union['b] -//│ 'c :> Intersect['c] | Outside['c] | Scale['c] | Translate['c] | Union['c] -//│ 'a <: Circle | Intersect['a] | Outside['a] | Translate['a] | Union['a] +//│ 'b <: Circle | Intersect[Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~??Region] | Outside[Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~??Region6] | Translate[Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~??Region2] | Union[Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~??Region4] +//│ 'Region18 <: Empty | Object & 'b & ~#Empty & ~#Scale & ~#Univ | Scale['Region18] | Univ | ~??Region7 +//│ 'Region8 <: Intersect['Region8] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region9] | Scale['Region10] | Translate['Region11] | Union['Region12] | Univ | ~??Region8 +//│ 'Region9 <: Intersect['Region13] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region14] | Scale['Region15] | Translate['Region16] | Union['Region17] | Univ | ~??Region9 +//│ 'Region13 <: Intersect['Region13] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region14] | Scale['Region15] | Translate['Region16] | Union['Region17] | Univ | ~??Region10 +//│ 'Region15 <: Intersect['Region13] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region14] | Scale['Region15] | Translate['Region16] | Union['Region17] | Univ | ~??Region11 +//│ 'Region16 <: Intersect['Region13] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region14] | Scale['Region15] | Translate['Region16] | Union['Region17] | Univ | ~??Region12 +//│ 'Region17 <: Intersect['Region13] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region14] | Scale['Region15] | Translate['Region16] | Union['Region17] | Univ | ~??Region13 +//│ 'Region14 <: Intersect['Region8] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region9] | Scale['Region10] | Translate['Region11] | Union['Region12] | Univ | ~??Region14 +//│ 'Region10 <: Intersect['Region8] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region9] | Scale['Region10] | Translate['Region11] | Union['Region12] | Univ | ~??Region15 +//│ 'Region11 <: Intersect['Region8] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region9] | Scale['Region10] | Translate['Region11] | Union['Region12] | Univ | ~??Region16 +//│ 'Region12 <: Intersect['Region8] | Object & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union & ~#Univ | Outside['Region9] | Scale['Region10] | Translate['Region11] | Union['Region12] | Univ | ~??Region17 +//│ 'Region3 <: Intersect['Region3] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region4] | Scale['Region5] | Translate['Region6] | Union['Region7] | ~??Region18 +//│ 'Region4 <: Intersect['Region3] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region4] & ~#Outside | Outside['Region4 & (Intersect['Region3] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region4] | Scale['Region5] | Translate['Region6] | Union['Region7] | ~??Region19)] | Scale['Region5] | Translate['Region6] | Union['Region7] | ~??Region20 +//│ 'Region5 <: Intersect['Region3] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region4] | Scale['Region5] | Translate['Region6] | Union['Region7] | ~??Region21 +//│ 'Region6 <: Intersect['Region3] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region4] | Scale['Region5] | Translate['Region6] | Union['Region7] | ~??Region22 +//│ 'Region7 <: Intersect['Region3] | Object & 'a & ~#Intersect & ~#Outside & ~#Scale & ~#Translate & ~#Union | Outside['Region4] | Scale['Region5] | Translate['Region6] | Union['Region7] | ~??Region23 +//│ 'a :> Intersect['a] | Outside['a] | Scale['a] | Translate['a] | Union['a] +//│ 'Region <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region24 +//│ 'Region0 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region25 +//│ 'Region1 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region26 +//│ 'Region2 <: Circle | Intersect['Region] | Outside['Region0] | Translate['Region1] | Union['Region2] | ~??Region27 Lang.size(circles) //│ Int @@ -399,21 +453,21 @@ Lang.size(mk(100)) :re Lang.contains(mk(100), Vector(0, 0)) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.400: Lang.contains(mk(100), Vector(0, 0)) +//│ ║ l.454: Lang.contains(mk(100), Vector(0, 0)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[?Region0] | Outside[?Region1] | Translate[?Region2] | Union[?Region3]` -//│ ║ l.327: _ then Scale(Vector(0, 0), mk(n)) +//│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[?Region0] | Outside[?Region1] | Translate[?Region2] | Union[?Region3] | ~??Region` +//│ ║ l.366: _ then Scale(Vector(0, 0), mk(n)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from reference: -//│ ║ l.113: if a is +//│ ║ l.116: if a is //│ ║ ^ //│ ╟── from field selection: -//│ ║ l.13: class Outside[out Region](a: Region) -//│ ║ ^ +//│ ║ l.16: class Translate[out Region](v: Vector, a: Region) +//│ ║ ^ //│ ╟── Note: type parameter Region is defined at: -//│ ║ l.13: class Outside[out Region](a: Region) -//│ ╙── ^^^^^^ -//│ error | false | true +//│ ║ l.16: class Translate[out Region](v: Vector, a: Region) +//│ ╙── ^^^^^^ +//│ error //│ res //│ Runtime error: //│ RangeError: Maximum call stack size exceeded @@ -422,16 +476,16 @@ Lang.contains(mk(100), Vector(0, 0)) :re Lang.text(mk(100)) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.423: Lang.text(mk(100)) +//│ ║ l.477: Lang.text(mk(100)) //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── application of type `Scale[?Region]` does not match type `Circle | Intersect[?Region0] | Outside[?Region1] | Translate[?Region2] | Union[?Region3]` -//│ ║ l.327: _ then Scale(Vector(0, 0), mk(n)) +//│ ║ l.366: _ then Scale(Vector(0, 0), mk(n)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── but it flows into application with expected type `Circle | Intersect[?Region4] | Outside[?Region5] | Translate[?Region6] | Union[?Region7]` -//│ ║ l.423: Lang.text(mk(100)) +//│ ║ l.477: Lang.text(mk(100)) //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from reference: -//│ ║ l.156: if e is +//│ ║ l.164: if e is //│ ╙── ^ //│ Str | error //│ res diff --git a/shared/src/test/diff/ex/RepMin.mls b/shared/src/test/diff/ex/RepMin.mls index 408abd3b96..3b3631ba44 100644 --- a/shared/src/test/diff/ex/RepMin.mls +++ b/shared/src/test/diff/ex/RepMin.mls @@ -88,7 +88,7 @@ fun walk(t, mn) = if t is let mnl = walk(l, mn) let mnr = walk(r, mn) [min(mnl.0, mnr.0), Node(mnl.1, mnr.1)] -//│ fun walk: forall 'a 'b. (Leaf[Num & 'a] | Node[Num & 'a], Int & 'b) -> ['a, Leaf['b | 'a] | Node['b | 'a]] +//│ fun walk: forall 'A 'A0 'a. (Leaf['A & (Num | ~??A)] | Node['A0 & (Num | ~??A | ~??A0)], Int & 'a) -> [??A & ('A | ??A0 & 'A0), Leaf['a | ??A & ('A | ??A0 & 'A0)] | Node['a | ??A & ('A | ??A0 & 'A0)]] let tree = Node of (Node of (Node of Leaf(1), Leaf(5)), Leaf(3)), Node of Leaf(3), Leaf(2) @@ -125,9 +125,7 @@ fun walk(t, mn) = if t is Pair of n, Leaf(if n > 2 * mn then mn else n) Node(l, r) and walk(l, mn) is Pair(mn1, l1) and walk(r, mn) is Pair(mn2, r1) then Pair of min(mn1, mn2), Node(l1, r1) -//│ fun walk: forall 'A 'a. (Leaf['A] | Node['A], Int & 'a) -> Pair['A, Leaf['a | 'A] | Node['a | 'A]] -//│ where -//│ 'A <: Num +//│ fun walk: forall 'A 'A0. (Leaf['A & (Num | ~??A)] | Node['A0 & (Num | ~??A | ~??A0)], Int) -> Pair[??A & ??A1 & ('A | ??A0 & 'A0), nothing] String of walk(tree, 2) //│ Str @@ -145,7 +143,7 @@ fun walkLazy(t, mn) = if t is let mnl = walkLazy(l, mn) let mnr = walkLazy(r, mn) [min(mnl.0, mnr.0), Lazy of () => Node of mnl.1.get, mnr.1.get] -//│ fun walkLazy: forall 'a 'get. (Leaf[Num & 'a] | Node[Num & 'a], {get: Int & 'get}) -> ['a, Lazy[Leaf['get | 'a] | Node['get | 'a]]] +//│ fun walkLazy: forall 'A 'A0. (Leaf['A & (Num | ~??A)] | Node['A0 & (Num | ~??A | ~??A0)], {get: Int}) -> [??A & ('A | ??A0 & 'A0), Lazy[nothing]] // * One way to tie the recursive knot @@ -156,9 +154,9 @@ class repmin(t: Tree[Int]) { val tree = mn_res.1.get } //│ class repmin(t: Tree[Int]) { -//│ val mn: Int -//│ val mn_res: [Int, Lazy[Leaf[Int] | Node[Int]]] -//│ val tree: Leaf[Int] | Node[Int] +//│ val mn: Int & ??A +//│ val mn_res: [Int & ??A, Lazy[nothing]] +//│ val tree: Leaf[Int & ??A] | Node[Int & ??A] //│ } let rm = repmin(tree) @@ -173,7 +171,7 @@ let rm = repmin(tree) //│ Traversing leaf 2 [rm.mn, String of rm.tree] -//│ [Int, Str] +//│ [Int & ??A, Str] //│ res //│ = [ //│ 1, @@ -188,7 +186,7 @@ fun repmin(t) = val mn_res = walkLazy of t, Lazy of () => mn_res.0 } [Rec.mn_res.0, Rec.mn_res.1.get] -//│ fun repmin: forall 'a. (Leaf[Int & 'a] | Node[Int & 'a]) -> ['a, Leaf['a] | Node['a]] +//│ fun repmin: forall 'A 'A0. (Leaf['A & (Int | ~??A)] | Node['A0 & (Int | ~??A | ~??A0)]) -> [??A & ('A | ??A0 & 'A0), Leaf[??A & ('A | ??A0 & 'A0)] | Node[??A & ('A | ??A0 & 'A0)]] String of repmin(tree) //│ Str @@ -208,7 +206,7 @@ String of repmin(tree) fun repmin(t) = let rec mn_res = walkLazy of t, Lazy(() => mn_res.0) [mn_res.0, mn_res.1.get] -//│ fun repmin: forall 'a. (Leaf[Int & 'a] | Node[Int & 'a]) -> ['a, Leaf['a] | Node['a]] +//│ fun repmin: forall 'A 'A0. (Leaf['A & (Int | ~??A)] | Node['A0 & (Int | ~??A | ~??A0)]) -> [??A & ('A | ??A0 & 'A0), Leaf[??A & ('A | ??A0 & 'A0)] | Node[??A & ('A | ??A0 & 'A0)]] //│ Code generation encountered an error: //│ unguarded recursive use of by-value binding mn_res @@ -240,7 +238,7 @@ fun repmin(t) = () => Node of l'(), r'() let res = go(t) [min, res()] -//│ fun repmin: forall 'min. (Leaf[Int & 'min] | Node[Int & 'min]) -> [2147483648 | 'min, Leaf[2147483648 | 'min] | Node[2147483648 | 'min]] +//│ fun repmin: forall 'A 'min 'A0. (Leaf['A & (Int & 'min | ~??A)] | Node['A0 & (Int & 'min | ~??A | ~??A0)]) -> [2147483648 | 'min, Leaf[2147483648 | 'min | ??A & ('A | ??A0 & 'A0)] | Node[2147483648 | 'min | ??A & ('A | ??A0 & 'A0)]] String of repmin(tree) //│ Str @@ -259,21 +257,21 @@ String of repmin(tree) // * Aside on UCS parsing: p => if p is Pair of a, b then a + b -//│ Pair[Int, Int] -> Int +//│ Pair[Int | ~??A, Int | ~??B] -> Int //│ res //│ = [Function: res] :e // TODO handle this pattern better in the parser? (p, q) => if p is Pair of a, b and q is Pair of a', b' then Pair of a + a', b + b' //│ ╔══[ERROR] Illegal pattern `and` -//│ ║ l.267: (p, q) => if p is Pair of a, b and q is Pair of a', b' then Pair of a + a', b + b' +//│ ║ l.265: (p, q) => if p is Pair of a, b and q is Pair of a', b' then Pair of a + a', b + b' //│ ╙── ^^^ //│ (anything, anything) -> error //│ Code generation encountered an error: //│ if expression was not desugared (p, q) => if p is (Pair of a, b) and q is Pair of a', b' then Pair of a + a', b + b' -//│ (Pair[Int, Int], Pair[Int, Int]) -> Pair[Int, Int] +//│ (Pair[Int | ~??A, Int | ~??B], Pair[Int | ~??A0, Int | ~??B0]) -> Pair[Int, Int] //│ res //│ = [Function: res] diff --git a/shared/src/test/diff/fcp-lit/Leijen.mls b/shared/src/test/diff/fcp-lit/Leijen.mls index e44fd04e4a..68c18b2019 100644 --- a/shared/src/test/diff/fcp-lit/Leijen.mls +++ b/shared/src/test/diff/fcp-lit/Leijen.mls @@ -425,7 +425,7 @@ app (map head) (single ids) (error : List['a -> 'a] -> int) (error : List[(forall 'd. 'd -> 'c) -> 'c]) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: ? -> 'a +//│ 'a <: #? -> 'a //│ ╙── //│ res: int @@ -843,7 +843,7 @@ takeAuto (fun f -> f f) // ,("[id]: [ids]", ok "[[forall a. a -> a]]") cons (single id) (single ids) -//│ res: List[List[forall 'a. 'a -> 'a]] +//│ res: List[List[forall 'a 'a0. 'a -> 'a & 'a0 -> 'a0]] //│ = Cons { //│ head: Cons { head: [Function: id1], tail: Nil {} }, //│ tail: Cons { @@ -854,7 +854,7 @@ cons (single id) (single ids) // ,("([id] :: [forall a. a -> a]) : [[\\x -> x]]", ok "[[forall a. a -> a]]") cons (single id : List[forall 'a. 'a -> 'a]) (single (single (fun x -> x))) -//│ res: List[List[forall 'a. 'a -> 'a]] +//│ res: List[List[forall 'a 'b. 'a -> 'a & 'b -> 'b]] //│ = Cons { //│ head: Cons { head: [Function: id1], tail: Nil {} }, //│ tail: Cons { @@ -932,7 +932,7 @@ xauto : (forall 'a. 'a -> 'a) -> (forall 'a. 'a -> 'a) def runST2: forall 'a. (forall 's. (ST['s, 'a], ST['s, 'a])) -> 'a runST2 ((newRef 1, newRef 2)) //│ runST2: (forall 's. (ST['s, 'a], ST['s, 'a],)) -> 'a -//│ res: Ref[in ??s, 1 | 2] +//│ res: Ref[in ??s, nothing] def runST3: forall 'a. (forall 's. ST[('s, 's), 'a]) -> 'a def newRef3: forall 'a 's. 'a -> ST[('s, 's), Ref['s, 'a]] diff --git a/shared/src/test/diff/fcp-lit/variations_PolyML.mls b/shared/src/test/diff/fcp-lit/variations_PolyML.mls index 9a971c8160..372093d13b 100644 --- a/shared/src/test/diff/fcp-lit/variations_PolyML.mls +++ b/shared/src/test/diff/fcp-lit/variations_PolyML.mls @@ -75,7 +75,7 @@ rec def mem x l = case l of } //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: {head: ?, tail: Cons[?] & 'a} +//│ 'a <: {head: #?, tail: Cons[?] & 'a} //│ ║ l.72: rec def mem x l = case l of //│ ╙── ^ //│ mem: anything -> 'a -> Bool diff --git a/shared/src/test/diff/fcp/Church_CT.mls b/shared/src/test/diff/fcp/Church_CT.mls index bcc8702053..6fde6cbffa 100644 --- a/shared/src/test/diff/fcp/Church_CT.mls +++ b/shared/src/test/diff/fcp/Church_CT.mls @@ -631,7 +631,7 @@ rec def to_ch_s n = else s (to_ch_s (n - 1)) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> forall 'b. (? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e) +//│ 'a :> forall 'b. (#? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e) //│ where //│ 'a <: 'b -> 'c -> 'd //│ 'b <: 'd -> 'e) @@ -653,7 +653,7 @@ rec def to_ch n = else s (to_ch (n - 1)) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> forall 'b. (? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e) +//│ 'a :> forall 'b. (#? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e) //│ where //│ 'a <: 'b -> 'c -> 'd //│ 'b <: 'd -> 'e) @@ -673,7 +673,7 @@ rec def to_ch n = to_church_ty = to_ch //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> forall 'b. (? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e) +//│ 'a :> forall 'b. (#? & 'b) -> (forall 'b 'c 'd 'e 'f. ('f & 'c) -> ('f | 'e) //│ where //│ 'a <: 'b -> 'c -> 'd //│ 'b <: 'd -> 'e) @@ -812,7 +812,7 @@ rec def to_ch_A1 n = else s (to_ch_A1 (n - 1) : ChurchInt) //│ ╔══[ERROR] Inferred recursive type: 'to_ch_A1 //│ where -//│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. (? & 'a) -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e) +//│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. (#? & 'a) -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e) //│ where //│ ChurchInt <: 'a -> 'b -> 'c //│ 'a <: 'c -> 'd)) @@ -834,7 +834,7 @@ rec def to_ch_A1 n = to_church_ty = to_ch_A1 //│ ╔══[ERROR] Inferred recursive type: 'to_ch_A1 //│ where -//│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. (? & 'a) -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e) +//│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a. (#? & 'a) -> (forall 'a 'b 'c 'd 'e. ('b & 'e) -> ('d | 'e) //│ where //│ ChurchInt <: 'a -> 'b -> 'c //│ 'a <: 'c -> 'd)) @@ -1069,7 +1069,7 @@ rec def to_chD n = to_church_ty = to_ch //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> forall 'b 'c 'd 'e 'f. (? & 'b) -> (('f & 'c) -> ('f | 'e) +//│ 'a :> forall 'b 'c 'd 'e 'f. (#? & 'b) -> (('f & 'c) -> ('f | 'e) //│ where //│ 'a <: 'b -> 'c -> 'd //│ 'b <: 'd -> 'e) @@ -1169,7 +1169,7 @@ to_church_ty = to_ch_simplif to_church_ty = to_ch_A1 //│ ╔══[ERROR] Inferred recursive type: 'to_ch_A1 //│ where -//│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a 'b 'c 'd 'e. (? & 'a) -> (('b & 'e) -> ('d | 'e) +//│ 'to_ch_A1 :> forall 'to_ch_A1. int -> (forall 'a 'b 'c 'd 'e. (#? & 'a) -> (('b & 'e) -> ('d | 'e) //│ where //│ ChurchInt <: 'a -> 'b -> 'c //│ 'a <: 'c -> 'd)) diff --git a/shared/src/test/diff/fcp/ConstrainedTypes2.mls b/shared/src/test/diff/fcp/ConstrainedTypes2.mls index 458ed46959..58af04b6d0 100644 --- a/shared/src/test/diff/fcp/ConstrainedTypes2.mls +++ b/shared/src/test/diff/fcp/ConstrainedTypes2.mls @@ -106,13 +106,13 @@ def test extr x = let f n m = x (n 0) in let _ = extr f in f 0 -//│ test: ((forall 'a 'b 'c. 'a -> (anything -> 'c +//│ test: (('a -> (anything -> ('b | 'c) //│ where -//│ 'd <: 'b -> 'c -//│ 'a <: 0 -> 'b)) -> anything) -> 'd -> (anything -> 'e +//│ 'd <: 'e -> 'b +//│ 0 | 'a <: 0 -> ('e & 'f))) -> anything) -> 'd -> (anything -> ('b | 'c) //│ where -//│ 'd <: 'f -> 'e -//│ 0 <: 0 -> 'f) +//│ 'd <: 'f -> 'c +//│ 0 | 'a <: 0 -> ('e & 'f)) //│ = [Function: test1] :e diff --git a/shared/src/test/diff/fcp/FunnyId.mls b/shared/src/test/diff/fcp/FunnyId.mls index 1180173631..a303dc15a8 100644 --- a/shared/src/test/diff/fcp/FunnyId.mls +++ b/shared/src/test/diff/fcp/FunnyId.mls @@ -30,9 +30,9 @@ id_ty = id rec def id x = let tmp = id id x in x //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: 'b -> ? +//│ 'a <: 'b -> #? //│ 'b :> 'b -> 'b -//│ <: ? & 'a +//│ <: #? & 'a //│ ║ l.30: rec def id x = let tmp = id id x in x //│ ╙── ^^^^^ //│ id: 'a -> 'a @@ -46,9 +46,9 @@ rec def id x = let tmp = id id x in x id 1 //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: 'b -> ? +//│ 'a <: 'b -> #? //│ 'b :> 1 | 'b -> 'b -//│ <: ? & 'a +//│ <: #? & 'a //│ ║ l.30: rec def id x = let tmp = id id x in x //│ ╙── ^^^^^ //│ ╔══[ERROR] Type mismatch in application: @@ -74,9 +74,9 @@ id 1 id_ty = id //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: 'b -> ? +//│ 'a <: 'b -> #? //│ 'b :> 'b -> 'b -//│ <: ? & 'a +//│ <: #? & 'a //│ ║ l.30: rec def id x = let tmp = id id x in x //│ ╙── ^^^^^ //│ 'a -> 'a diff --git a/shared/src/test/diff/fcp/ListBuild.mls b/shared/src/test/diff/fcp/ListBuild.mls index 1dfe4f4548..a340ae8939 100644 --- a/shared/src/test/diff/fcp/ListBuild.mls +++ b/shared/src/test/diff/fcp/ListBuild.mls @@ -74,7 +74,7 @@ def build0 (g: forall 'b. ('a -> 'a -> 'b) -> 'b) = g (fun x -> fun y -> single( def build0 (g: forall 'b. ('a -> 'b -> 'b) -> 'b) = g (fun x -> fun y -> single((x, y))) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> Ls[(?, forall 'a. 'a,)] +//│ 'a :> Ls[(#?, forall 'a. 'a,)] //│ ║ l.74: def build0 (g: forall 'b. ('a -> 'b -> 'b) -> 'b) = g (fun x -> fun y -> single((x, y))) //│ ╙── ^^^^^^^^^^^^^^ //│ build0: (forall 'b. ('a -> 'b -> 'b) -> 'b) -> 'c diff --git a/shared/src/test/diff/fcp/NestedDataTypes.mls b/shared/src/test/diff/fcp/NestedDataTypes.mls index 9aa94da253..2acefb72bf 100644 --- a/shared/src/test/diff/fcp/NestedDataTypes.mls +++ b/shared/src/test/diff/fcp/NestedDataTypes.mls @@ -67,7 +67,7 @@ rec def map f tree = case tree of { } //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: {subTree: Leaf[?] & {value: ((?, (?, ?,),), ((?, ?,), ?,),)} | Node[?] & 'a} +//│ 'a <: {subTree: Leaf[?] & {value: ((#?, (#?, #?,),), ((#?, #?,), #?,),)} | Node[?] & 'a} //│ ║ l.64: rec def map f tree = case tree of { //│ ╙── ^^^^ //│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required diff --git a/shared/src/test/diff/fcp/NestedDataTypesGADT.mls b/shared/src/test/diff/fcp/NestedDataTypesGADT.mls index 5c5e2f2b55..db2b09b3d2 100644 --- a/shared/src/test/diff/fcp/NestedDataTypesGADT.mls +++ b/shared/src/test/diff/fcp/NestedDataTypesGADT.mls @@ -96,7 +96,7 @@ d2_ : HTree[S[Z], int] //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.95: d2_ : HTree[S[Z], int] //│ ║ ^^^ -//│ ╟── expression of type `S[in Z & 'p out Z | 'p]` is not an instance of type `Z` +//│ ╟── expression of type `S[in Z | 'p out Z & 'p]` is not an instance of type `Z` //│ ╟── Note: constraint arises from type reference: //│ ║ l.72: def d1_ty: HTree[Z, int] //│ ║ ^ @@ -116,7 +116,7 @@ d2_ : HTree[S[Z], int] //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.112: d2_ : HTree[S[Z], int] //│ ║ ^^^ -//│ ╟── type `HTreeBase[S[Z], ?]` does not match type `DLeaf[int] | DNode[S[in Z & 'p out Z | 'p], int]` +//│ ╟── type `HTreeBase[S[Z], ?]` does not match type `DLeaf[int] | DNode[S[in Z | 'p out Z & 'p], int]` //│ ║ l.111: d2_ k = k (d2:HTreeBase[S[Z], int]) //│ ║ ^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from union type: diff --git a/shared/src/test/diff/fcp/OCamlList.mls b/shared/src/test/diff/fcp/OCamlList.mls index c1012d8ff3..ffb0c38602 100644 --- a/shared/src/test/diff/fcp/OCamlList.mls +++ b/shared/src/test/diff/fcp/OCamlList.mls @@ -776,7 +776,7 @@ rec def merge cmp l1 l2 = if cmp h1 h2 <= 0 then Cons(h1, merge cmp t1 l2) else Cons(h2, merge cmp l1 t2) -//│ ('A -> 'A0 -> number) -> List['A & 'a] -> List['A0 & 'a] -> List['a | 'A0 | 'A] +//│ ('A -> 'A0 -> number) -> List['A & 'a] -> List['A0 & 'a] -> List['A & 'A0 & 'a] //│ <: merge: //│ ('a -> 'a -> int) -> List['a] -> List['a] -> List['a] @@ -850,7 +850,7 @@ def stable_sort cmp l = in let len = length l in if len < 2 then l else fst (sort len l) -//│ ('A -> 'A -> number) -> (List['A & 'A0] & 'a & List['A & 'A1]) -> (List['A0 | 'A1] | 'a) +//│ ('A -> 'A -> number) -> (List['A & 'A0] & 'a & List['A & 'A1]) -> (List['A1 & 'A0] | 'a) //│ <: stable_sort: //│ ('a -> 'a -> int) -> List['a] -> List['a] @@ -971,7 +971,7 @@ def sort_uniq cmp l = in let len = length l in if len < 2 then l else fst (sort len l) -//│ ('A -> 'A -> number) -> (List['A & 'A0] & 'a & List['A & 'A1]) -> (List['A0 | 'A1] | 'a) +//│ ('A -> 'A -> number) -> (List['A & 'A0] & 'a & List['A & 'A1]) -> (List['A1 & 'A0] | 'a) //│ <: sort_uniq: //│ ('a -> 'a -> int) -> List['a] -> List['a] diff --git a/shared/src/test/diff/fcp/Paper.mls b/shared/src/test/diff/fcp/Paper.mls index a9ab8da0d0..3de8758305 100644 --- a/shared/src/test/diff/fcp/Paper.mls +++ b/shared/src/test/diff/fcp/Paper.mls @@ -92,7 +92,7 @@ auto auto! //│ ╔══[ERROR] Inferred recursive type: 'a //│ where //│ 'a :> 'a -> 'b -//│ <: 'a -> (? & 'b) +//│ <: 'a -> (#? & 'b) //│ ╙── //│ res: nothing diff --git a/shared/src/test/diff/fcp/PaperTable.mls b/shared/src/test/diff/fcp/PaperTable.mls index 19921d0790..ea66f51e65 100644 --- a/shared/src/test/diff/fcp/PaperTable.mls +++ b/shared/src/test/diff/fcp/PaperTable.mls @@ -713,7 +713,7 @@ auto auto //│ ╔══[ERROR] Inferred recursive type: 'a //│ where //│ 'a :> 'a -> 'b -//│ <: 'a -> (? & 'b) +//│ <: 'a -> (#? & 'b) //│ ╙── //│ res: nothing //│ Runtime error: @@ -1120,7 +1120,7 @@ auto auto //│ ╔══[ERROR] Inferred recursive type: 'a //│ where //│ 'a :> 'a -> 'b -//│ <: 'a -> (? & 'b) +//│ <: 'a -> (#? & 'b) //│ ╙── //│ res: nothing //│ Runtime error: @@ -1499,7 +1499,7 @@ auto auto //│ ╔══[ERROR] Inferred recursive type: 'a //│ where //│ 'a :> 'a -> 'b -//│ <: 'a -> (? & 'b) +//│ <: 'a -> (#? & 'b) //│ ╙── //│ res: nothing //│ Runtime error: diff --git a/shared/src/test/diff/fcp/Proofs.mls b/shared/src/test/diff/fcp/Proofs.mls index 2ee3205792..c39f38fa5a 100644 --- a/shared/src/test/diff/fcp/Proofs.mls +++ b/shared/src/test/diff/fcp/Proofs.mls @@ -375,8 +375,8 @@ EM_to_DNE: EM -> DNE //│ ║ l.23: type DNE = forall 'a. Not[Not['a]] -> 'a //│ ║ ^^ //│ ╟── back into type variable `'a` -//│ ║ l.32: case em of Left -> em.v, Right -> nna em.v -//│ ║ ^^^^ +//│ ║ l.23: type DNE = forall 'a. Not[Not['a]] -> 'a +//│ ║ ^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this field selection: //│ ║ l.32: case em of Left -> em.v, Right -> nna em.v @@ -386,36 +386,30 @@ EM_to_DNE: EM -> DNE //│ ║ ^^^^^^^^^ //│ ╟── • this field selection: //│ ║ l.32: case em of Left -> em.v, Right -> nna em.v -//│ ║ ^^^^ -//│ ╟── Note: constraint arises from type variable: -//│ ║ l.19: type EM = forall 'a. Either['a, Not['a]] -//│ ╙── ^^ +//│ ╙── ^^^^ //│ res: EM -> DNE :e EM_to_DNE: EM -> DNE //│ ╔══[ERROR] Type error in type ascription -//│ ║ l.396: EM_to_DNE: EM -> DNE +//│ ║ l.393: EM_to_DNE: EM -> DNE //│ ║ ^^^^^^^^^ //│ ╟── type variable `'a` leaks out of its scope //│ ║ l.23: type DNE = forall 'a. Not[Not['a]] -> 'a //│ ║ ^^ //│ ╟── back into type variable `'a` -//│ ║ l.32: case em of Left -> em.v, Right -> nna em.v -//│ ║ ^^^^ +//│ ║ l.23: type DNE = forall 'a. Not[Not['a]] -> 'a +//│ ║ ^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this field selection: //│ ║ l.32: case em of Left -> em.v, Right -> nna em.v //│ ║ ^^^^ //│ ╟── • this reference: -//│ ║ l.396: EM_to_DNE: EM -> DNE +//│ ║ l.393: EM_to_DNE: EM -> DNE //│ ║ ^^^^^^^^^ //│ ╟── • this field selection: //│ ║ l.32: case em of Left -> em.v, Right -> nna em.v -//│ ║ ^^^^ -//│ ╟── Note: constraint arises from type variable: -//│ ║ l.19: type EM = forall 'a. Either['a, Not['a]] -//│ ╙── ^^ +//│ ╙── ^^^^ //│ res: EM -> DNE @@ -430,7 +424,7 @@ def EM_to_DNE em nna = :e // * Still needs distrib! (after "sound extrusion") EM_to_DNE: EM -> DNE //│ ╔══[ERROR] Type error in type ascription -//│ ║ l.431: EM_to_DNE: EM -> DNE +//│ ║ l.425: EM_to_DNE: EM -> DNE //│ ║ ^^^^^^^^^ //│ ╟── type variable `'a` leaks out of its scope //│ ║ l.23: type DNE = forall 'a. Not[Not['a]] -> 'a @@ -440,12 +434,12 @@ EM_to_DNE: EM -> DNE //│ ║ ^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this function: -//│ ║ l.424: def EM_to_DNE em nna = +//│ ║ l.418: def EM_to_DNE em nna = //│ ║ ^^^^^ -//│ ║ l.425: case em of Left -> em.v, Right -> nna em.v +//│ ║ l.419: case em of Left -> em.v, Right -> nna em.v //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── • this reference: -//│ ║ l.431: EM_to_DNE: EM -> DNE +//│ ║ l.425: EM_to_DNE: EM -> DNE //│ ║ ^^^^^^^^^ //│ ╟── Note: constraint arises from type variable: //│ ║ l.19: type EM = forall 'a. Either['a, Not['a]] @@ -461,20 +455,20 @@ def DNE_to_EM dne = :e // * Still needs distrib! (after "sound extrusion") DNE_to_EM: DNE -> EM //│ ╔══[ERROR] Type error in type ascription -//│ ║ l.462: DNE_to_EM: DNE -> EM +//│ ║ l.456: DNE_to_EM: DNE -> EM //│ ║ ^^^^^^^^^ //│ ╟── type variable `'a` leaks out of its scope //│ ║ l.19: type EM = forall 'a. Either['a, Not['a]] //│ ║ ^^ //│ ╟── back into type variable `'a0` -//│ ║ l.456: dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) })) +//│ ║ l.450: dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) })) //│ ║ ^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this reference: -//│ ║ l.462: DNE_to_EM: DNE -> EM +//│ ║ l.456: DNE_to_EM: DNE -> EM //│ ║ ^^^^^^^^^ //│ ╟── • this application: -//│ ║ l.456: dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) })) +//│ ║ l.450: dne (fun not_em -> not_em (Right { v = fun a -> not_em (Left { v = a }) })) //│ ╙── ^^^^^^^^^^^^^^ //│ res: DNE -> EM diff --git a/shared/src/test/diff/fcp/QML_exist_Classes.mls b/shared/src/test/diff/fcp/QML_exist_Classes.mls index b3ea5d1988..09a54eaadc 100644 --- a/shared/src/test/diff/fcp/QML_exist_Classes.mls +++ b/shared/src/test/diff/fcp/QML_exist_Classes.mls @@ -82,20 +82,19 @@ def simpleStepImpl arrImpl = ArraysImpl { update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.Update r0 i a, "updated"); fold = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f b r0 } -//│ simpleStepImpl: ArraysRep[in 'A & 'A0 & 'A1 out 'A0 | 'A, in 'Rep & 'Rep0 & 'a out 'Rep | 'Rep0] -> (ArraysImpl['A1, 'Rep1] with { -//│ fold: forall 'b. ('A0 -> 'b -> 'b) -> 'b -> (('Rep0, anything,),) -> 'b, -//│ init: 'A -> ('Rep, "initialized",), -//│ sub: (('Rep0, anything,),) -> int -> 'A0, -//│ update: forall 'c. (('Rep0 & 'c, anything,),) -> int -> 'A -> ('Rep | 'c, "updated",) +//│ simpleStepImpl: ArraysRep[in ('A | 'A0) & 'A1 & ('A | 'A2) out 'A1 & 'A3 | 'A0 & ('A2 | 'A), in 'Rep & 'Rep0 & 'Rep1 out 'Rep] -> (ArraysImpl['A3, 'Rep2] with { +//│ fold: forall 'b. ('A1 -> 'b -> 'b) -> 'b -> (('Rep, anything,),) -> 'b, +//│ init: 'A2 -> (nothing, "initialized",), +//│ sub: (('Rep0, anything,),) -> int -> 'A, +//│ update: forall 'a. (('Rep1 & 'a, anything,),) -> int -> 'A0 -> ('a, "updated",) //│ }) //│ where -//│ 'Rep1 :> ('Rep | 'd, "initialized" | "updated",) -//│ <: ('Rep0 & 'a, anything,) -//│ 'a <: 'Rep0 & 'd -//│ 'd :> 'Rep -//│ <: 'Rep0 & 'a -//│ 'A1 :> 'A0 -//│ <: 'A +//│ 'Rep2 :> ('c, "initialized" | "updated",) +//│ <: ('Rep & 'd & 'Rep0, anything,) +//│ 'c <: 'Rep & 'd & 'Rep0 +//│ 'd <: 'Rep1 & 'c +//│ 'A3 :> 'A +//│ <: 'A2 & 'A0 //│ = [Function: simpleStepImpl] def simpleStepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)] @@ -103,20 +102,19 @@ def simpleStepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)] //│ = simpleStepImpl_ty = simpleStepImpl -//│ ArraysRep[in 'A & 'A0 & 'A1 out 'A0 | 'A, in 'Rep & 'Rep0 & 'a out 'Rep | 'Rep0] -> (ArraysImpl['A1, 'Rep1] with { -//│ fold: forall 'b. ('A0 -> 'b -> 'b) -> 'b -> (('Rep0, anything,),) -> 'b, -//│ init: 'A -> ('Rep, "initialized",), -//│ sub: (('Rep0, anything,),) -> int -> 'A0, -//│ update: forall 'c. (('Rep0 & 'c, anything,),) -> int -> 'A -> ('Rep | 'c, "updated",) +//│ ArraysRep[in ('A | 'A0) & 'A1 & ('A | 'A2) out 'A1 & 'A3 | 'A0 & ('A2 | 'A), in 'Rep & 'Rep0 & 'Rep1 out 'Rep] -> (ArraysImpl['A3, 'Rep2] with { +//│ fold: forall 'b. ('A1 -> 'b -> 'b) -> 'b -> (('Rep, anything,),) -> 'b, +//│ init: 'A2 -> (nothing, "initialized",), +//│ sub: (('Rep0, anything,),) -> int -> 'A, +//│ update: forall 'a. (('Rep1 & 'a, anything,),) -> int -> 'A0 -> ('a, "updated",) //│ }) //│ where -//│ 'Rep1 :> ('Rep | 'd, "initialized" | "updated",) -//│ <: ('Rep0 & 'a, anything,) -//│ 'a <: 'Rep0 & 'd -//│ 'd :> 'Rep -//│ <: 'Rep0 & 'a -//│ 'A1 :> 'A0 -//│ <: 'A +//│ 'Rep2 :> ('c, "initialized" | "updated",) +//│ <: ('Rep & 'd & 'Rep0, anything,) +//│ 'c <: 'Rep & 'd & 'Rep0 +//│ 'd <: 'Rep1 & 'c +//│ 'A3 :> 'A +//│ <: 'A2 & 'A0 //│ <: simpleStepImpl_ty: //│ ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)] //│ = [Function: simpleStepImpl] @@ -128,14 +126,14 @@ simpleStepImpl_ty = simpleStepImpl :stats simpleStepImpl : ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)] //│ ╔══[ERROR] Subtyping constraint of the form `forall ?a ?b. ?a -> ?b <: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)]` took too many steps and ran out of fuel (10000) -//│ ║ l.129: simpleStepImpl : ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)] +//│ ║ l.127: simpleStepImpl : ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)] //│ ║ ^^^^^^^^^^^^^^ //│ ╙── Note: use flag `:ex` to see internal error info. //│ res: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string,)] //│ = [Function: simpleStepImpl] //│ constrain calls : 9926 //│ annoying calls : 78 -//│ subtyping calls : 28186 +//│ subtyping calls : 28184 // * Note that the above incidentally can be checked using recursive types :RecursiveTypes :stats @@ -166,11 +164,11 @@ def simpleStep: Arrays['a] -> Arrays['a] // * Note: this one fails to type check when the file is typed with `:ConstrainedTypes` def simpleStep arr = arr (fun impl -> fun (k: ArraysRepConsumer['a, 'r]) -> k (simpleStepImpl impl)) -//│ ((forall 'A 'A0 'A1 'Rep 'a. ArraysRep[in 'A & 'A0 & 'A1 out 'A | 'A0, 'Rep] -> ArraysRepConsumer['A, 'a] -> 'a) -> 'b) -> 'b +//│ ((forall 'A 'A0 'A1 'A2 'A3 'a 'Rep 'b. ArraysRep[in ('A0 | 'A) & 'A1 & ('A0 | 'A2) out 'A1 & 'A3 | 'A & ('A2 | 'A0), out 'Rep] -> ArraysRepConsumer['a, 'b] -> 'b) -> 'c) -> 'c //│ where -//│ 'A :> 'A0 -//│ <: 'A1 -//│ 'A1 <: 'A +//│ 'A3 <: 'A2 & 'A & 'a +//│ 'a :> 'A0 +//│ <: 'A3 //│ <: simpleStep: //│ Arrays['a] -> Arrays['a] //│ = [Function: simpleStep] @@ -183,7 +181,7 @@ def simpleStep2: Arrays['a] -> Arrays['a] //│ = def simpleStep2 arr (k: ArraysRepConsumer['a, 'r]) = arr (fun impl -> k (simpleStepImpl impl)) -//│ ((forall 'Rep. ArraysRep['a, 'Rep] -> 'r) -> 'b) -> ArraysRepConsumer['a, 'r] -> 'b +//│ ((forall 'A 'A0 'A1 'Rep. ArraysRep[in 'A & ('A2 | 'A0 & 'A1) out 'A2 & 'A | 'A1 & ('A0 | 'A2), out 'Rep] -> 'r) -> 'a) -> ArraysRepConsumer['A2, 'r] -> 'a //│ <: simpleStep2: //│ Arrays['a] -> Arrays['a] //│ = [Function: simpleStep2] @@ -205,7 +203,7 @@ sb (fun arr -> arr.Sub (arr.Init true) 1) :e // * Type error is expected – argument order confusion sb (fun arr -> arr.Sub 0 (arr.Init true)) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.206: sb (fun arr -> arr.Sub 0 (arr.Init true)) +//│ ║ l.204: sb (fun arr -> arr.Sub 0 (arr.Init true)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type `'Rep` is not an instance of type `int` //│ ║ l.37: type Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r @@ -214,7 +212,7 @@ sb (fun arr -> arr.Sub 0 (arr.Init true)) //│ ║ l.9: method Sub: Rep -> int -> A //│ ║ ^^^ //│ ╟── from application: -//│ ║ l.206: sb (fun arr -> arr.Sub 0 (arr.Init true)) +//│ ║ l.204: sb (fun arr -> arr.Sub 0 (arr.Init true)) //│ ║ ^^^^^^^^^^^^^ //│ ╟── Note: quantified type variable 'Rep is defined at: //│ ║ l.37: type Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r @@ -233,26 +231,26 @@ sb (fun arr -> arr.Update (arr.Init true) 1 false) :e // * Rightly prevent skolem confusion sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) //│ ╔══[ERROR] Type error in application -//│ ║ l.234: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) +//│ ║ l.232: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'Rep` leaks out of its scope //│ ║ l.37: type Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r //│ ║ ^^^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this application: -//│ ║ l.234: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) +//│ ║ l.232: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── • this application: -//│ ║ l.193: sb = simpleStep base +//│ ║ l.191: sb = simpleStep base //│ ║ ^^^^^^^^^^^^^^^ //│ ╟── • this reference: -//│ ║ l.234: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) +//│ ║ l.232: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) //│ ║ ^^ //│ ╟── • this reference: -//│ ║ l.234: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) +//│ ║ l.232: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) //│ ║ ^^^^ //│ ╟── Note: constraint arises from application: -//│ ║ l.234: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) +//│ ║ l.232: sb (fun arr1 -> sb (fun arr2 -> arr2.Update (arr1.Init true))) //│ ╙── ^^^^^^^^^^^^^^ //│ res: error | int -> anything -> anything //│ = [Function (anonymous)] @@ -270,34 +268,33 @@ sb (fun arr -> :e def simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl)) -//│ ((forall 'A 'A0 'A1 'Rep 'Rep0 'a 'c 'd. ArraysRep[in 'A & 'A0 & 'A1 out 'A0 | 'A, in 'Rep & 'Rep0 & 'a out 'Rep | 'Rep0] -> ((forall 'Rep1. ArraysImpl['A1, 'Rep1] with { -//│ fold: forall 'b. ('A0 -> 'b -> 'b) -> 'b -> (('Rep0, anything,),) -> 'b, -//│ init: 'A -> ('Rep, "initialized",), +//│ ((forall 'A 'A0 'A1 'A2 'A3 'Rep 'Rep0 'Rep1 'a 'c 'd. ArraysRep[in ('A0 | 'A) & 'A1 & ('A0 | 'A2) out 'A1 & 'A3 | 'A & ('A2 | 'A0), in 'Rep & 'Rep0 & 'Rep1 out 'Rep] -> ((forall 'Rep2. ArraysImpl['A3, 'Rep2] with { +//│ fold: forall 'b. ('A1 -> 'b -> 'b) -> 'b -> (('Rep, anything,),) -> 'b, +//│ init: 'A2 -> (nothing, "initialized",), //│ sub: (('Rep0, anything,),) -> int -> 'A0, -//│ update: forall 'e. (('Rep0 & 'e, anything,),) -> int -> 'A -> ('Rep | 'e, "updated",) +//│ update: forall 'e. (('Rep1 & 'e, anything,),) -> int -> 'A -> ('e, "updated",) //│ }) -> 'd) -> 'd) -> 'f) -> 'f //│ where -//│ 'Rep1 :> ('Rep | 'c, "initialized" | "updated",) -//│ <: ('Rep0 & 'a, anything,) -//│ 'a <: 'Rep0 & 'c -//│ 'c :> 'Rep -//│ <: 'Rep0 & 'a -//│ 'A1 :> 'A0 -//│ <: 'A +//│ 'Rep2 :> ('a, "initialized" | "updated",) +//│ <: ('Rep & 'c & 'Rep0, anything,) +//│ 'a <: 'Rep & 'c & 'Rep0 +//│ 'c <: 'Rep1 & 'a +//│ 'A3 :> 'A0 +//│ <: 'A2 & 'A //│ <: simpleStep: //│ Arrays['a] -> Arrays['a] //│ ╔══[ERROR] Type error in def definition -//│ ║ l.272: def simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl)) +//│ ║ l.270: def simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'Rep` leaks out of its scope //│ ║ l.37: type Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r //│ ║ ^^^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this applied expression: -//│ ║ l.272: def simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl)) +//│ ║ l.270: def simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl)) //│ ║ ^^^ //│ ╟── • this function: -//│ ║ l.272: def simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl)) +//│ ║ l.270: def simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from reference: //│ ║ l.81: sub = fun ((r0, r1)) -> fun i -> arrImpl.Sub r0 i; @@ -306,38 +303,39 @@ def simpleStep arr = arr (fun impl -> fun k -> k (simpleStepImpl impl)) :e def simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl)) -//│ ((ArraysRep[out 'A, out 'Rep] -> 'a) -> 'c) -> ((forall 'Rep0. ArraysImpl[in 'A & 'A0 out 'A0, 'Rep0] with { -//│ fold: forall 'b. (nothing -> 'b -> 'b) -> 'b -> (('Rep, anything,),) -> 'b, -//│ init: 'A -> (nothing, "initialized",), -//│ sub: (('Rep, anything,),) -> int -> nothing, -//│ update: forall 'd. (('Rep & 'd, anything,),) -> int -> 'A -> ('d, "updated",) +//│ ((forall 'A 'A0 'A1 'Rep. ArraysRep[out 'A & ('A1 | 'A0 & 'A2), in ('Rep0 | 'Rep) & 'Rep1 & 'Rep2 out 'Rep] -> 'a) -> 'c) -> ((ArraysImpl[in 'A3 & 'A4 & 'A5 out 'A2 | 'A5, in ('Rep0 & 'Rep1 & 'Rep2 & 'd, anything,) & 'Rep3 out ('d, "initialized" | "updated",) | 'Rep3] with { +//│ fold: (nothing -> 'b -> 'b) -> 'b -> (('Rep0, anything,),) -> 'b, +//│ init: 'A3 -> (nothing, "initialized",), +//│ sub: (('Rep1, anything,),) -> int -> 'A2, +//│ update: (('Rep2 & 'e, anything,),) -> int -> 'A4 -> ('e, "updated",) //│ }) -> 'a) -> 'c -//│ where -//│ 'Rep0 :> ('e | 'f, "initialized" | "updated",) -//│ <: ('Rep & 'g & 'h, anything,) -//│ 'f :> 'e -//│ <: 'Rep & 'g & 'h -//│ 'h <: 'Rep & 'f -//│ 'e <: 'Rep & 'g -//│ 'g <: 'Rep & 'e //│ <: simpleStep2: //│ Arrays['a] -> Arrays['a] //│ ╔══[ERROR] Type error in def definition -//│ ║ l.308: def simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl)) +//│ ║ l.305: def simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'Rep` leaks out of its scope //│ ║ l.37: type Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r //│ ║ ^^^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this reference: -//│ ║ l.83: fold = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f b r0 -//│ ║ ^^^^^^^ +//│ ║ l.82: update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.Update r0 i a, "updated"); +//│ ║ ^^ //│ ╟── • this reference: -//│ ║ l.308: def simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl)) +//│ ║ l.80: init = fun a -> (arrImpl.Init a, "initialized"); +//│ ║ ^^^^^^^ +//│ ╟── • this reference: +//│ ║ l.305: def simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl)) //│ ║ ^^^^ //│ ╟── • this applied expression: -//│ ║ l.308: def simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl)) -//│ ╙── ^^^ +//│ ║ l.305: def simpleStep2 arr k = arr (fun impl -> k (simpleStepImpl impl)) +//│ ║ ^^^ +//│ ╟── • this reference: +//│ ║ l.81: sub = fun ((r0, r1)) -> fun i -> arrImpl.Sub r0 i; +//│ ║ ^^^^^^^ +//│ ╟── Note: constraint arises from reference: +//│ ║ l.81: sub = fun ((r0, r1)) -> fun i -> arrImpl.Sub r0 i; +//│ ╙── ^^ //│ = [Function: simpleStep21] @@ -380,23 +378,22 @@ def stepImpl arrImpl = ArraysImpl { else (r0, arrImpl.Update r1 (div i 2) a); fold = fun f -> fun b -> fun ((r0, r1)) -> arrImpl.Fold f (arrImpl.Fold f b r0) r1 } -//│ stepImpl: ArraysRep[in 'A & 'A0 & 'A1 out 'A0 | 'A, in 'Rep & 'Rep0 & 'a & 'c out 'Rep | 'Rep0] -> (ArraysImpl['A1, 'Rep1] with { -//│ fold: forall 'b 'b0. ('A0 -> 'b -> 'b & 'A0 -> 'b0 -> ('b & 'b0)) -> ('b & 'b0) -> (('Rep0, 'Rep0,),) -> 'b, -//│ init: 'A -> ('Rep, 'Rep,), -//│ sub: (('Rep0, 'Rep0,),) -> int -> 'A0, -//│ update: forall 'd 'e. (('Rep0 & 'd, 'Rep0 & 'e,),) -> int -> 'A -> ('Rep | 'd, 'Rep | 'e,) +//│ stepImpl: ArraysRep[in 'A & 'A0 & ('A1 | 'A2 | 'A3 | ('A1 | 'A2 | 'A4) & ('A1 | 'A2 & ('A1 | 'A2 | 'A5))) out 'A6 & ('A0 | 'A & ('A3 | 'A4 & ('A1 | 'A2 & 'A5))), in 'Rep & 'Rep0 & ('Rep1 | 'Rep2 | 'Rep3 & 'Rep4) out 'Rep0 & 'a & 'Rep1 & 'Rep3 | 'Rep] -> (ArraysImpl['A6, 'Rep5] with { +//│ fold: forall 'b 'b0. ('A -> 'b -> 'b & 'A0 -> 'b0 -> ('b & 'b0)) -> ('b & 'b0) -> (('Rep, 'Rep0,),) -> 'b, +//│ init: 'A5 -> (nothing, nothing,), +//│ sub: (('Rep6, 'Rep3,),) -> int -> ('A1 | 'A2), +//│ update: forall 'c 'd. (('Rep4 & 'c, 'Rep2 & 'd,),) -> int -> ('A4 & 'A3) -> ('c, 'Rep1 | 'd,) //│ }) //│ where -//│ 'Rep1 :> ('Rep | 'a | 'f, 'Rep | 'g | 'c,) -//│ <: ('Rep0 & 'a, 'Rep0 & 'c,) -//│ 'c <: 'Rep0 & 'g -//│ 'g :> 'Rep -//│ <: 'Rep0 & 'c -//│ 'a <: 'Rep0 & 'f -//│ 'f :> 'Rep -//│ <: 'Rep0 & 'a -//│ 'A1 :> 'A0 -//│ <: 'A +//│ 'Rep5 :> ('e | 'f, 'g | 'a,) +//│ <: ('Rep & 'e & 'Rep6, 'Rep0 & 'a & 'Rep3,) +//│ 'e <: 'Rep & 'Rep4 & 'f & 'Rep6 +//│ 'f <: 'Rep & 'e & 'Rep6 +//│ 'a <: 'Rep0 & 'Rep2 & 'g & 'Rep3 +//│ 'g :> 'Rep1 +//│ <: 'Rep0 & 'a & 'Rep3 +//│ 'A6 :> 'A1 | 'A2 +//│ <: 'A5 & 'A4 & 'A3 //│ = [Function: stepImpl] @@ -405,11 +402,11 @@ def step: Arrays['a] -> Arrays['a] //│ = def step arr = arr (fun impl -> fun (k: ArraysRepConsumer['a, 'r]) -> k (stepImpl impl)) -//│ ((forall 'A 'A0 'A1 'Rep 'a. ArraysRep[in 'A & 'A0 & 'A1 out 'A | 'A0, 'Rep] -> ArraysRepConsumer['A, 'a] -> 'a) -> 'b) -> 'b +//│ ((forall 'A 'A0 'A1 'A2 'A3 'A4 'A5 'A6 'a 'Rep 'Rep0 'b. ArraysRep[in 'A & 'A0 & ('A2 | 'A3 | 'A1 | ('A2 | 'A3 | 'A4) & ('A2 | 'A3 & ('A2 | 'A3 | 'A5))) out 'A6 & ('A0 | 'A & ('A1 | 'A4 & ('A2 | 'A3 & 'A5))), in 'Rep & 'Rep0 out 'Rep0 | 'Rep] -> ArraysRepConsumer['a, 'b] -> 'b) -> 'c) -> 'c //│ where -//│ 'A :> 'A0 -//│ <: 'A1 -//│ 'A1 <: 'A +//│ 'A6 <: 'A5 & 'A4 & 'A1 & 'a +//│ 'a :> 'A2 | 'A3 +//│ <: 'A6 //│ <: step: //│ Arrays['a] -> Arrays['a] //│ = [Function: step] @@ -420,7 +417,7 @@ def step2: Arrays['a] -> Arrays['a] //│ = def step2 arr (k: ArraysRepConsumer['a, 'r]) = arr (fun impl -> k (simpleStepImpl impl)) -//│ ((forall 'Rep. ArraysRep['a, 'Rep] -> 'r) -> 'b) -> ArraysRepConsumer['a, 'r] -> 'b +//│ ((forall 'A 'A0 'A1 'Rep. ArraysRep[in 'A & ('A2 | 'A0 & 'A1) out 'A2 & 'A | 'A1 & ('A0 | 'A2), out 'Rep] -> 'r) -> 'a) -> ArraysRepConsumer['A2, 'r] -> 'a //│ <: step2: //│ Arrays['a] -> Arrays['a] //│ = [Function: step2] @@ -452,11 +449,11 @@ ssb (fun arr -> rec def mkMonoArray n = if n == 0 then base else step (mkMonoArray(n - 1)) -//│ mkMonoArray: int -> Arrays['a] +//│ mkMonoArray: int -> Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function: mkMonoArray] snb = mkMonoArray 5 -//│ snb: Arrays['a] +//│ snb: Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function (anonymous)] snb (fun arr -> arr.Init true) @@ -469,11 +466,11 @@ snb (fun arr -> arr.Init true) rec def mkMonoArray n = if n == 0 then base else step2 (mkMonoArray(n - 1)) -//│ mkMonoArray: int -> Arrays['a] +//│ mkMonoArray: int -> Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function: mkMonoArray1] snb = mkMonoArray 5 -//│ snb: Arrays['a] +//│ snb: Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function (anonymous)] snb (fun arr -> arr.Init true) diff --git a/shared/src/test/diff/fcp/QML_exist_Classes_min.mls b/shared/src/test/diff/fcp/QML_exist_Classes_min.mls index fff2ca6edd..aad74be97b 100644 --- a/shared/src/test/diff/fcp/QML_exist_Classes_min.mls +++ b/shared/src/test/diff/fcp/QML_exist_Classes_min.mls @@ -52,25 +52,10 @@ mkArrays impl k = k impl // * Inconsistent bounds on 'Rep after type avoidance during extrusion (<- not sure comment is still current) :e def stepped = arr (fun arrImpl -> fun k -> k (simpleStepImpl arrImpl)) -//│ ╔══[ERROR] Type error in application -//│ ║ l.54: def stepped = arr (fun arrImpl -> fun k -> k (simpleStepImpl arrImpl)) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── type variable `'Rep` leaks out of its scope -//│ ║ l.18: type Arrays[A] = (forall 'Rep. ArraysRep[A, 'Rep] -> 'r) -> 'r -//│ ║ ^^^^ -//│ ╟── adding a type annotation to any of the following terms may help resolve the problem -//│ ╟── • this function: -//│ ║ l.54: def stepped = arr (fun arrImpl -> fun k -> k (simpleStepImpl arrImpl)) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── • this reference: -//│ ║ l.54: def stepped = arr (fun arrImpl -> fun k -> k (simpleStepImpl arrImpl)) -//│ ║ ^^^ -//│ ╟── Note: constraint arises from reference: -//│ ║ l.23: update = fun ((r0, r1)) -> fun i -> fun a -> (arrImpl.Update r0 i a, "updated") -//│ ╙── ^^ -//│ stepped: error +//│ stepped: ((ArraysImpl[int, in (??Rep, anything,) & 'Rep out (anything, "updated",) | 'Rep] with {update: ((??Rep, anything,),) -> int -> int -> (anything, "updated",)}) -> 'a) -> 'a //│ = //│ arr is not implemented +//│ TEST CASE FAILURE: There was an unexpected lack of type error def stepped = arr (fun arrImpl -> fun (k: forall 'Rep. ArraysRep[int, 'Rep] -> 'r) -> k (simpleStepImpl arrImpl)) diff --git a/shared/src/test/diff/fcp/QML_exist_Records_D.mls b/shared/src/test/diff/fcp/QML_exist_Records_D.mls index a7fadb762e..6eeed8f98f 100644 --- a/shared/src/test/diff/fcp/QML_exist_Records_D.mls +++ b/shared/src/test/diff/fcp/QML_exist_Records_D.mls @@ -186,11 +186,11 @@ ssb (fun arr -> rec def mkMonoArray n = if n == 0 then base else step (mkMonoArray (n - 1)) -//│ mkMonoArray: int -> Arrays['a] +//│ mkMonoArray: int -> Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function: mkMonoArray] snb = mkMonoArray 3 -//│ snb: Arrays['a] +//│ snb: Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function (anonymous)] // * Here we are trying to leak the internally-quantified representation, resulting in `anything` being returned @@ -257,11 +257,11 @@ ssb (fun arr -> rec def mkMonoArray n = if n == 0 then base else step2 (mkMonoArray (n - 1)) -//│ mkMonoArray: int -> Arrays['a] +//│ mkMonoArray: int -> Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function: mkMonoArray1] snb = mkMonoArray 3 -//│ snb: Arrays['a] +//│ snb: Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function (anonymous)] // * Here we are trying to leak the internally-quantified representation, resulting in `anything` being returned @@ -328,7 +328,7 @@ def step arr = arr (fun impl -> fun k -> k (stepImpl_ty impl)) :e def step (arr: Arrays['a]) = arr (fun impl -> fun k -> k (stepImpl impl)) //│ Arrays['a] -> ({ -//│ fold: forall 'b. ('a -> 'b -> 'b) -> 'b -> ((??rep, anything,),) -> 'b, +//│ fold: ('a -> 'b -> 'b) -> 'b -> ((??rep, anything,),) -> 'b, //│ init: 'a -> (anything, "hi",), //│ sub: ((??rep, anything,),) -> int -> 'a, //│ update: ((??rep, anything,),) -> int -> 'a -> (anything, "hey",) @@ -359,6 +359,19 @@ def step arr = arr (forall 'a. fun impl -> forall 'r. fun (k: ArraysImplConsumer //│ ((forall 'a 'r 'r0. ArraysImpl['a, 'r] -> ArraysImplConsumer['a, 'r0] -> 'r0) -> 'b) -> 'b //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type mismatch in def definition: +//│ ║ l.358: def step arr = arr (forall 'a. fun impl -> forall 'r. fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `'r` does not match type `'r0` +//│ ║ l.20: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── Note: constraint arises from rigid type variable: +//│ ║ l.358: def step arr = arr (forall 'a. fun impl -> forall 'r. fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl)) +//│ ║ ^^ +//│ ╟── Note: quantified type variable 'r is defined at: +//│ ║ l.20: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ╙── ^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step7] // * ...unless we use `stepImpl_ty` instead of `stepImpl` @@ -369,6 +382,19 @@ def step arr = arr (fun impl -> forall 'r. fun (k: ArraysImplConsumer['a, 'r]) - //│ <: 'a0 //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type mismatch in def definition: +//│ ║ l.378: def step arr = arr (fun impl -> forall 'r. fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_ty impl)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `'r` does not match type `'r0` +//│ ║ l.20: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── Note: constraint arises from rigid type variable: +//│ ║ l.378: def step arr = arr (fun impl -> forall 'r. fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_ty impl)) +//│ ║ ^^ +//│ ╟── Note: quantified type variable 'r is defined at: +//│ ║ l.20: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ╙── ^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step8] diff --git a/shared/src/test/diff/fcp/QML_exist_Records_ND.mls b/shared/src/test/diff/fcp/QML_exist_Records_ND.mls index 67a2268cc9..721f96a375 100644 --- a/shared/src/test/diff/fcp/QML_exist_Records_ND.mls +++ b/shared/src/test/diff/fcp/QML_exist_Records_ND.mls @@ -135,11 +135,26 @@ def helper impl (k: ArraysImplConsumer['a, 'res]) = k (stepImpl impl) // * FIXME why does this require so much fuel?! :Fuel 50000 def step (arr: Arrays['a]) = arr helper -//│ Arrays['a] -> (forall 'a0 'b. ArraysImplConsumer['a0, 'b] -> 'b) -//│ where -//│ 'a0 := 'a +//│ Arrays['a] -> ArraysImplConsumer['a, 'b] -> 'b //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type error in def definition +//│ ║ l.137: def step (arr: Arrays['a]) = arr helper +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `'r` leaks out of its scope +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── back into type variable `'r` +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.137: def step (arr: Arrays['a]) = arr helper +//│ ║ ^^^^^^^^^^ +//│ ╟── • this application: +//│ ║ l.128: def helper impl (k: ArraysImplConsumer['a, 'res]) = k (stepImpl impl) +//│ ╙── ^^^^^^^^^^^^^^^^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step] :ResetFuel @@ -155,6 +170,23 @@ def step arr = arr helper //│ ((forall 'a 'r. ArraysImpl['a, 'r] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)) -> 'c) -> 'c //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type error in def definition +//│ ║ l.169: def step arr = arr helper +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `'r` leaks out of its scope +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── back into type variable `'r` +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.169: def step arr = arr helper +//│ ║ ^^^^^^^^^^ +//│ ╟── • this application: +//│ ║ l.163: def helper = forall 'a. fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl) +//│ ╙── ^^^^^^^^^^^^^^^^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step1] // * In one go: <------------------------ this is probably the most canonical definition of `step` in this file @@ -163,6 +195,20 @@ def step arr = arr (forall 'a. fun impl -> fun (k: ArraysImplConsumer['a, 'r]) - //│ ((forall 'a 'r. ArraysImpl['a, 'r] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)) -> 'c) -> 'c //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type error in def definition +//│ ║ l.194: def step arr = arr (forall 'a. fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `'r` leaks out of its scope +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── back into type variable `'r` +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.194: def step arr = arr (forall 'a. fun impl -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl impl)) +//│ ╙── ^^^^^^^^^^^^^^^^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step2] @@ -184,17 +230,25 @@ def helper (impl: ArraysImpl['a, 'rep]) (k: ArraysImplConsumer['b, 'res]) = k (s // * which is used for reconstraining, then this no longer require extra fuel! :e def step (arr: Arrays['a]) = arr helper -//│ Arrays['a] -> error +//│ Arrays['a] -> ArraysImplConsumer['a, 'b] -> 'b //│ <: step: //│ Arrays['a] -> Arrays['a] -//│ ╔══[ERROR] Subtyping constraint of the form `Arrays['a] <: (forall 'a0 'rep. ArraysImpl['a0, 'rep] -> (forall ?a 'b 'res. ArraysImplConsumer['b, 'res] -> ?a)) -> ?b` took too many steps and ran out of fuel (10000) -//│ ║ l.186: def step (arr: Arrays['a]) = arr helper -//│ ║ ^^^^^^^^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Subtyping constraint of the form `forall 'a ?a. Arrays['a] -> ?a <: forall 'a0. Arrays['a0] -> Arrays['a0]` took too many steps and ran out of fuel (10000) -//│ ║ l.186: def step (arr: Arrays['a]) = arr helper +//│ ╔══[ERROR] Type error in def definition +//│ ║ l.232: def step (arr: Arrays['a]) = arr helper //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. +//│ ╟── type variable `'r` leaks out of its scope +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── back into type variable `'r` +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.232: def step (arr: Arrays['a]) = arr helper +//│ ║ ^^^^^^^^^^ +//│ ╟── • this application: +//│ ║ l.217: def helper (impl: ArraysImpl['a, 'rep]) (k: ArraysImplConsumer['b, 'res]) = k (stepImpl impl) +//│ ╙── ^^^^^^^^^^^^^^^^^ //│ = [Function: step3] @@ -210,9 +264,29 @@ def helper = forall 'a 'rep. fun (impl: ArraysImpl['a, 'rep]) -> //│ = [Function: helper3] def step (arr: Arrays['a]) = arr helper -//│ Arrays['a] -> (forall 'res. ArraysImplConsumer['a, 'res] -> 'res) +//│ Arrays['a] -> ArraysImplConsumer['a, 'res] -> 'res //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type error in def definition +//│ ║ l.266: def step (arr: Arrays['a]) = arr helper +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `'r` leaks out of its scope +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── back into type variable `'r` +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this quantified type variable: +//│ ║ l.262: forall 'res. fun (k: ArraysImplConsumer['a, 'res]) -> k (stepImpl impl) +//│ ║ ^^^^ +//│ ╟── • this application: +//│ ║ l.266: def step (arr: Arrays['a]) = arr helper +//│ ║ ^^^^^^^^^^ +//│ ╟── • this application: +//│ ║ l.262: forall 'res. fun (k: ArraysImplConsumer['a, 'res]) -> k (stepImpl impl) +//│ ╙── ^^^^^^^^^^^^^^^^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step4] @@ -238,54 +312,29 @@ def helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl impl) :e def step (arr: Arrays['a]) = arr helper -//│ Arrays['a] -> (forall 'c. error | ({ -//│ fold: forall 'b 'b0. ('a0 -> 'b -> ('b & 'b0)) -> (forall 'd. ('b & 'd) -> (('rep & 'rep0, anything,),) -> ('d | 'b0)), -//│ init: ('a & 'a0) -> ('rep, "hi",), -//│ sub: (('rep & 'rep0, anything,),) -> int -> 'a0, -//│ update: (('rep & 'rep0, anything,),) -> int -> ('a & 'a0) -> ('rep, "hey",) -//│ } -> 'c) -> 'c) -//│ where -//│ 'rep :> anything -//│ <: 'rep0 -//│ 'rep0 <: ??rep & 'rep -//│ 'a <: 'a0 -//│ 'a0 := 'a +//│ Arrays['a] -> ({ +//│ fold: ('a -> 'b -> 'b) -> 'b -> ((??rep, anything,),) -> 'b, +//│ init: 'a -> (anything, "hi",), +//│ sub: ((??rep, anything,),) -> int -> 'a, +//│ update: ((??rep, anything,),) -> int -> 'a -> (anything, "hey",) +//│ } -> 'c) -> 'c //│ <: step: //│ Arrays['a] -> Arrays['a] -//│ ╔══[ERROR] Type error in application -//│ ║ l.240: def step (arr: Arrays['a]) = arr helper -//│ ║ ^^^^^^^^^^ -//│ ╟── type variable `'rep` leaks out of its scope -//│ ║ l.19: type ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R -//│ ║ ^^^^ -//│ ╟── adding a type annotation to any of the following terms may help resolve the problem -//│ ╟── • this function: -//│ ║ l.230: def helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl impl) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── • this reference: -//│ ║ l.240: def step (arr: Arrays['a]) = arr helper -//│ ║ ^^^^^^ -//│ ╟── • this reference: -//│ ║ l.240: def step (arr: Arrays['a]) = arr helper -//│ ║ ^^^ -//│ ╟── Note: constraint arises from type variable: -//│ ║ l.93: def stepImpl (arrImpl: ArraysImpl['a, 'r]) = { -//│ ╙── ^^ //│ ╔══[ERROR] Type error in def definition -//│ ║ l.240: def step (arr: Arrays['a]) = arr helper +//│ ║ l.314: def step (arr: Arrays['a]) = arr helper //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'rep` leaks out of its scope //│ ║ l.19: type ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R //│ ║ ^^^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this function: -//│ ║ l.230: def helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl impl) +//│ ║ l.304: def helper (impl: ArraysImpl['a, 'rep]) k = k (stepImpl impl) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── • this reference: -//│ ║ l.240: def step (arr: Arrays['a]) = arr helper +//│ ║ l.314: def step (arr: Arrays['a]) = arr helper //│ ║ ^^^^^^ //│ ╟── • this reference: -//│ ║ l.240: def step (arr: Arrays['a]) = arr helper +//│ ║ l.314: def step (arr: Arrays['a]) = arr helper //│ ║ ^^^ //│ ╟── Note: constraint arises from reference: //│ ║ l.95: sub = fun ((r0, r1)) -> fun i -> arrImpl.sub r0 i; @@ -315,7 +364,7 @@ def step = forall 'a. fun arr -> arr (fun impl -> (fun k -> k (stepImpl impl)) : // * This one is wrong (notice the extrusion in the type): def step_ arr = forall 'a. arr (fun (impl : ArraysImpl['a, 'rep]) -> (fun k -> k (stepImpl impl)) : Arrays['a]) -//│ step_: ((forall 'rep. ArraysImpl[in ??a out ??a0, 'rep] -> Arrays[in ??a out ??a0]) -> 'a) -> 'a +//│ step_: ((ArraysImpl[in ??a out ??a0, 'rep] -> Arrays[in ??a out ??a0]) -> 'a) -> 'a //│ = [Function: step_] def step = forall 'a. fun arr -> arr (fun (impl : ArraysImpl['a, 'rep]) -> (fun k -> k (stepImpl impl)) : Arrays['a]) @@ -361,6 +410,23 @@ def step arr = arr helper //│ ((forall 'a2 'r. ArraysImpl['a2, 'r] -> (forall 'a. ArraysImplConsumer['a2, 'a] -> 'a)) -> 'b) -> 'b //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type error in def definition +//│ ║ l.409: def step arr = arr helper +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `'r` leaks out of its scope +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── back into type variable `'r` +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.409: def step arr = arr helper +//│ ║ ^^^^^^^^^^ +//│ ╟── • this application: +//│ ║ l.405: def helper = forall 'a2. fun impl -> fun (k: ArraysImplConsumer['a2, 'res]) -> k (stepImpl_ty impl) +//│ ╙── ^^^^^^^^^^^^^^^^^^^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step10] @@ -376,6 +442,23 @@ def step arr = arr helper //│ ((forall 'a 'rep. ArraysImpl['a, 'rep] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)) -> 'c) -> 'c //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type error in def definition +//│ ║ l.441: def step arr = arr helper +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `'r` leaks out of its scope +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── back into type variable `'r` +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.441: def step arr = arr helper +//│ ║ ^^^^^^^^^^ +//│ ╟── • this application: +//│ ║ l.434: def helper (impl: ArraysImpl['a, 'rep]) (k: ArraysImplConsumer['a2, 'res]) = k (stepImpl_ty impl) +//│ ╙── ^^^^^^^^^^^^^^^^^^^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step11] :ResetFuel @@ -389,6 +472,23 @@ def step arr = arr helper //│ ((forall 'a 'rep. ArraysImpl['a, 'rep] -> (forall 'b. ArraysImplConsumer['a, 'b] -> 'b)) -> 'c) -> 'c //│ <: step: //│ Arrays['a] -> Arrays['a] +//│ ╔══[ERROR] Type error in def definition +//│ ║ l.471: def step arr = arr helper +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `'r` leaks out of its scope +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── back into type variable `'r` +//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r +//│ ║ ^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.471: def step arr = arr helper +//│ ║ ^^^^^^^^^^ +//│ ╟── • this application: +//│ ║ l.467: def helper = forall 'a 'rep. fun (impl: ArraysImpl['a, 'rep]) -> fun (k: ArraysImplConsumer['a, 'r]) -> k (stepImpl_ty impl) +//│ ╙── ^^^^^^^^^^^^^^^^^^^^ +//│ TEST CASE FAILURE: There was an unexpected type error //│ = [Function: step12] :DontGeneralizeCurriedFunctions @@ -473,11 +573,11 @@ ssb (fun arr -> rec def mkMonoArray n = if n == 0 then base else step (mkMonoArray (n - 1)) -//│ mkMonoArray: int -> (forall 'a. Arrays['a]) +//│ mkMonoArray: int -> (forall 'a. Arrays[in 'a0 | 'a out 'a0 & 'a]) //│ = [Function: mkMonoArray] snb = mkMonoArray 3 -//│ snb: Arrays['a] +//│ snb: Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function (anonymous)] // * Here we are trying to leak the internally-quantified representation, resulting in extruded types being returned @@ -536,17 +636,17 @@ def step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (ste //│ <: step2: //│ Arrays['a] -> Arrays['a] //│ ╔══[ERROR] Type error in def definition -//│ ║ l.534: def step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl)) +//│ ║ l.634: def step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'rep` leaks out of its scope //│ ║ l.19: type ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R //│ ║ ^^^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this reference: -//│ ║ l.534: def step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl)) +//│ ║ l.634: def step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl)) //│ ║ ^^^^ //│ ╟── • this reference: -//│ ║ l.534: def step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl)) +//│ ║ l.634: def step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (stepImpl_ty impl)) //│ ║ ^^^ //│ ╟── Note: constraint arises from type variable: //│ ║ l.88: def stepImpl_ty: ArraysImpl['a, 'r] -> ArraysImpl['a, ('r, string)] @@ -557,69 +657,75 @@ def step2 = forall 'a. fun (arr: Arrays['a]) -> fun k -> arr (fun impl -> k (ste def step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl)) // * Or equivalently: // def step = forall 'a. fun arr -> forall 'rep. fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl)) -//│ ((forall 'r. ArraysImpl['a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b +//│ ((ArraysImpl['a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b //│ <: step2: //│ Arrays['a] -> Arrays['a] //│ ╔══[ERROR] Type error in def definition -//│ ║ l.557: def step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl)) +//│ ║ l.657: def step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── type variable `'r` leaks out of its scope -//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r -//│ ║ ^^ -//│ ╟── back into type variable `'r` -//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r -//│ ║ ^^ +//│ ╟── type variable `'rep` leaks out of its scope +//│ ║ l.19: type ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R +//│ ║ ^^^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem -//│ ╟── • this application: -//│ ║ l.557: def step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl)) -//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── • this applied expression: +//│ ║ l.657: def step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl)) +//│ ║ ^^^ +//│ ╟── • this function: +//│ ║ l.657: def step2 = forall 'a. fun arr -> fun (k: ArraysImplConsumer['a, 'rep]) -> arr (fun impl -> k (stepImpl_ty impl)) +//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ = [Function: step26] // * FIXME why is this displayed as `'a <: nothing`? Simplification bug? def s arr (k: ArraysImplConsumer['a, 'rep]) = arr (fun impl -> k (stepImpl_ty impl)) -//│ s: ((forall 'r. ArraysImpl['a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b +//│ s: ((ArraysImpl[in 'a out 'a | 'a0, 'r] -> 'rep) -> 'b) -> (forall 'a1. ArraysImplConsumer['a1, 'rep] -> 'b) +//│ where +//│ 'a1 :> 'a +//│ <: 'a0 //│ = [Function: s] // * We can see it shouldn't be simplified to nothing: :ns s -//│ res: forall 'b 'a 'a0 'rep 'c. 'b -> (forall 'a1 'rep0 'd. ArraysImplConsumer['a1, 'rep0] -> 'd) +//│ res: forall 'b 'c 'a 'a0 'a1 'a2 'r 'r0 'd 'rep 'e. 'b -> (forall 'a3 'rep0 'f. ArraysImplConsumer['a3, 'rep0] -> 'f) //│ where -//│ 'd :> 'c +//│ 'f :> 'e //│ 'rep0 <: 'rep -//│ 'a1 :> 'a0 -//│ <: 'a -//│ 'b <: (forall 'r 'e 'a2 'f. 'e -> 'f) -> 'c -//│ 'f :> 'rep -//│ 'e <: ArraysImpl['a2, 'r] -//│ 'a2 :> 'a -//│ <: 'a0 +//│ 'a3 :> 'a0 +//│ <: 'a2 +//│ 'b <: ('c -> 'd) -> 'e +//│ 'd :> 'rep +//│ 'c <: ArraysImpl[in 'a out 'a1, in 'r out 'r0] +//│ 'r0 :> 'r +//│ 'a1 :> 'a | 'a2 +//│ 'a2 :> 'a0 //│ 'a <: 'a0 -//│ 'a0 <: 'a //│ = [Function: s] // * BTW: this doesn't work (same reason as before: k needs an annotation) :e step2 = s -//│ ((forall 'r. ArraysImpl['a, 'r] -> 'rep) -> 'b) -> ArraysImplConsumer['a, 'rep] -> 'b +//│ ((ArraysImpl[in 'a out 'a | 'a0, 'r] -> 'rep) -> 'b) -> (forall 'a1. ArraysImplConsumer['a1, 'rep] -> 'b) +//│ where +//│ 'a1 :> 'a +//│ <: 'a0 //│ <: step2: //│ Arrays['a] -> Arrays['a] //│ ╔══[ERROR] Type error in def definition -//│ ║ l.603: step2 = s +//│ ║ l.706: step2 = s //│ ║ ^^^^^^^^^ -//│ ╟── type variable `'r` leaks out of its scope -//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r -//│ ║ ^^ -//│ ╟── back into type variable `'r` -//│ ║ l.22: type Arrays[A] = forall 'r. ArraysImplConsumer[A, 'r] -> 'r -//│ ║ ^^ +//│ ╟── type variable `'rep` leaks out of its scope +//│ ║ l.19: type ArraysImplConsumer[A, R] = forall 'rep. ArraysImpl[A, 'rep] -> R +//│ ║ ^^^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this applied expression: +//│ ║ l.680: def s arr (k: ArraysImplConsumer['a, 'rep]) = arr (fun impl -> k (stepImpl_ty impl)) +//│ ║ ^^^ +//│ ╟── • this function: +//│ ║ l.680: def s arr (k: ArraysImplConsumer['a, 'rep]) = arr (fun impl -> k (stepImpl_ty impl)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── • this reference: -//│ ║ l.603: step2 = s -//│ ║ ^ -//│ ╟── • this application: -//│ ║ l.580: def s arr (k: ArraysImplConsumer['a, 'rep]) = arr (fun impl -> k (stepImpl_ty impl)) -//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.706: step2 = s +//│ ╙── ^ //│ = [Function: s] @@ -641,11 +747,11 @@ ssb (fun arr -> rec def mkMonoArray n = if n == 0 then base else step2 (mkMonoArray (n - 1)) -//│ mkMonoArray: int -> (forall 'a. Arrays['a]) +//│ mkMonoArray: int -> (forall 'a. Arrays[in 'a0 | 'a out 'a0 & 'a]) //│ = [Function: mkMonoArray1] snb = mkMonoArray 3 -//│ snb: Arrays['a] +//│ snb: Arrays[in 'a | 'a0 out 'a & 'a0] //│ = [Function (anonymous)] // * Here we are trying to leak the internally-quantified representation, resulting in extruded types being returned diff --git a/shared/src/test/diff/fcp/QML_exist_Records_min_1.mls b/shared/src/test/diff/fcp/QML_exist_Records_min_1.mls index b39b761b03..d0ada3a180 100644 --- a/shared/src/test/diff/fcp/QML_exist_Records_min_1.mls +++ b/shared/src/test/diff/fcp/QML_exist_Records_min_1.mls @@ -153,22 +153,19 @@ def step arr k = k (arr stepImpl) //│ ║ l.142: def step arr k = k (arr stepImpl) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'b` leaks out of its scope -//│ ║ l.126: type ArraysImpl2[Rep] = { fold: forall 'b. 'b -> Rep -> 'b } -//│ ║ ^^ +//│ ║ l.132: def stepImpl arrImpl = { fold = fun f -> fun r0 -> arrImpl.fold f r0 } +//│ ║ ^ //│ ╟── back into type variable `'b` //│ ║ l.126: type ArraysImpl2[Rep] = { fold: forall 'b. 'b -> Rep -> 'b } -//│ ║ ^^ +//│ ║ ^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem -//│ ╟── • this function: -//│ ║ l.132: def stepImpl arrImpl = { fold = fun f -> fun r0 -> arrImpl.fold f r0 } -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── • this application: -//│ ║ l.142: def step arr k = k (arr stepImpl) -//│ ║ ^^^^^^^^^^^^ //│ ╟── • this applied expression: //│ ║ l.142: def step arr k = k (arr stepImpl) //│ ║ ^ -//│ ╟── Note: constraint arises from application: +//│ ╟── • this application: +//│ ║ l.142: def step arr k = k (arr stepImpl) +//│ ║ ^^^^^^^^^^^^ +//│ ╟── • this application: //│ ║ l.132: def stepImpl arrImpl = { fold = fun f -> fun r0 -> arrImpl.fold f r0 } //│ ╙── ^^^^^^^^^^^^^^^^^ diff --git a/shared/src/test/diff/fcp/QML_exist_Records_min_3.mls b/shared/src/test/diff/fcp/QML_exist_Records_min_3.mls index 79e4c290c5..7d497739be 100644 --- a/shared/src/test/diff/fcp/QML_exist_Records_min_3.mls +++ b/shared/src/test/diff/fcp/QML_exist_Records_min_3.mls @@ -15,22 +15,24 @@ def stepImpl_ty: ArraysImpl['a] -> ArraysImpl['a] // * There used to be a wrongly-simplified `'a <: nothing` bound here def s arr (k: ArraysImplConsumer['a]) = arr (fun impl -> k (stepImpl_ty impl)) -//│ s: ((ArraysImpl['a] -> int) -> 'b) -> ArraysImplConsumer['a] -> 'b +//│ s: ((ArraysImpl[in 'a out 'a | 'a0] -> int) -> 'b) -> (forall 'a1. ArraysImplConsumer['a1] -> 'b) +//│ where +//│ 'a1 :> 'a +//│ <: 'a0 // * ...although we could see that it shouldn't be simplified to nothing: :ns s -//│ res: forall 'b 'a 'a0 'c. 'b -> (forall 'a1 'd. ArraysImplConsumer['a1] -> 'd) +//│ res: forall 'b 'c 'a 'a0 'a1 'a2 'd 'e. 'b -> (forall 'a3 'f. ArraysImplConsumer['a3] -> 'f) //│ where -//│ 'd :> 'c -//│ 'a1 :> 'a0 -//│ <: 'a -//│ 'b <: (forall 'e 'a2 'f. 'e -> 'f) -> 'c -//│ 'f :> int -//│ 'e <: ArraysImpl['a2] -//│ 'a2 :> 'a -//│ <: 'a0 +//│ 'f :> 'e +//│ 'a3 :> 'a0 +//│ <: 'a2 +//│ 'b <: ('c -> 'd) -> 'e +//│ 'd :> int +//│ 'c <: ArraysImpl[in 'a out 'a1] +//│ 'a1 :> 'a | 'a2 +//│ 'a2 :> 'a0 //│ 'a <: 'a0 -//│ 'a0 <: 'a diff --git a/shared/src/test/diff/fcp/QML_exist_nu.mls b/shared/src/test/diff/fcp/QML_exist_nu.mls index a2bb1e2b70..0610ba5514 100644 --- a/shared/src/test/diff/fcp/QML_exist_nu.mls +++ b/shared/src/test/diff/fcp/QML_exist_nu.mls @@ -224,9 +224,9 @@ class StepAlt'[A](from: Arrays[A]) extends Arrays[A] { // * 1. ArraysImpl[A, 'rep] -> 'res <: (StepImpl[A, impl] -> 'r) -> 'r // * which eventually leads to 'rep := impl and 'r := 'res. } -//│ ╔══[ERROR] Type error in application +//│ ╔══[ERROR] Type error in definition of value use //│ ║ l.211: val use = from.use of impl => -//│ ║ ^^^^^^^^^^^^^^^^^^^ +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ║ l.212: k => k(StepImpl(impl)) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'rep` leaks out of its scope @@ -244,12 +244,24 @@ class StepAlt'[A](from: Arrays[A]) extends Arrays[A] { //│ ╟── • this field selection: //│ ║ l.211: val use = from.use of impl => //│ ╙── ^^^^^^^^ +//│ ╔══[ERROR] Type error in definition of value use +//│ ║ l.211: val use = from.use of impl => +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.212: k => k(StepImpl(impl)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `'res` leaks out of its scope +//│ ║ l.40: fun use: ArraysImplConsumer[A, 'res] -> 'res +//│ ║ ^^^^ +//│ ╟── back into type variable `'res` +//│ ║ l.40: fun use: ArraysImplConsumer[A, 'res] -> 'res +//│ ║ ^^^^ +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.212: k => k(StepImpl(impl)) +//│ ╙── ^^^^^^^^^^^^^^^^^ //│ class StepAlt'[A](from: Arrays[A]) extends Arrays { -//│ val use: forall 'R 'a. error | (StepImpl[A, 'R] -> 'a) -> 'a +//│ val use: (StepImpl[A, in ??rep] -> ??res) -> anything //│ } -//│ where -//│ 'R :> ??rep -//│ <: ??rep0 //│ Syntax error: //│ Unexpected string diff --git a/shared/src/test/diff/fcp/SystemF_2.mls b/shared/src/test/diff/fcp/SystemF_2.mls index 9df044c916..54adc33c72 100644 --- a/shared/src/test/diff/fcp/SystemF_2.mls +++ b/shared/src/test/diff/fcp/SystemF_2.mls @@ -38,7 +38,7 @@ id iter2 iter2 iter2 iter2 K //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> ? -> ? -> 'a +//│ 'a :> #? -> #? -> 'a //│ ╙── //│ res: 'a -> anything -> 'b //│ where @@ -97,7 +97,7 @@ c2 = succ (succ n0) c2 c2 K //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> ? -> 'a +//│ 'a :> #? -> 'a //│ ╙── //│ res: ('a & 'X) -> (anything -> 'a | 'X) //│ where @@ -127,10 +127,10 @@ c2_ c2_! c2_ c2_ K //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> ? -> ('a | 'b | 'c | 'd) -//│ 'c :> ? -> ('d | 'b) | ? -> ('b | 'c) -//│ 'd :> ? -> ('c | 'b) -//│ 'b :> ? -> ('a | 'b) +//│ 'a :> #? -> ('a | 'b | 'c | 'd) +//│ 'c :> #? -> ('d | 'b) | #? -> ('b | 'c) +//│ 'd :> #? -> ('c | 'b) +//│ 'b :> #? -> ('a | 'b) //│ ╙── //│ res: ('a & 'b & 'c) -> anything -> ('d | 'e) //│ where @@ -153,7 +153,7 @@ c2__ c2__ c2__ c2__ K //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> ? -> ? -> 'a +//│ 'a :> #? -> #? -> 'a //│ ╙── //│ res: 'a -> anything -> 'b //│ where @@ -327,7 +327,7 @@ c2 = succ (succ n0) c2 c2 K //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> ? -> 'a +//│ 'a :> #? -> 'a //│ ╙── //│ res: ('a & 'X) -> (anything -> 'a | 'X) //│ where @@ -370,7 +370,7 @@ c2_ c2_ c2_ c2_ K //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> forall 'b 'c 'd 'e. ('b & 'e) -> (? -> 'e | 'd) +//│ 'a :> forall 'b 'c 'd 'e. ('b & 'e) -> (#? -> 'e | 'd) //│ where //│ forall 'f. 'f -> (forall 'g 'h 'i. 'g -> 'i //│ where diff --git a/shared/src/test/diff/fcp/ToChurchSimplif_CT.mls b/shared/src/test/diff/fcp/ToChurchSimplif_CT.mls index 23bac46b06..de55cc0c98 100644 --- a/shared/src/test/diff/fcp/ToChurchSimplif_CT.mls +++ b/shared/src/test/diff/fcp/ToChurchSimplif_CT.mls @@ -555,7 +555,7 @@ rec def to_ch n = else s (to_ch (n - 1)) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> forall 'b 'c 'd 'e. (? & 'b) -> (('e & 'c) -> ('e | 'd) +//│ 'a :> forall 'b 'c 'd 'e. (#? & 'b) -> (('e & 'c) -> ('e | 'd) //│ where //│ 'a <: 'b -> 'c -> 'd) //│ ╙── @@ -572,7 +572,7 @@ rec def to_ch n = to_church = to_ch //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> forall 'b 'c 'd 'e. (? & 'b) -> (('e & 'c) -> ('e | 'd) +//│ 'a :> forall 'b 'c 'd 'e. (#? & 'b) -> (('e & 'c) -> ('e | 'd) //│ where //│ 'a <: 'b -> 'c -> 'd) //│ ╙── @@ -614,7 +614,7 @@ rec def to_ch_weird n = to_church = to_ch //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> forall 'b 'c 'd 'e. (? & 'b) -> (('e & 'c) -> ('e | 'd) +//│ 'a :> forall 'b 'c 'd 'e. (#? & 'b) -> (('e & 'c) -> ('e | 'd) //│ where //│ 'a <: 'b -> 'c -> 'd) //│ ╙── diff --git a/shared/src/test/diff/fcp/Vec.mls b/shared/src/test/diff/fcp/Vec.mls index 6a1673e602..7b5e89a7ec 100644 --- a/shared/src/test/diff/fcp/Vec.mls +++ b/shared/src/test/diff/fcp/Vec.mls @@ -46,7 +46,7 @@ def cons_ty : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] cons_ty = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ where -//│ 'n := S['n] +//│ 'n := S[in 'p | 'n out 'n & 'p] //│ <: cons_ty: //│ 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ ╔══[ERROR] Type mismatch in def definition: @@ -65,7 +65,7 @@ cons_ty = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] cons_ty2 = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ cons_ty2: 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ where -//│ 'n := S['n] +//│ 'n := S[in 'p | 'n out 'n & 'p] type Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ Defined type alias Cons_ty @@ -108,26 +108,19 @@ cons_ty = cons : Cons_ty //│ ╔══[ERROR] Type mismatch in type ascription: //│ ║ l.104: cons_ty = cons : Cons_ty //│ ║ ^^^^ -//│ ╟── expression of type `S[in 'n & 'p out 'n | 'p]` does not match type `'n` +//│ ╟── expression of type `S[in 'n | 'p out 'n & 'p]` does not match type `'n` //│ ╟── Note: constraint arises from type variable: //│ ║ l.70: type Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ ║ ^^ //│ ╟── Note: class type parameter N is defined at: //│ ║ l.18: class Cons[A, N]: { size: S[N]; head: A; tail: Vec[A, N] } //│ ╙── ^ -//│ ╔══[ERROR] Type mismatch in def definition: -//│ ║ l.104: cons_ty = cons : Cons_ty -//│ ║ ^^^^^^^^^^^^^^ -//│ ╟── expression of type `'n` does not match type `'p` -//│ ╟── Note: constraint arises from quantified type variable: -//│ ║ l.20: type Vec[A, N] = forall 'r. (forall 'p. (Nil & { size: N } | Cons[A, S['p]] & Cons[A, N]) -> 'r) -> 'r -//│ ╙── ^^ cons_ty3 = cons : Cons_ty //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.126: cons_ty3 = cons : Cons_ty +//│ ║ l.119: cons_ty3 = cons : Cons_ty //│ ║ ^^^^ -//│ ╟── expression of type `S[in 'n & 'p out 'n | 'p]` does not match type `'n` +//│ ╟── expression of type `S[in 'n | 'p out 'n & 'p]` does not match type `'n` //│ ╟── Note: constraint arises from type variable: //│ ║ l.70: type Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ ║ ^^ @@ -141,14 +134,14 @@ def cons h (t: Vec['a, 'n]) k = k (Cons h t) cons : Cons_ty //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.142: cons : Cons_ty +//│ ║ l.135: cons : Cons_ty //│ ║ ^^^^ -//│ ╟── expression of type `S[in 'n & 'p out 'n | 'p]` does not match type `'n` +//│ ╟── expression of type `S[in 'n | 'p out 'n & 'p]` does not match type `'n` //│ ╟── Note: constraint arises from type variable: //│ ║ l.70: type Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ ║ ^^ //│ ╟── from type variable: -//│ ║ l.139: def cons h (t: Vec['a, 'n]) k = k (Cons h t) +//│ ║ l.132: def cons h (t: Vec['a, 'n]) k = k (Cons h t) //│ ║ ^^ //│ ╟── Note: class type parameter N is defined at: //│ ║ l.18: class Cons[A, N]: { size: S[N]; head: A; tail: Vec[A, N] } @@ -160,14 +153,14 @@ def cons h (t: Vec['a, 'n]) k = k (Cons h t) cons : Cons_ty //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.161: cons : Cons_ty +//│ ║ l.154: cons : Cons_ty //│ ║ ^^^^ -//│ ╟── expression of type `S[in 'n & 'p out 'n | 'p]` does not match type `'n` +//│ ╟── expression of type `S[in 'n | 'p out 'n & 'p]` does not match type `'n` //│ ╟── Note: constraint arises from type variable: //│ ║ l.70: type Cons_ty = forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ ║ ^^ //│ ╟── from type variable: -//│ ║ l.158: def cons h (t: Vec['a, 'n]) k = k (Cons h t) +//│ ║ l.151: def cons h (t: Vec['a, 'n]) k = k (Cons h t) //│ ║ ^^ //│ ╟── Note: class type parameter N is defined at: //│ ║ l.18: class Cons[A, N]: { size: S[N]; head: A; tail: Vec[A, N] } @@ -194,13 +187,13 @@ v1_0 = cons 1 nil v1_0 : Vec[int, S[Z]] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.195: v1_0 : Vec[int, S[Z]] +//│ ║ l.188: v1_0 : Vec[int, S[Z]] //│ ║ ^^^^ //│ ╟── application of type `Z` is not an instance of type `S` //│ ║ l.28: def Nil = Nil { size = Z{} } //│ ║ ^^^ //│ ╟── Note: constraint arises from applied type reference: -//│ ║ l.195: v1_0 : Vec[int, S[Z]] +//│ ║ l.188: v1_0 : Vec[int, S[Z]] //│ ║ ^^^^ //│ ╟── Note: class Z is defined at: //│ ║ l.7: class Z @@ -215,13 +208,13 @@ v1_1 k = k v1_ // :e v1_1 : Vec[int, S[Z]] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.216: v1_1 : Vec[int, S[Z]] +//│ ║ l.209: v1_1 : Vec[int, S[Z]] //│ ║ ^^^^ //│ ╟── application of type `Z` is not an instance of type `S` //│ ║ l.28: def Nil = Nil { size = Z{} } //│ ║ ^^^ //│ ╟── Note: constraint arises from applied type reference: -//│ ║ l.216: v1_1 : Vec[int, S[Z]] +//│ ║ l.209: v1_1 : Vec[int, S[Z]] //│ ║ ^^^^ //│ ╟── Note: class Z is defined at: //│ ║ l.7: class Z @@ -234,7 +227,7 @@ v1_tty = cons_ty 1 nil_ty v1_tty = cons_ty2 1 nil_ty //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.235: v1_tty = cons_ty2 1 nil_ty +//│ ║ l.228: v1_tty = cons_ty2 1 nil_ty //│ ║ ^^^^^^^^^^^^^^^^^ //│ ╟── type `Z` is not an instance of type `S` //│ ║ l.39: nil_ty = nil : Vec[int, Z] @@ -245,10 +238,7 @@ v1_tty = cons_ty2 1 nil_ty //│ ╟── from type variable: //│ ║ l.65: cons_ty2 = cons : forall 'a. 'a -> Vec['a, 'n] -> Vec['a, S['n]] //│ ╙── ^^ -//│ v1_tty: error | Vec[int, S['n]] -//│ where -//│ 'n :> S['n] | Z -//│ <: nothing +//│ v1_tty: error v1_tty = cons_ty3 1 nil_ty //│ v1_tty: Vec[int, S[Z]] @@ -261,7 +251,7 @@ v1 = cons 1 nil v2 = cons 1 (cons 2 nil) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.262: v2 = cons 1 (cons 2 nil) +//│ ║ l.252: v2 = cons 1 (cons 2 nil) //│ ║ ^^^^^^^^^^^^^^^^^^^ //│ ╟── application of type `Z` is not an instance of type `S` //│ ║ l.28: def Nil = Nil { size = Z{} } @@ -272,7 +262,7 @@ v2 = cons 1 (cons 2 nil) //│ ╟── Note: class Z is defined at: //│ ║ l.7: class Z //│ ╙── ^ -//│ v2: error +//│ v2: error | ((Cons[1 | 2, in S['p] out S['p] | Z] with {head: 1, size: forall 'P. S['P], tail: Vec[2, in S['p] out S['p] | Z]}) -> 'a) -> 'a def impossible x = case x of {} @@ -300,21 +290,21 @@ def head2 (vec: Vec['a, S['p]]) = vec (fun v -> case v of { head1 v1 head1 v2 //│ res: 1 -//│ res: error +//│ res: 1 | error :e head1 nil //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.306: head1 nil +//│ ║ l.296: head1 nil //│ ║ ^^^^^^^^^ //│ ╟── application of type `Z` does not match type `nothing` //│ ║ l.28: def Nil = Nil { size = Z{} } //│ ║ ^^^ //│ ╟── Note: constraint arises from reference: -//│ ║ l.278: def impossible x = case x of {} +//│ ║ l.268: def impossible x = case x of {} //│ ║ ^ //│ ╟── from field selection: -//│ ║ l.282: | Nil -> impossible v.size +//│ ║ l.272: | Nil -> impossible v.size //│ ║ ^^^^^^ //│ ╟── Note: class Z is defined at: //│ ║ l.7: class Z @@ -342,7 +332,7 @@ sum_ty = sum //│ <: sum_ty: //│ Vec[int, 'n] -> int //│ ╔══[ERROR] Subtyping constraint of the form `forall ?sum. ?sum <: forall 'n. Vec[int, 'n] -> int` exceeded recursion depth limit (250) -//│ ║ l.338: sum_ty = sum +//│ ║ l.328: sum_ty = sum //│ ║ ^^^^^^^^^^^^ //│ ╙── Note: use flag `:ex` to see internal error info. @@ -353,13 +343,17 @@ sum nil // * Note: also worked woth top/bot extrusion sum v1_0 //│ ╔══[ERROR] Subtyping constraint of the form `forall ?sum. ?sum <: (forall ?a. ?a) -> ?b` exceeded recursion depth limit (250) -//│ ║ l.354: sum v1_0 +//│ ║ l.344: sum v1_0 //│ ║ ^^^^^^^^ //│ ╙── Note: use flag `:ex` to see internal error info. //│ res: error // * Note: also worked woth top/bot extrusion sum v2 +//│ ╔══[ERROR] Subtyping constraint of the form `forall ?sum. ?sum <: (forall ?a. ?a) -> ?b` exceeded recursion depth limit (250) +//│ ║ l.352: sum v2 +//│ ║ ^^^^^^ +//│ ╙── Note: use flag `:ex` to see internal error info. //│ res: error @@ -388,7 +382,7 @@ def head1_ty v = case v of { //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ║ l.+4: } //│ ║ ^^^ -//│ ╟── type `(forall 'p. (Cons['a, in S[in 'p0 & 'p out 'p0 | 'p] out S[in 'p0 | 'p out 'p0 & 'p]] | (Nil with {size: S['p0]})) -> 'r) -> 'r` does not match type `Cons[?, ?] & ?a | Nil & ?b` +//│ ╟── type `(forall 'p. (Cons['a, S[in 'p0 | 'p out 'p0 & 'p]] | (Nil with {size: S['p0]})) -> 'r) -> 'r` does not match type `Cons[?, ?] & ?a | Nil & ?b` //│ ║ l.20: type Vec[A, N] = forall 'r. (forall 'p. (Nil & { size: N } | Cons[A, S['p]] & Cons[A, N]) -> 'r) -> 'r //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from reference: @@ -401,22 +395,22 @@ sum v1_ty //│ ║ l.+1: sum v1_ty //│ ║ ^^^^^^^^^ //│ ╟── type `Cons[int, Z]` is not a function -//│ ║ l.187: v1_ty = v1_ : Cons[int, Z] +//│ ║ l.180: v1_ty = v1_ : Cons[int, Z] //│ ║ ^^^^^^^^^^^^ //│ ╟── but it flows into reference with expected type `(forall ?a ?b. ?a -> ?b) -> ?c` //│ ║ l.+1: sum v1_ty //│ ║ ^^^^^ //│ ╟── Note: constraint arises from application: -//│ ║ l.325: rec def sum vec = vec (fun v -> case v of { +//│ ║ l.315: rec def sum vec = vec (fun v -> case v of { //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.326: | Nil -> 0 +//│ ║ l.316: | Nil -> 0 //│ ║ ^^^^^^^^^^^^ -//│ ║ l.327: | Cons -> v.head + sum v.tail +//│ ║ l.317: | Cons -> v.head + sum v.tail //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.328: }) +//│ ║ l.318: }) //│ ║ ^^^^ //│ ╟── from reference: -//│ ║ l.325: rec def sum vec = vec (fun v -> case v of { +//│ ║ l.315: rec def sum vec = vec (fun v -> case v of { //│ ╙── ^^^ //│ res: error diff --git a/shared/src/test/diff/gadt/AliasGADT.mls b/shared/src/test/diff/gadt/AliasGADT.mls new file mode 100644 index 0000000000..94ba235aa9 --- /dev/null +++ b/shared/src/test/diff/gadt/AliasGADT.mls @@ -0,0 +1,58 @@ +:NewDefs + + +type Test[T] = LitInt | LitStr +class LitInt(n: Int) { type T = Int } +class LitStr(s: Str) { type T = Str } +//│ type Test[T] = LitInt | LitStr +//│ class LitInt(n: Int) +//│ class LitStr(s: Str) + +fun foo[T](x: Test[T]): x.T = if x is + LitInt(n) then n + LitStr(s) then s +//│ fun foo: forall 'T. (x: Test['T]) -> (Int | Str) + +// FIXME +fun foo[T](x: Test[T]): T = if x is + LitInt(n) then n : x.T + LitStr(s) then s : x.T +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.18: LitInt(n) then n : x.T +//│ ║ ^ +//│ ╟── type `Int` does not match type `T` +//│ ║ l.5: class LitInt(n: Int) { type T = Int } +//│ ║ ^^^ +//│ ╟── Note: constraint arises from method type parameter: +//│ ║ l.17: fun foo[T](x: Test[T]): T = if x is +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.19: LitStr(s) then s : x.T +//│ ║ ^ +//│ ╟── type `Str` does not match type `T` +//│ ║ l.6: class LitStr(s: Str) { type T = Str } +//│ ║ ^^^ +//│ ╟── Note: constraint arises from method type parameter: +//│ ║ l.17: fun foo[T](x: Test[T]): T = if x is +//│ ╙── ^ +//│ fun foo: forall 'T. (x: Test['T]) -> 'T + +// * somehow we need to find a way to associate T in Foo and T in MkF +type Foo[T] = MkF +class MkF(n: Int) { type T = Int } +//│ type Foo[T] = MkF +//│ class MkF(n: Int) + +// FIXME +fun foo[T](x: Foo[T]): T = if x is + MkF(n) then n : x.T +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.48: MkF(n) then n : x.T +//│ ║ ^ +//│ ╟── type `Int` does not match type `T` +//│ ║ l.42: class MkF(n: Int) { type T = Int } +//│ ║ ^^^ +//│ ╟── Note: constraint arises from method type parameter: +//│ ║ l.47: fun foo[T](x: Foo[T]): T = if x is +//│ ╙── ^ +//│ fun foo: forall 'T. (x: Foo['T]) -> 'T diff --git a/shared/src/test/diff/gadt/AscPushHygiene.mls b/shared/src/test/diff/gadt/AscPushHygiene.mls new file mode 100644 index 0000000000..802f86fd02 --- /dev/null +++ b/shared/src/test/diff/gadt/AscPushHygiene.mls @@ -0,0 +1,17 @@ +:NewDefs + + +// * Example lack of hygiene from pushing ascriptions in + +class Foo[type A](a: A, n: Int) +//│ class Foo[A](a: A, n: Int) + +:e // FIXME +fun test(x: Foo[Int]): x.A = if x is + Foo(a, x) then a +//│ ╔══[ERROR] Type `Int` does not contain member `A` +//│ ║ l.10: fun test(x: Foo[Int]): x.A = if x is +//│ ╙── ^^ +//│ fun test: (x: Foo[Int]) -> error + + diff --git a/shared/src/test/diff/gadt/BadTypeProjection.mls b/shared/src/test/diff/gadt/BadTypeProjection.mls new file mode 100644 index 0000000000..88a93af39b --- /dev/null +++ b/shared/src/test/diff/gadt/BadTypeProjection.mls @@ -0,0 +1,21 @@ +:NewDefs + + +class Wrap[type A] +class Test[type B] +//│ class Wrap[A] { +//│ constructor() +//│ } +//│ class Test[B] { +//│ constructor() +//│ } + +fun oops(w: Wrap[Test[Int] & Test[Str]]) = 1 : w.A.B +//│ fun oops: (w: Wrap[in Test[out Int | Str] out Test[in Int | Str out nothing]]) -> nothing + +oops(new Wrap) +//│ nothing +//│ res +//│ = 1 + + diff --git a/shared/src/test/diff/gadt/Exp1.mls b/shared/src/test/diff/gadt/Exp1.mls index 489ddea752..0c5d196a3d 100644 --- a/shared/src/test/diff/gadt/Exp1.mls +++ b/shared/src/test/diff/gadt/Exp1.mls @@ -15,17 +15,17 @@ fun f(p: Pair['a, 'b]) = p.lhs fun f(e) = if e is Pair(l, r) then [l, r] -//│ fun f: forall 'a 'b. Pair['a, 'b] -> ['a, 'b] +//│ fun f: forall 'L 'R. Pair['L, 'R] -> [??L & 'L, ??R & 'R] // f: (Exp['a] & Pair) -> 0 fun f(e) = if e is Pair(l, r) then [l, r] Lit(n) then n -//│ fun f: forall 'a 'b. (Lit | Pair['a, 'b]) -> (Int | ['a, 'b]) +//│ fun f: forall 'L 'R. (Lit | Pair['L, 'R]) -> (Int | [??L & 'L, ??R & 'R]) (e: Exp['X]) => f(e) -//│ forall 'X. (e: Exp['X]) -> (Int | [??L, ??R]) +//│ forall 'X. (e: Exp['X]) -> (Int | [??L & ??L0, ??R & ??R0]) //│ res //│ = [Function: res] @@ -46,13 +46,10 @@ fun f(e) = if e is Pair(l: a, r) then let f(x: a) = x f(l) -//│ ╔══[ERROR] type identifier not found: a -//│ ║ l.47: let f(x: a) = x -//│ ╙── ^ //│ ╔══[ERROR] identifier not found: l //│ ║ l.48: f(l) //│ ╙── ^ -//│ fun f: Pair[anything, anything] -> error +//│ fun f: forall 'L. Pair['L, anything] -> (error | ??L & 'L) //│ Code generation encountered an error: //│ unresolved symbol l // fun f: forall 'lhs 'rhs. Pair['lhs, 'rhs] -> ('lhs, 'rhs,) diff --git a/shared/src/test/diff/gadt/Exp2.mls b/shared/src/test/diff/gadt/Exp2.mls index 45449541c3..e240035a25 100644 --- a/shared/src/test/diff/gadt/Exp2.mls +++ b/shared/src/test/diff/gadt/Exp2.mls @@ -17,16 +17,16 @@ fun f(p: Pair['a, 'b]) = p.lhs fun f(e) = if e is Pair(l, r) then [l, r] -//│ fun f: forall 'L 'R. Pair['L, 'R] -> [Exp['L], Exp['R]] +//│ fun f: forall 'L 'R. Pair['L, 'R] -> [Exp[??L & 'L], Exp[??R & 'R]] // f: (Exp['a] & Pair) -> 0 fun f(e) = if e is Pair(l, r) then [l, r] Lit(n) then n -//│ fun f: forall 'L 'R. (Lit | Pair['L, 'R]) -> (Int | [Exp['L], Exp['R]]) +//│ fun f: forall 'L 'R. (Lit | Pair['L, 'R]) -> (Int | [Exp[??L & 'L], Exp[??R & 'R]]) (e: Exp['X]) => f(e) -//│ (e: Exp[anything]) -> (Int | [Exp[??L], Exp[??R]]) +//│ (e: Exp[anything]) -> (Int | [Exp[??L & ??L0], Exp[??R & ??R0]]) //│ res //│ = [Function: res] @@ -38,7 +38,7 @@ fun f(e) = if e is // * Invariant: -abstract class Exp[A]: Pair | Lit +abstract class Exp[A]: Pair[?, ?] | Lit class Lit(val n: Int) extends Exp[Int] class Pair[L, R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]] //│ abstract class Exp[A]: Lit | Pair[?, ?] @@ -51,60 +51,26 @@ fun f(p: Pair['a, 'b]) = p.lhs fun f(e) = if e is Pair(l, r) then [l, r] -//│ fun f: forall 'L 'R. Pair['L, 'R] -> [Exp['L], Exp['R]] +//│ fun f: forall 'L 'L0 'R 'R0. Pair[in 'L out 'L0, in 'R out 'R0] -> [Exp[in 'L & 'L0 out ??L & 'L0], Exp[in 'R & 'R0 out ??R & 'R0]] // f: (Exp['a] & Pair) -> 0 fun f(e) = if e is Pair(l, r) then [l, r] Lit(n) then n -//│ fun f: forall 'L 'R. (Lit | Pair['L, 'R]) -> (Int | [Exp['L], Exp['R]]) +//│ fun f: forall 'L 'L0 'R 'R0. (Lit | Pair[in 'L out 'L0, in 'R out 'R0]) -> (Int | [Exp[in 'L & 'L0 out ??L & 'L0], Exp[in 'R & 'R0 out ??R & 'R0]]) -:e +// :e (e: Exp['X]) => f(e) -//│ ╔══[ERROR] Type error in application -//│ ║ l.63: (e: Exp['X]) => f(e) -//│ ║ ^^^^ -//│ ╟── type variable `L` leaks out of its scope -//│ ║ l.43: class Pair[L, R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]] -//│ ╙── ^ -//│ forall 'X 'L 'R. (e: Exp['X]) -> (Int | error | [Exp['L], Exp['R]]) -//│ where -//│ 'R :> ??R -//│ <: ??R0 -//│ 'L :> ??L -//│ <: ??L0 +//│ forall 'X. (e: Exp['X]) -> (Int | [Exp[out ??L], Exp[out ??R]]) //│ res //│ = [Function: res] -:e fun f(e) = if e is Pair(l, r) then f(l) + f(r) Lit(n) then n -//│ ╔══[ERROR] Type error in definition -//│ ║ l.80: fun f(e) = if e is -//│ ║ ^^^^^^^^^^^^^^ -//│ ║ l.81: Pair(l, r) then f(l) + f(r) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.82: Lit(n) then n -//│ ║ ^^^^^^^^^^^^^^^ -//│ ╟── type variable `L` leaks out of its scope -//│ ║ l.43: class Pair[L, R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]] -//│ ╙── ^ -//│ ╔══[ERROR] Type error in definition -//│ ║ l.80: fun f(e) = if e is -//│ ║ ^^^^^^^^^^^^^^ -//│ ║ l.81: Pair(l, r) then f(l) + f(r) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.82: Lit(n) then n -//│ ║ ^^^^^^^^^^^^^^^ -//│ ╟── type variable `R` leaks out of its scope -//│ ║ l.43: class Pair[L, R](val lhs: Exp[L], val rhs: Exp[R]) extends Exp[[L, R]] -//│ ╙── ^ -//│ fun f: forall 'L 'R. (Lit | Pair['L, 'R]) -> Int -//│ where -//│ 'R :> ??R -//│ <: ??R0 -//│ 'L :> ??L -//│ <: ??L0 - +//│ fun f: (Lit | Pair[?, ?]) -> Int +f(Pair(Pair(Lit(1), Lit(2)), Lit(3))) +//│ Int +//│ res +//│ = 6 diff --git a/shared/src/test/diff/gadt/ExtIntro.mls b/shared/src/test/diff/gadt/ExtIntro.mls new file mode 100644 index 0000000000..55b8da0ec0 --- /dev/null +++ b/shared/src/test/diff/gadt/ExtIntro.mls @@ -0,0 +1,434 @@ +:NewDefs +:DontDistributeForalls + +class Z +class S[type P] +//│ class Z { +//│ constructor() +//│ } +//│ class S[P] { +//│ constructor() +//│ } + +abstract class K[type T]: KS[?] +class KS[A](ev: K[A]) extends K[S[A]] +//│ abstract class K[T]: KS[?] +//│ class KS[A](ev: K[A]) extends K + +// TODO +fun fr: (K['L], K['L]) -> Int +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then fr(e1, e2) else 0 +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.21: if l is KS(e1) and r is KS(e2) then fr(e1, e2) else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `??A & ~??A0` does not match type `~??A1` +//│ ║ l.19: fun fr: (K['L], K['L]) -> Int +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.21: if l is KS(e1) and r is KS(e2) then fr(e1, e2) else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `~??A` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.19: fun fr: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.19: fun fr: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.14: class KS[A](ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> Int +//│ fun fr: forall 'L0. (K['L0], K['L0]) -> Int + +:e +fun fr: (K['L], K['L]) -> Int +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then fr(l, e2) else 0 +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.47: if l is KS(e1) and r is KS(e2) then fr(l, e2) else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `S[in A & ?A out A | ?A0] | L | ~??A` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.45: fun fr: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.45: fun fr: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.14: class KS[A](ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> Int +//│ fun fr: forall 'L0. (K['L0], K['L0]) -> Int + +// FIXedME +:e +fun fr: (K['L], K['L]) -> Int +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then fr(l, e1) else 0 +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.68: if l is KS(e1) and r is KS(e2) then fr(l, e1) else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `S[in ??A & ?A out ?A0] | L | ~??A` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.66: fun fr: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.66: fun fr: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.14: class KS[A](ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> Int +//│ fun fr: forall 'L0. (K['L0], K['L0]) -> Int + +:e +fun fr: (K['L], K['L]) -> Int +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then fr(l, e1) else 0 +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.88: if l is KS(e1) and r is KS(e2) then fr(l, e1) else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `S[in ??A & ?A out ?A0] | L | ~??A` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.86: fun fr: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.86: fun fr: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.14: class KS[A](ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> Int +//│ fun fr: forall 'L0. (K['L0], K['L0]) -> Int + +fun fr: (K['L], K['L]) -> Int +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then fr(l, r) else 0 +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> Int +//│ fun fr: forall 'L0. (K['L0], K['L0]) -> Int + +fun fk: (K['L], K['L]) -> Int +fun fk[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then fk((e1 : K[e1.T]), (e2 : K[e2.T])) else 0 +//│ fun fk: forall 'L. (l: K['L], r: K['L]) -> Int +//│ fun fk: forall 'L0. (K['L0], K['L0]) -> Int + +fun fz[L](l: K[L], r: K[L]) = + if l is KS(ea) and r is KS(eb) then + let xw: K[eb.T] = ea : K[ea.T]; 0 + else 0 +//│ fun fz: forall 'L. (l: K['L], r: K['L]) -> 0 + +:re +fk((error : K[S[S[nothing]]]), (error : K[S[S[nothing]]])) +//│ Int +//│ res +//│ Runtime error: +//│ Error: an error was thrown + +:e +fk((error : K[S[S[nothing]]]), (error : K[S[nothing]])) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.131: fk((error : K[S[S[nothing]]]), (error : K[S[nothing]])) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `S[nothing]` does not match type `nothing` +//│ ║ l.131: fk((error : K[S[S[nothing]]]), (error : K[S[nothing]])) +//│ ║ ^^^^^^^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.131: fk((error : K[S[S[nothing]]]), (error : K[S[nothing]])) +//│ ╙── ^^^^^^^ +//│ Int | error +//│ res +//│ Runtime error: +//│ Error: an error was thrown + +// * with alt + +abstract class K[type T]: KZ | KS[?] +class KZ() extends K[Z] +class KS[type A](ev: K[A]) extends K[S[A]] +//│ abstract class K[T]: KS[?] | KZ +//│ class KZ() extends K +//│ class KS[A](ev: K[A]) extends K + +fun get[A](x: K[S[A]]): K[A] = if x is KS(m) then m : K[x.T.P] else error +//│ fun get: forall 'A. (x: K[S['A]]) -> K['A] + +// TODO +fun fk: (K['L], K['L]) -> Int +fun fk[L](l: K[L], r: K[L]): Int = + if l is KS(ep) and r is KS(eq) then 1 + fk(ep, eq) else 0 +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.161: if l is KS(ep) and r is KS(eq) then 1 + fk(ep, eq) else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `??A & ~??A0` does not match type `~??A1` +//│ ║ l.159: fun fk: (K['L], K['L]) -> Int +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.161: if l is KS(ep) and r is KS(eq) then 1 + fk(ep, eq) else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `~??A` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.159: fun fk: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.159: fun fk: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.150: class KS[type A](ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ fun fk: forall 'L. (l: K['L], r: K['L]) -> Int +//│ fun fk: forall 'L0. (K['L0], K['L0]) -> Int + +fk(KS(KS(KZ())), KS(KS(KZ()))) +//│ Int +//│ res +//│ = 2 + +:e +fk(KS(KS(KZ())), KS(KZ())) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.190: fk(KS(KS(KZ())), KS(KZ())) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S[?A]` +//│ ║ l.149: class KZ() extends K[Z] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.150: class KS[type A](ev: K[A]) extends K[S[A]] +//│ ║ ^^^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.150: class KS[type A](ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ Int | error +//│ res +//│ = 1 + +fun fi[L](x: K[L]): K[L] = if x is + KZ() then KZ() : K[x.T] + KS(ea) then KS(ea) : K[x.T] +//│ fun fi: forall 'L. (x: K['L]) -> K['L] + +fun fz[L](l: K[L], r: K[L]) = + if l is KS(ea) and r is KS(eb) then + let zt: K[ea.T] = ea ; 0 + else 0 +//│ fun fz: forall 'L. (l: K['L], r: K['L]) -> 0 + +fun fz[L](l: KS[L], r: KS[L]) = + if l is KS(ea) and r is KS(eb) then + let zt: K[eb.T] = ea : K[ea.T] ; 0 + else 0 +//│ fun fz: forall 'L. (l: KS['L], r: KS['L]) -> 0 + +// TODO +fun fz[L](l: K[L], r: K[L]) = + if l is KS(ea) and r is KS(eb) then + let zt = ea : K[eb.T] ; 0 + else error +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.226: if l is KS(ea) and r is KS(eb) then +//│ ║ ^^^^^^^^^^^^^^^^ +//│ ║ l.227: let zt = ea : K[eb.T] ; 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.228: else error +//│ ║ ^^^^^^^^^^^^ +//│ ╟── type `S[?] & ??A & ~??A0` does not match type `Z | ~??A1` +//│ ║ l.227: let zt = ea : K[eb.T] ; 0 +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.226: if l is KS(ea) and r is KS(eb) then +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.227: let zt = ea : K[eb.T] ; 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.228: else error +//│ ║ ^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `S[?] | ~??A` +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.227: let zt = ea : K[eb.T] ; 0 +//│ ║ ^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.150: class KS[type A](ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ fun fz: forall 'L. (l: K['L], r: K['L]) -> (0 | error) + +fun fz[L](l: K[L], r: K[L]): K[L] = + if l is KS(ea) and r is KS(eb) + then (KS(eb) : K[r.T]) : K[l.T] + else error +//│ fun fz: forall 'L. (l: K['L], r: K['L]) -> K['L] + +abstract class Eq[type A, type B]: Refl[A] +class Refl[A]() extends Eq[A, A] +//│ abstract class Eq[A, B]: Refl[A] +//│ class Refl[A]() extends Eq + +fun conv[L, A](x: K[L], ev: Eq[L, S[A]]): K[S[A]] = + if ev is Refl() then (x as K[ev.A]) as K[ev.B] +//│ fun conv: forall 'L 'A. (x: K['L], ev: Eq['L, S['A]]) -> K[S['A]] + +conv(KS(KZ()), Refl()) +//│ K[S[Z]] +//│ res +//│ = KS {} + +:e +conv(KZ(), Refl()) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.276: conv(KZ(), Refl()) +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S[?A]` +//│ ║ l.149: class KZ() extends K[Z] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.266: fun conv[L, A](x: K[L], ev: Eq[L, S[A]]): K[S[A]] = +//│ ╙── ^^^^ +//│ K[S['A]] | error +//│ res +//│ = KZ {} + +fun extr[L, H](x: K[L], ev: Eq[L, S[H]]): K[H] = + let y: K[S[ev.B.P]] = x : K[ev.B] + if y is KS(m) then m : K[y.T.P] else error +//│ fun extr: forall 'L 'H. (x: K['L], ev: Eq['L, S['H]]) -> K['H] + +fun extr[L, H](x: K[L], ev: Eq[L, S[H]]): K[H] = get(x : K[ev.B]) +//│ fun extr: forall 'L 'H. (x: K['L], ev: Eq['L, S['H]]) -> K['H] + +extr(KS(KZ()), Refl()) +//│ K[Z] +//│ res +//│ = KZ {} + +:e +extr(KZ(), Refl()) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.304: extr(KZ(), Refl()) +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S[?H]` +//│ ║ l.149: class KZ() extends K[Z] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.295: fun extr[L, H](x: K[L], ev: Eq[L, S[H]]): K[H] = get(x : K[ev.B]) +//│ ╙── ^^^^ +//│ K['H] | error +//│ res +//│ Runtime error: +//│ Error: an error was thrown + +abstract class K[type T]: (KZ | KS[?]) { + fun m: Eq[T, S['A]] -> Int + fun m(ev) = if ev is Refl() then 0 + fun n: T -> T + fun n(x) = x +} +class KZ() extends K[Z] +class KS[type A](ev: K[A]) extends K[S[A]] +//│ abstract class K[T]: KS[?] | KZ { +//│ fun m: forall 'A. Eq[T, S['A]] -> Int +//│ fun n: T -> T +//│ } +//│ class KZ() extends K { +//│ fun m: forall 'A0. Eq['T, S['A0]] -> Int +//│ fun n: 'T -> 'T +//│ } +//│ class KS[A](ev: K[A]) extends K { +//│ fun m: forall 'A1. Eq['T0, S['A1]] -> Int +//│ fun n: 'T0 -> 'T0 +//│ } +//│ where +//│ 'T0 := S[A] +//│ 'T := Z + +KS(KZ()).n(new S : S[Z]) +KZ().n(new Z) +//│ Z +//│ res +//│ = S {} +//│ res +//│ = Z {} + +:e +KS(KZ()).n(new Z) +KZ().n(new S : S[Z]) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.352: KS(KZ()).n(new Z) +//│ ║ ^^^^^^^^^^^^^^^^^ +//│ ╟── application of type `Z` is not an instance of `S[?A]` +//│ ║ l.352: KS(KZ()).n(new Z) +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.326: class KS[type A](ev: K[A]) extends K[S[A]] +//│ ║ ^^^^ +//│ ╟── Note: type parameter T is defined at: +//│ ║ l.319: abstract class K[type T]: (KZ | KS[?]) { +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.353: KZ().n(new S : S[Z]) +//│ ║ ^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `S[Z]` is not an instance of `Z` +//│ ║ l.353: KZ().n(new S : S[Z]) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.325: class KZ() extends K[Z] +//│ ║ ^ +//│ ╟── Note: type parameter T is defined at: +//│ ║ l.319: abstract class K[type T]: (KZ | KS[?]) { +//│ ╙── ^ +//│ Z | error +//│ res +//│ = Z {} +//│ res +//│ = S {} + +KS(KZ()).m(Refl()) +//│ Int +//│ res +//│ = 0 + +:e +KZ().m(Refl()) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.390: KZ().m(Refl()) +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S['A]` +//│ ║ l.325: class KZ() extends K[Z] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.320: fun m: Eq[T, S['A]] -> Int +//│ ╙── ^^^^^ +//│ Int | error +//│ res +//│ = 0 + +class C[type A]() +//│ class C[A]() + +fun test(k) = + let f(x) = let c = C() in [k(c), c] + f +//│ fun test: forall 'A 'A0 'a. (C[in 'A out 'A | 'A0] -> 'a) -> (forall 'A1. anything -> ['a, C['A1]]) +//│ where +//│ 'A1 :> 'A +//│ <: 'A0 + +class C[A, in B, out C]() { fun f: [A, B] -> [A, C] = f } +//│ class C[A, B, C]() { +//│ fun f: (A, B) -> [A, C] +//│ } + +fun test(k) = + let f(x) = let c = C() in [k(c), c] + f +//│ fun test: forall 'A 'A0 'a. (C[in 'A out 'A | 'A0, anything, nothing] -> 'a) -> (forall 'A1. anything -> ['a, C['A1, anything, nothing]]) +//│ where +//│ 'A1 :> 'A +//│ <: 'A0 + + + + + + + + diff --git a/shared/src/test/diff/gadt/ExtIntro_repro.mls b/shared/src/test/diff/gadt/ExtIntro_repro.mls new file mode 100644 index 0000000000..c986a5825d --- /dev/null +++ b/shared/src/test/diff/gadt/ExtIntro_repro.mls @@ -0,0 +1,869 @@ +:NewDefs +:DontDistributeForalls + +:NoJS + + + +class Z +class S[type P] +//│ class Z { +//│ constructor() +//│ } +//│ class S[P] { +//│ constructor() +//│ } + + + +(x: S) => x as S[?] +//│ (x: S[?]) -> S[?] + + +class Foo[type A](val foo: Foo[A]) +//│ class Foo[A](foo: Foo[A]) + + +(x: Foo[?]) => x as Foo[?] +//│ (x: Foo[?]) -> Foo[?] + +(x: Foo) => x as Foo[?] +//│ (x: Foo[?]) -> Foo[?] + +(x: Foo[?]) => x as Foo +//│ (x: Foo[?]) -> Foo[?] + +(x: Foo[?]) => x.foo as Foo[?] +//│ (x: Foo[?]) -> Foo[?] + +(x: Foo) => x.foo as Foo[?] +//│ (x: Foo[?]) -> Foo[?] + +:e +(x: Foo) => x.foo as x.A +//│ ╔══[ERROR] Type error in type ascription +//│ ║ l.43: (x: Foo) => x.foo as x.A +//│ ║ ^^^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.23: class Foo[type A](val foo: Foo[A]) +//│ ╙── ^^^^^^ +//│ (x: Foo[?]) -> ??A + +:e +(x: Foo[?]) => x.foo as x.A +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.53: (x: Foo[?]) => x.foo as x.A +//│ ║ ^^^^^ +//│ ╟── type `Foo[?]` does not match type `nothing` +//│ ║ l.23: class Foo[type A](val foo: Foo[A]) +//│ ║ ^^^^^^ +//│ ╟── but it flows into field selection with expected type `nothing` +//│ ║ l.53: (x: Foo[?]) => x.foo as x.A +//│ ║ ^^^^^ +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.53: (x: Foo[?]) => x.foo as x.A +//│ ╙── ^^ +//│ (x: Foo[?]) -> anything + +:e +(x: Foo) => if x is + Foo then + x.foo as x.A +//│ ╔══[ERROR] Type error in `case` expression +//│ ║ l.69: (x: Foo) => if x is +//│ ║ ^^^^ +//│ ║ l.70: Foo then +//│ ║ ^^^^^^^^^^ +//│ ║ l.71: x.foo as x.A +//│ ║ ^^^^^^^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.23: class Foo[type A](val foo: Foo[A]) +//│ ╙── ^ +//│ (x: Foo[?]) -> anything + +:e +(x: Foo[?]) => if x is + Foo then + x.foo as x.A +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.85: (x: Foo[?]) => if x is +//│ ║ ^^^^ +//│ ║ l.86: Foo then +//│ ║ ^^^^^^^^^^ +//│ ║ l.87: x.foo as x.A +//│ ║ ^^^^^^^^^ +//│ ╙── expression of type `Foo[in ?A out ??A & ?A0] & ~??A0` does not match type `nothing` +//│ (x: Foo[?]) -> anything + + + +fun fz(l) = + if l is Foo(ea) and 0 is 0 then + ea : Foo[ea.A] +//│ fun fz: forall 'A 'A0. Foo[in 'A out 'A0] -> Foo[in 'A & 'A0 out ??A & 'A0] + + + + + + + + + + + +// abstract class K[type T]: KZ | KS[?] +abstract class K[type T]: KS[?] +// class KZ() extends K[Z] +class KS[type A](ev: K[A]) extends K[S[A]] +//│ abstract class K[T]: KS[?] +//│ class KS[A](ev: K[A]) extends K + +:d + +fun fz(l) = + if l is KS(ea) then + ea : K[ea.T] +//│ fun fz: forall 'A 'A0. KS[in 'A out 'A0] -> K[in S[?] | 'A & 'A0 out ??A & 'A0 & S[?]] + + +// :d +fun fz(l) = + if l is KS(ea) then + () => ea : K[ea.T] +//│ fun fz: forall 'A 'A0. KS[in 'A out 'A0] -> () -> K[in S[in anything out nothing] | 'A & 'A0 out S[?] & ??A & 'A0] + +// :d +fun fz(l) = + if l is KS(ea) and 0 is 0 then + ea : K[ea.T] +//│ fun fz: forall 'A 'A0. KS[in 'A out 'A0] -> K[in S[in anything out nothing] | 'A & 'A0 out S[?] & ??A & 'A0] + + + +fun fz[L](l: K[L], r: K[L]) = + if l is KS(ea) and r is KS(eb) then + let zt: K[ea.T] = ea ; 0 + else 0 +//│ fun fz: forall 'L. (l: K['L], r: K['L]) -> 0 + + +// fun fr: (K['L], K['L]) -> Int + +:e +fun fr[L](l: K[L]) = if l is KS(e1) then e1 as K[L] +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.154: fun fr[L](l: K[L]) = if l is KS(e1) then e1 as K[L] +//│ ║ ^^^^^^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `L | ~??A` +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.118: class KS[type A](ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ fun fr: forall 'L. (l: K['L]) -> (K['L] | error) + +:e +fun fr[L](l: K[L]) = if l is KS(e1) then e1 as K[S['X]] +//│ ╔══[ERROR] Type `??A` does not contain member `P` +//│ ║ l.9: class S[type P] +//│ ╙── ^ +//│ fun fr: forall 'L. (l: K['L]) -> (K[S[error]] | error) + +// :d +fun fr[L](l: K[L]) = if l is KS(e1) then e1 as K['X] +//│ fun fr: forall 'L. (l: K['L]) -> K[?] + + + + +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then [(e1 as K['X]), e2 as K['X]] else 0 +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> (0 | [K[?], K[out ??A]]) + + + +// MIN + +fun sig: (K['L], K['L]) -> Int +//│ fun sig: forall 'L. (K['L], K['L]) -> Int + +// FIXME +:d +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then sig(e1, e2) +//│ 0. Typing TypingUnit(List(NuFunDef(None,Var(fr),None,List(TypeName(L)),Left(Lam(Tup(List((Some(Var(l)),Fld(_,TyApp(Var(K),List(TypeName(L))))), (Some(Var(r)),Fld(_,TyApp(Var(K),List(TypeName(L))))))),Blk(List(If(IfThen(App(Var(and),Tup(List((None,Fld(_,App(Var(is),Tup(List((None,Fld(_,Var(l))), (None,Fld(_,App(Var(KS),Tup(List((None,Fld(_,Var(e1))))))))))))), (None,Fld(_,App(Var(is),Tup(List((None,Fld(_,Var(r))), (None,Fld(_,App(Var(KS),Tup(List((None,Fld(_,Var(e2)))))))))))))))),App(Var(sig),Tup(List((None,Fld(_,Var(e1))), (None,Fld(_,Var(e2))))))),None)))))))) +//│ | 0. Created lazy type info for NuFunDef(None,Var(fr),None,List(TypeName(L)),Left(Lam(Tup(List((Some(Var(l)),Fld(_,TyApp(Var(K),List(TypeName(L))))), (Some(Var(r)),Fld(_,TyApp(Var(K),List(TypeName(L))))))),Blk(List(If(IfThen(App(Var(and),Tup(List((None,Fld(_,App(Var(is),Tup(List((None,Fld(_,Var(l))), (None,Fld(_,App(Var(KS),Tup(List((None,Fld(_,Var(e1))))))))))))), (None,Fld(_,App(Var(is),Tup(List((None,Fld(_,Var(r))), (None,Fld(_,App(Var(KS),Tup(List((None,Fld(_,Var(e2)))))))))))))))),App(Var(sig),Tup(List((None,Fld(_,Var(e1))), (None,Fld(_,Var(e2))))))),None)))))) +//│ | Completing fun fr = (l: K‹L›, r: K‹L›,) => {if (and(is(l, KS(e1,),), is(r, KS(e2,),),)) then sig(e1, e2,)} +//│ | | Type params (TypeName(L),L542',TypeParamInfo(None,false,None,None)) +//│ | | Params +//│ | | Type fr polymorphically? true && (0 === 0 || false || false +//│ | | 1. Typing term (l: K‹L›, r: K‹L›,) => {if (and(is(l, KS(e1,),), is(r, KS(e2,),),)) then sig(e1, e2,)} +//│ | | | 1. Typing pattern [l: K‹L›, r: K‹L›,] +//│ | | | | 1. Typing pattern l : K[L] +//│ | | | | | Typing type AppliedType(TypeName(K),List(TypeName(L))) +//│ | | | | | | vars=Map(L -> ‘L542') newDefsInfo=Map() +//│ | | | | | | 1. type AppliedType(TypeName(K),List(TypeName(L))) +//│ | | | | | | | 1. type TypeName(L) +//│ | | | | | | | => ‘L542' +//│ | | | | | | => K[‘L542'] +//│ | | | | | => K[‘L542'] ——— +//│ | | | | 1. : K[‘L542'] +//│ | | | | 1. Typing pattern r : K[L] +//│ | | | | | Typing type AppliedType(TypeName(K),List(TypeName(L))) +//│ | | | | | | vars=Map(L -> ‘L542') newDefsInfo=Map() +//│ | | | | | | 1. type AppliedType(TypeName(K),List(TypeName(L))) +//│ | | | | | | | 1. type TypeName(L) +//│ | | | | | | | => ‘L542' +//│ | | | | | | => K[‘L542'] +//│ | | | | | => K[‘L542'] ——— +//│ | | | | 1. : K[‘L542'] +//│ | | | 1. : (l: K[‘L542'], r: K[‘L542'],) +//│ | | | 1. Typing term {if (and(is(l, KS(e1,),), is(r, KS(e2,),),)) then sig(e1, e2,)} +//│ | | | | 1. Typing term if (and(is(l, KS(e1,),), is(r, KS(e2,),),)) then sig(e1, e2,) +//│ | | | | | [Desugarer.destructPattern] scrutinee = Var(l); pattern = App(Var(KS),Tup(List((None,Fld(_,Var(e1)))))) +//│ | | | | | [Desugarer.destructPattern] Result: «l is Var(KS)» +//│ | | | | | [Desugarer.destructPattern] scrutinee = Var(r); pattern = App(Var(KS),Tup(List((None,Fld(_,Var(e2)))))) +//│ | | | | | [Desugarer.destructPattern] Result: «r is Var(KS)» +//│ | | | | | Desugared term: case l of { KS => let $unapp = (KS).unapply(l,) in let e1 = ($unapp).0 in case r of { KS => let $unapp = (KS).unapply(r,) in let e2 = ($unapp).0 in sig(e1, e2,) } } +//│ | | | | | 1. Typing term case l of { KS => let $unapp = (KS).unapply(l,) in let e1 = ($unapp).0 in case r of { KS => let $unapp = (KS).unapply(r,) in let e2 = ($unapp).0 in sig(e1, e2,) } } +//│ | | | | | | 1. Typing term l +//│ | | | | | | 1. : K[‘L542'] +//│ | | | | | | CONSTRAIN K[‘L542'] T172' +//│ | | | | | | | Assigned Some(‘L542') +//│ | | | | | | | 1. C ((#K & KS[? :> ⊥ <: ⊤]) & {T: mut ‘L542'..‘L542'}) (2) +//│ | | | | | | | | Already a subtype by <:< +//│ | | | | | | Match arm KS: #KS & {A: mut A175_544'..A175_545'} intl {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')} +//│ | | | | | | var rfn: l :: K[‘L542'] & #KS & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')} +//│ | | | | | | 2. Typing term let $unapp = (KS).unapply(l,) in let e1 = ($unapp).0 in case r of { KS => let $unapp = (KS).unapply(r,) in let e2 = ($unapp).0 in sig(e1, e2,) } +//│ | | | | | | | 2. Typing term (KS).unapply(l,) +//│ | | | | | | | | 2. Typing term (KS).unapply +//│ | | | | | | | | | 2. Typing term (x::14,) => let _ = x : KS in [(x).#ev,] +//│ | | | | | | | | | | TYPING POLY LAM +//│ | | | | | | | | | | 3. Typing pattern [x::14,] +//│ | | | | | | | | | | | 3. Typing pattern x::14 +//│ | | | | | | | | | | | 3. : x548''' +//│ | | | | | | | | | | 3. : (x548''',) +//│ | | | | | | | | | | 3. Typing term let _ = x : KS in [(x).#ev,] +//│ | | | | | | | | | | | 3. Typing term x : KS +//│ | | | | | | | | | | | | 3. Typing term x +//│ | | | | | | | | | | | | 3. : x548''' +//│ | | | | | | | | | | | | Typing type TypeName(KS) +//│ | | | | | | | | | | | | | vars=Map(L -> ‘L542') newDefsInfo=Map() +//│ | | | | | | | | | | | | | 3. type TypeName(KS) +//│ | | | | | | | | | | | | | => #KS +//│ | | | | | | | | | | | | => #KS ——— +//│ | | | | | | | | | | | | CONSTRAIN x548''' +//│ | | | | | | | | | | | | where +//│ | | | | | | | | | | | | 3. C x548''' (0) +//│ | | | | | | | | | | | | | NEW x548''' UB (0) +//│ | | | | | | | | | | | 3. : #KS +//│ | | | | | | | | | | | 3. Typing term [(x).#ev,] +//│ | | | | | | | | | | | | 3. Typing term (x).#ev +//│ | | | | | | | | | | | | | 3. Typing term x +//│ | | | | | | | | | | | | | 3. : x548''' +//│ | | | | | | | | | | | | | CONSTRAIN x548''' +//│ | | | | | | | | | | | | | 3. C x548''' (#ev549''',)) —— where +//│ x548''' <: {#ev: #ev549'''} & #KS +//│ | | | | | | | | | 2. : ‹∀ 2. (x548''' -> (#ev549''',))› +//│ | | | | | | | | 2. : ‹∀ 2. (x548''' -> (#ev549''',))› +//│ | | | | | | | | 2. Typing term l +//│ | | | | | | | | 2. : ((K[‘L542'] & #KS) & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')}) +//│ | | | | | | | | CONSTRAIN ‹∀ 2. (x548''' -> (#ev549''',))› ) & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')}) -> α550'') +//│ | | | | | | | | where +//│ A175_544' <: A175_545' +//│ x548''' <: {#ev: #ev549'''} & #KS +//│ | | | | | | | | 2. C ‹∀ 2. (x548''' -> (#ev549''',))› ) & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')}) -> α550'') (0) +//│ | | | | | | | | | INST [2] ‹∀ 2. (x548''' -> (#ev549''',))› +//│ | | | | | | | | | where +//│ x548''' <: {#ev: #ev549'''} & #KS +//│ | | | | | | | | | TO [2] ~> (x548_551'' -> (#ev549_552'',)) +//│ | | | | | | | | | where +//│ x548_551'' <: {#ev: #ev549_552''} & #KS +//│ | | | | | | | | | 2. C (x548_551'' -> (#ev549_552'',)) ) & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')}) -> α550'') (2) +//│ | | | | | | | | | | 2. C (((K[‘L542'] & #KS) & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')}),) ) & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')}) ) & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')}) T172' +//│ | | | | | | | | | | | | | Assigned Some(‘L542') +//│ | | | | | | | | | | | | | Assigning A :: A175' := ? :> ⊥ <: ⊤ +//│ | | | | | | | | | | | | | Set A175_554 ~> A175' +//│ | | | | | | | | | | | | | Assigned Some(⊥..⊤) +//│ | | | | | | | | | | | | | 2. ARGH DNF(2, #KS{T: mut ‘L542'..‘L542', A: mut (A175_544' | ‘A546'')..(‘A546'' & A175_545')}) {T: mut ‘L542'..‘L542', A: mut (A175_544' | ‘A546'')..(‘A546'' & A175_545')} <: DNF(2, {#ev: #ev549_552''}) +//│ | | | | | | | | | | | | | | Possible: List({#ev: #ev549_552''}) +//│ | | | | | | | | | | | | | | 2. A #KS{T: mut ‘L542'..‘L542', A: mut (A175_544' | ‘A546'')..(‘A546'' & A175_545')} % List() {T: mut ‘L542'..‘L542', A: mut (A175_544' | ‘A546'')..(‘A546'' & A175_545')} % List() {T: mut ‘L542'..‘L542', A: mut (A175_544' | ‘A546'')..(‘A546'' & A175_545')} % List() ) & {A: mut (A175_544' | ‘A546'')..(A175_545' & ‘A546'')}) (6) +//│ | | | | | | | | | | | | | Already a subtype by <:< +//│ | | | | | | | | | | 2. C (#ev549_552'',) let $unapp = (KS).unapply(r,) in let e2 = ($unapp).0 in sig(e1, e2,) } +//│ | | | | | | | | 2. Typing term ($unapp).0 +//│ | | | | | | | | | 2. Typing term $unapp +//│ | | | | | | | | | 2. : α550'' +//│ | | | | | | | | | CONSTRAIN α550'' (#ev549_552'',) +//│ #ev549_552'' :> K[(A175_544' | ‘A546'')..(‘A546'' & A175_545')] +//│ | | | | | | | | | 2. C α550'' let $unapp = (KS).unapply(r,) in let e2 = ($unapp).0 in sig(e1, e2,) } +//│ | | | | | | | | | 2. Typing term r +//│ | | | | | | | | | 2. : K[‘L542'] +//│ | | | | | | | | | CONSTRAIN K[‘L542'] T172' +//│ | | | | | | | | | | Assigned Some(‘L542') +//│ | | | | | | | | | | 2. C ((#K & KS[? :> ⊥ <: ⊤]) & {T: mut ‘L542'..‘L542'}) (2) +//│ | | | | | | | | | | | Already a subtype by <:< +//│ | | | | | | | | | Match arm KS: #KS & {A: mut A175_557''..A175_558''} intl {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')} +//│ | | | | | | | | | var rfn: r :: K[‘L542'] & #KS & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')} +//│ | | | | | | | | | 3. Typing term let $unapp = (KS).unapply(r,) in let e2 = ($unapp).0 in sig(e1, e2,) +//│ | | | | | | | | | | 3. Typing term (KS).unapply(r,) +//│ | | | | | | | | | | | 3. Typing term (KS).unapply +//│ | | | | | | | | | | | | 3. Typing term (x::15,) => let _ = x : KS in [(x).#ev,] +//│ | | | | | | | | | | | | | TYPING POLY LAM +//│ | | | | | | | | | | | | | 4. Typing pattern [x::15,] +//│ | | | | | | | | | | | | | | 4. Typing pattern x::15 +//│ | | | | | | | | | | | | | | 4. : x561'''' +//│ | | | | | | | | | | | | | 4. : (x561'''',) +//│ | | | | | | | | | | | | | 4. Typing term let _ = x : KS in [(x).#ev,] +//│ | | | | | | | | | | | | | | 4. Typing term x : KS +//│ | | | | | | | | | | | | | | | 4. Typing term x +//│ | | | | | | | | | | | | | | | 4. : x561'''' +//│ | | | | | | | | | | | | | | | Typing type TypeName(KS) +//│ | | | | | | | | | | | | | | | | vars=Map(L -> ‘L542') newDefsInfo=Map() +//│ | | | | | | | | | | | | | | | | 4. type TypeName(KS) +//│ | | | | | | | | | | | | | | | | => #KS +//│ | | | | | | | | | | | | | | | => #KS ——— +//│ | | | | | | | | | | | | | | | CONSTRAIN x561'''' +//│ | | | | | | | | | | | | | | | where +//│ | | | | | | | | | | | | | | | 4. C x561'''' (0) +//│ | | | | | | | | | | | | | | | | NEW x561'''' UB (0) +//│ | | | | | | | | | | | | | | 4. : #KS +//│ | | | | | | | | | | | | | | 4. Typing term [(x).#ev,] +//│ | | | | | | | | | | | | | | | 4. Typing term (x).#ev +//│ | | | | | | | | | | | | | | | | 4. Typing term x +//│ | | | | | | | | | | | | | | | | 4. : x561'''' +//│ | | | | | | | | | | | | | | | | CONSTRAIN x561'''' +//│ | | | | | | | | | | | | | | | | 4. C x561'''' (#ev562'''',)) —— where +//│ x561'''' <: {#ev: #ev562''''} & #KS +//│ | | | | | | | | | | | | 3. : ‹∀ 3. (x561'''' -> (#ev562'''',))› +//│ | | | | | | | | | | | 3. : ‹∀ 3. (x561'''' -> (#ev562'''',))› +//│ | | | | | | | | | | | 3. Typing term r +//│ | | | | | | | | | | | 3. : ((K[‘L542'] & #KS) & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')}) +//│ | | | | | | | | | | | CONSTRAIN ‹∀ 3. (x561'''' -> (#ev562'''',))› ) & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')}) -> α563''') +//│ | | | | | | | | | | | where +//│ A175_557'' <: A175_558'' +//│ x561'''' <: {#ev: #ev562''''} & #KS +//│ | | | | | | | | | | | 3. C ‹∀ 3. (x561'''' -> (#ev562'''',))› ) & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')}) -> α563''') (0) +//│ | | | | | | | | | | | | INST [3] ‹∀ 3. (x561'''' -> (#ev562'''',))› +//│ | | | | | | | | | | | | where +//│ x561'''' <: {#ev: #ev562''''} & #KS +//│ | | | | | | | | | | | | TO [3] ~> (x561_564''' -> (#ev562_565''',)) +//│ | | | | | | | | | | | | where +//│ x561_564''' <: {#ev: #ev562_565'''} & #KS +//│ | | | | | | | | | | | | 3. C (x561_564''' -> (#ev562_565''',)) ) & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')}) -> α563''') (2) +//│ | | | | | | | | | | | | | 3. C (((K[‘L542'] & #KS) & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')}),) ) & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')}) ) & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')}) T172' +//│ | | | | | | | | | | | | | | | | Assigned Some(‘L542') +//│ | | | | | | | | | | | | | | | | Assigning A :: A175' := ? :> ⊥ <: ⊤ +//│ | | | | | | | | | | | | | | | | Set A175_567 ~> A175' +//│ | | | | | | | | | | | | | | | | Assigned Some(⊥..⊤) +//│ | | | | | | | | | | | | | | | | 3. ARGH DNF(3, #KS{T: mut ‘L542'..‘L542', A: mut (A175_557'' | ‘A559''')..(‘A559''' & A175_558'')}) {T: mut ‘L542'..‘L542', A: mut (A175_557'' | ‘A559''')..(‘A559''' & A175_558'')} <: DNF(3, {#ev: #ev562_565'''}) +//│ | | | | | | | | | | | | | | | | | Possible: List({#ev: #ev562_565'''}) +//│ | | | | | | | | | | | | | | | | | 3. A #KS{T: mut ‘L542'..‘L542', A: mut (A175_557'' | ‘A559''')..(‘A559''' & A175_558'')} % List() {T: mut ‘L542'..‘L542', A: mut (A175_557'' | ‘A559''')..(‘A559''' & A175_558'')} % List() {T: mut ‘L542'..‘L542', A: mut (A175_557'' | ‘A559''')..(‘A559''' & A175_558'')} % List() ) & {A: mut (A175_557'' | ‘A559''')..(A175_558'' & ‘A559''')}) (6) +//│ | | | | | | | | | | | | | | | | Already a subtype by <:< +//│ | | | | | | | | | | | | | 3. C (#ev562_565''',) (#ev562_565''',) +//│ #ev562_565''' :> K[(A175_557'' | ‘A559''')..(‘A559''' & A175_558'')] +//│ | | | | | | | | | | | | 3. C α563''' Int)›› +//│ | | | | | | | | | | | | 3. Typing term e1 +//│ | | | | | | | | | | | | 3. : α555'' +//│ | | | | | | | | | | | | 3. Typing term e2 +//│ | | | | | | | | | | | | 3. : α568''' +//│ | | | | | | | | | | | | CONSTRAIN ‹∀ 0. ‹∀ 0. ((K['L537'], K['L537'],) -> Int)›› α569''') +//│ | | | | | | | | | | | | where +//│ A175_544' <: A175_545' +//│ α555'' :> K[(A175_544' | ‘A546'')..(‘A546'' & A175_545')] +//│ A175_557'' <: A175_558'' +//│ α568''' :> K[(A175_557'' | ‘A559''')..(‘A559''' & A175_558'')] +//│ | | | | | | | | | | | | 3. C ‹∀ 0. ‹∀ 0. ((K['L537'], K['L537'],) -> Int)›› α569''') (0) +//│ | | | | | | | | | | | | | 3. C ‹∀ 0. ((K['L537'], K['L537'],) -> Int)› α569''') (2) +//│ | | | | | | | | | | | | | | INST [0] ‹∀ 0. ((K['L537'], K['L537'],) -> Int)› +//│ | | | | | | | | | | | | | | where +//│ | | | | | | | | | | | | | | TO [3] ~> ((K['L537_570'''], K['L537_570'''],) -> Int) +//│ | | | | | | | | | | | | | | where +//│ | | | | | | | | | | | | | | 3. C ((K['L537_570'''], K['L537_570'''],) -> Int) α569''') (4) +//│ | | | | | | | | | | | | | | | 3. C (α555'', α568''',) 'L537_571'' +//│ | | | | | | | | | | | | | | | | | | => 'L537_571'' +//│ | | | | | | | | | | | | | | | | | | EXTR[-] 'L537_570''' || 2 .. 1024 3 false +//│ | | | | | | | | | | | | | | | | | | | EXTR[-] 'L537_570''' || 2 .. 1024 3 false +//│ | | | | | | | | | | | | | | | | | | | | EXTR[-] 'L537_571'' || 2 .. 1024 2 true +//│ | | | | | | | | | | | | | | | | | | | | => 'L537_571'' +//│ | | | | | | | | | | | | | | | | | | | => 'L537_572'' +//│ | | | | | | | | | | | | | | | | | | => 'L537_572'' +//│ | | | | | | | | | | | | | | | | | => K[? :> 'L537_571'' <: 'L537_572''] +//│ | | | | | | | | | | | | | | | | | RECONSTRAINING TVs +//│ | | | | | | | | | | | | | | | | | | Reconstraining 'L537_571'' +//│ | | | | | | | | | | | | | | | | | | Reconstraining 'L537_572'' +//│ | | | | | | | | | | | | | | | | | EXTR RHS ~> K[? :> 'L537_571'' <: 'L537_572''] to 2 +//│ | | | | | | | | | | | | | | | | | where +//│ 'L537_572'' <: 'L537_571'' +//│ | | | | | | | | | | | | | | | | | 3. C α555'' 'L537_571'' <: 'L537_572''] (4) +//│ | | | | | | | | | | | | | | | | | | NEW α555'' UB (2) +//│ | | | | | | | | | | | | | | | | | | 3. C K[(A175_544' | ‘A546'')..(‘A546'' & A175_545')] 'L537_571'' <: 'L537_572''] (7) +//│ | | | | | | | | | | | | | | | | | | | 3. C 'L537_571'' A175_558'' +//│ | | | | | | | | | | | | | | | | | | | | | | | EXTR[+] ‘A559''' || 2 .. 1024 3 false +//│ | | | | | | | | | | | | | | | | | | | | | | | => ⊤(‘A559''') +//│ | | | | | | | | | | | | | | | | | | | | | | => (A175_558'' & ⊤(‘A559''')) +//│ | | | | | | | | | | | | | | | | | | | | | | EXTR LHS ~> (A175_558'' & ⊤(‘A559''')) to 2 +//│ | | | | | | | | | | | | | | | | | | | | | | where +//│ | | | | | | | | | | | | | | | | | | | | | | 3. C (A175_558'' & ⊤(‘A559''')) ⊥(‘A559''') +//│ | | | | | | | | | | | | | | | | | | | | | | | EXTR[-] A175_557'' || 2 .. 1024 2 true +//│ | | | | | | | | | | | | | | | | | | | | | | | => A175_557'' +//│ | | | | | | | | | | | | | | | | | | | | | | => (⊥(‘A559''') | A175_557'') +//│ | | | | | | | | | | | | | | | | | | | | | | EXTR RHS ~> (⊥(‘A559''') | A175_557'') to 2 +//│ | | | | | | | | | | | | | | | | | | | | | | where +//│ A175_544' <: A175_545' +//│ A175_557'' <: A175_558'' +//│ A175_558'' <: ((A175_544' | ‘A546'') | ~(⊤(‘A559'''))) +//│ | | | | | | | | | | | | | | | | | | | | | | 3. C 'L537_572'' Int +//│ | | | | | | | | | 3. C α569''' ,{A: mut A175_557''..A175_558''})] + List() and [α560''] | ⊥ +//│ | | | | | | | | | finishing case K[‘L542'] <: (#KS & {A: mut A175_557''..A175_558''}) +//│ | | | | | | | | | CONSTRAIN K[‘L542'] & {A: mut A175_557''..A175_558''}) +//│ | | | | | | | | | where +//│ A175_544' <: A175_545' +//│ A175_557'' :> (‘A546'' & A175_545') <: A175_558'' +//│ A175_558'' :> (‘A546'' & A175_545') <: ((A175_544' | ‘A546'') | ~(⊤(‘A559'''))) +//│ | | | | | | | | | 2. C K[‘L542'] & {A: mut A175_557''..A175_558''}) (0) +//│ | | | | | | | | | | 2. C K[‘L542'] (2) +//│ | | | | | | | | | | | Assigning T :: T172' := ‘L542' where +//│ | | | | | | | | | | | Set T172_573' ~> T172' +//│ | | | | | | | | | | | Assigned Some(‘L542') +//│ | | | | | | | | | | | 2. C ((#K & KS[? :> ⊥ <: ⊤]) & {T: mut ‘L542'..‘L542'}) (4) +//│ | | | | | | | | | | | | Assigning A :: A175' := ? :> ⊥ <: ⊤ +//│ | | | | | | | | | | | | Set A175_574 ~> A175' +//│ | | | | | | | | | | | | Assigned Some(⊥..⊤) +//│ | | | | | | | | | | | | 2. ARGH DNF(1, #KS{T: mut ‘L542'..‘L542', A: mut ..⊤}) {}) +//│ | | | | | | | | | | | | | DNF DISCHARGE CONSTRAINTS +//│ | | | | | | | | | | | | | Consider #KS{T: mut ‘L542'..‘L542', A: mut ..⊤} <: DNF(0, #KS{}) +//│ | | | | | | | | | | | | | OK #KS{T: mut ‘L542'..‘L542', A: mut ..⊤} <: #KS{} +//│ | | | | | | | | | | 2. C K[‘L542'] T172' +//│ | | | | | | | | | | | Assigned Some(‘L542') +//│ | | | | | | | | | | | Assigning A :: A175' := ? :> ⊥ <: ⊤ +//│ | | | | | | | | | | | Set A175_576 ~> A175' +//│ | | | | | | | | | | | Assigned Some(⊥..⊤) +//│ | | | | | | | | | | | 2. ARGH DNF(1, #KS{T: mut ‘L542'..‘L542', A: mut ..⊤}) {T: mut ‘L542'..‘L542', A: mut ..⊤} <: DNF(2, {A: mut A175_557''..A175_558''}) +//│ | | | | | | | | | | | | Possible: List({A: mut A175_557''..A175_558''}) +//│ | | | | | | | | | | | | 2. A #KS{T: mut ‘L542'..‘L542', A: mut ..⊤} % List() {T: mut ‘L542'..‘L542', A: mut ..⊤} % List() {T: mut ‘L542'..‘L542', A: mut ..⊤} % List() ⊤(‘A559''') +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | EXTR[+] ~(‘A546'') || 1 .. 1024 2 false +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | EXTR[-] ‘A546'' || 1 .. 1024 2 false +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | => ⊥(‘A546'') +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | => ~(⊥(‘A546'')) +//│ | | | | | | | | | | | | | | | | | | | | | | | | | => (⊤(‘A559''') & ~(⊥(‘A546''))) +//│ | | | | | | | | | | | | | | | | | | | | | | | | | EXTR LHS ~> (⊤(‘A559''') & ~(⊥(‘A546''))) to 1 +//│ | | | | | | | | | | | | | | | | | | | | | | | | | where +//│ | | | | | | | | | | | | | | | | | | | | | | | | | 2. C (⊤(‘A559''') & ~(⊥(‘A546''))) ⊤(‘A546'') +//│ | | | | | | | | | | | | | | | | | | | | => ~(⊤(‘A546'')) +//│ | | | | | | | | | | | | | | | | | | | | EXTR RHS ~> ~(⊤(‘A546'')) to 1 +//│ | | | | | | | | | | | | | | | | | | | | where +//│ | | | | | | | | | | | | | | | | | | | | 2. C A175_545' ⊤(‘A546'') +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | | ~> ~(⊤(‘A546'')) +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | allVarPols: +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | normLike[+] (⊤(‘A559''') & ~(⊥(‘A546''))) +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | | norm[+] (⊤(‘A559''') & ~(⊥(‘A546''))) +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | DNF: DNF(0, {}∧⊤(‘A559''')∧~(⊥(‘A546''))) +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | | ~> (⊤(‘A559''') & ~(⊥(‘A546''))) +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | CONSTRAIN #error<> Int +//│ | | | | | | | | | | | | | | | | | | | | | | | | | | | 2. C #error<> #error<> | Int +//│ | | | | | | 2. C α560'' ,{A: mut A175_544'..A175_545'})] + List() and [α547'] | ⊥ +//│ | | | | | | finishing case K[‘L542'] <: (#KS & {A: mut A175_544'..A175_545'}) +//│ | | | | | | CONSTRAIN K[‘L542'] & {A: mut A175_544'..A175_545'}) +//│ | | | | | | where +//│ A175_544' :> (⊤(‘A559''') & ~(⊥(‘A546''))) <: A175_545' +//│ A175_545' :> (⊤(‘A559''') & ~(⊥(‘A546''))) <: ~(⊤(‘A546'')) +//│ | | | | | | 1. C K[‘L542'] & {A: mut A175_544'..A175_545'}) (0) +//│ | | | | | | | 1. C K[‘L542'] (2) +//│ | | | | | | | | Assigning T :: T172' := ‘L542' where +//│ | | | | | | | | Set T172_581' ~> T172' +//│ | | | | | | | | Assigned Some(‘L542') +//│ | | | | | | | | 1. C ((#K & KS[? :> ⊥ <: ⊤]) & {T: mut ‘L542'..‘L542'}) (4) +//│ | | | | | | | | | Assigning A :: A175' := ? :> ⊥ <: ⊤ +//│ | | | | | | | | | Set A175_582 ~> A175' +//│ | | | | | | | | | Assigned Some(⊥..⊤) +//│ | | | | | | | | | 1. ARGH DNF(1, #KS{T: mut ‘L542'..‘L542', A: mut ..⊤}) {}) +//│ | | | | | | | | | | DNF DISCHARGE CONSTRAINTS +//│ | | | | | | | | | | Consider #KS{T: mut ‘L542'..‘L542', A: mut ..⊤} <: DNF(0, #KS{}) +//│ | | | | | | | | | | OK #KS{T: mut ‘L542'..‘L542', A: mut ..⊤} <: #KS{} +//│ | | | | | | | 1. C K[‘L542'] T172' +//│ | | | | | | | | Assigned Some(‘L542') +//│ | | | | | | | | Assigning A :: A175' := ? :> ⊥ <: ⊤ +//│ | | | | | | | | Set A175_584 ~> A175' +//│ | | | | | | | | Assigned Some(⊥..⊤) +//│ | | | | | | | | 1. ARGH DNF(1, #KS{T: mut ‘L542'..‘L542', A: mut ..⊤}) {T: mut ‘L542'..‘L542', A: mut ..⊤} <: DNF(1, {A: mut A175_544'..A175_545'}) +//│ | | | | | | | | | Possible: List({A: mut A175_544'..A175_545'}) +//│ | | | | | | | | | 1. A #KS{T: mut ‘L542'..‘L542', A: mut ..⊤} % List() {T: mut ‘L542'..‘L542', A: mut ..⊤} % List() {T: mut ‘L542'..‘L542', A: mut ..⊤} % List() ⊤(‘A546'') +//│ | | | | | | | | | | | | | | | | | | | | ~> ~(⊤(‘A546'')) +//│ | | | | | | | | | | | | | | | | | | | allVarPols: +//│ | | | | | | | | | | | | | | | | | | | normLike[+] ⊤ +//│ | | | | | | | | | | | | | | | | | | | | norm[+] ⊤ +//│ | | | | | | | | | | | | | | | | | | | | | DNF: DNF(0, ) +//│ | | | | | | | | | | | | | | | | | | | | ~> ⊤ +//│ | | | | | | | | | | | | | | | | | | | CONSTRAIN #error<> Int | #error<> +//│ | | | | | | | | | | | | | | | | | | | 1. C #error<> ⊥ +//│ | | | | | | | | | | | | | | | | | | allVarPols: +//│ | | | | | | | | | | | | | | | | | | normLike[+] (⊤(‘A559''') & ~(⊥(‘A546''))) +//│ | | | | | | | | | | | | | | | | | | | norm[+] (⊤(‘A559''') & ~(⊥(‘A546''))) +//│ | | | | | | | | | | | | | | | | | | | | DNF: DNF(0, {}∧⊤(‘A559''')∧~(⊥(‘A546''))) +//│ | | | | | | | | | | | | | | | | | | | ~> (⊤(‘A559''') & ~(⊥(‘A546''))) +//│ | | | | | 1. : α547' +//│ | | | | 1. : α547' +//│ | | | 1. : α547' +//│ | | 1. : ((l: K[‘L542'], r: K[‘L542'],) -> α547') +//│ | | CONSTRAIN ((l: K[‘L542'], r: K[‘L542'],) -> α547') #error<> | Int | #error<> +//│ | | 1. C ((l: K[‘L542'], r: K[‘L542'],) -> α547') α547')) where +//│ α547' :> #error<> | Int | #error<> +//│ | Typing unit statements +//│ | : None +//│ ======== TYPED ======== +//│ fun fr: ‹∀ 0. ((l: K[‘L542'], r: K[‘L542'],) -> α547')› where +//│ | α547' :> #error<> | Int | #error<> +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> (Int | error) + + + + +// :e +// fun fr[L](l: K[L], r: K[L]) = +// if l is KS(e1) and r is KS(e2) then [e1, e2] : [K[L], K[L]] else 0 + + + + + + + + + + +// * TODO investigate: 'L0 :> ??A <: ??A0 bad bounds? +// :d +// :e +fun fr[L](l: K[L]) = if l is KS(e1) then () => (e1 as K['X]) +//│ fun fr: forall 'L. (l: K['L]) -> () -> K[?] + +// Doesn't happen here: +fun fr[L](l: K[L]) = if l is KS(e1) then (e1 as K['X]) +//│ fun fr: forall 'L. (l: K['L]) -> K[?] + +// ~~Doesn't happen~~ happens here: +// :e +fun fr[L](l: K[L]) = if l is KS(e1) then () => (e1 as K[l.A]) +//│ fun fr: forall 'L. (l: K['L]) -> () -> K[out ??A] + + + + +// :d +:e +fun fr[L](l: K[L]) = if l is KS(e1) then (e1 as K[S['X]]) +//│ ╔══[ERROR] Type `??A` does not contain member `P` +//│ ║ l.9: class S[type P] +//│ ╙── ^ +//│ fun fr: forall 'L. (l: K['L]) -> (K[S[error]] | error) + +fun fr[L](l: K[L]) = if l is KS(e1) then (e1 as K[l.A]) +//│ fun fr: forall 'L. (l: K['L]) -> K[out ??A] + + + + diff --git a/shared/src/test/diff/gadt/ExtIntro_repro2.mls b/shared/src/test/diff/gadt/ExtIntro_repro2.mls new file mode 100644 index 0000000000..8af96e7fb6 --- /dev/null +++ b/shared/src/test/diff/gadt/ExtIntro_repro2.mls @@ -0,0 +1,108 @@ +:NewDefs +:DontDistributeForalls + +:NoJS + + +class Z +class S[type P](val pred: P) +//│ class Z { +//│ constructor() +//│ } +//│ class S[P](pred: P) + +// abstract class K[type T]: KS[?] +abstract class K[type T]: KS +class KS[type A](val ev: K[A]) extends K[S[A]] +//│ abstract class K[T]: KS[?] +//│ class KS[A](ev: K[A]) extends K + +// * TODO investigate: 'L0 :> ??A <: ??A0 bad bounds? +// :d +// :e +fun fr[L](l: K[L]) = if l is KS(e1) then () => (e1 as K['X]) +//│ fun fr: forall 'L. (l: K['L]) -> () -> K[in ??A] + +// Doesn't happen here: +fun fr[L](l: K[L]) = if l is KS(e1) then (e1 as K['X]) +//│ fun fr: forall 'L. (l: K['L]) -> K[in ??A] + +// fun fr[L](l: K[L]) = if l is KS(e1) then () => [(e1 as K['X]), e1 as K['X]] + +// MIN +// :d +// fun fr[L](l: K[L], r: K[L]) = +// if l is KS(e1) and r is KS(e2) then [e1, e2] as [K['X], K['X]] + +// :d +fun helper[L, A1, A2](l: KS[A1] & K[L], r: KS[A2] & K[L]) = + // (l.ev : K[A1]), () + // (l : K[l.T.Pred]), () + // (l : KS[l.T]), () + (l : K[r.T]), () + (l : K[r.T] & KS[A1]), () + (l : K[r.T] & KS[l.T.P]), () + // ((l : K[r.T] & KS[A1]) : KS[A1] & KS[A2]), () + ((error : l.T.P) : A1), () + ((error : A1) : l.T.P), () + // ((error : l.T.P)), () + // () + (l : K[r.T] & KS[l.T.P]).ev +//│ fun helper: forall 'A1 'L 'A2. (l: KS['A1] & K['L], r: KS['A2] & K['L]) -> K['A1] + +fun helper[L, A1, A2](l: KS[A1] & K[L], r: KS[A2] & K[L]) = + // (l : KS[l.T.P]).ev + // (r : KS[r.T.P]).ev + [(l : KS[l.T.P]).ev, (r : KS[r.T.P]).ev] +//│ fun helper: forall 'A1 'L 'A2. (l: KS['A1] & K['L], r: KS['A2] & K['L]) -> [K['A1], K['A2]] + + +fun rec_sig: (K['L], K['L]) -> Int +//│ fun rec_sig: forall 'L. (K['L], K['L]) -> Int + +fun helper[L, A1, A2](l: KS[A1] & K[L], r: KS[A2] & K[L]): [K[A1], K[A1]] = error +//│ fun helper: forall 'A1 'L 'A2. (l: KS['A1] & K['L], r: KS['A2] & K['L]) -> [K['A1], K['A1]] + +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then + let tmp = helper(l, r) + rec_sig(tmp.0, tmp.1) +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> Int + + + + +fun sig: (K['L], K['L]) -> Int +//│ fun sig: forall 'L. (K['L], K['L]) -> Int + +// :d +fun fr[L](l: K[L], r: K[L]) = + if l is KS(e1) and r is KS(e2) then sig(e1, e2) +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.80: if l is KS(e1) and r is KS(e2) then sig(e1, e2) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `??A & ??A0 & ~??A1` does not match type `~??A2` +//│ ║ l.75: fun sig: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.16: class KS[type A](val ev: K[A]) extends K[S[A]] +//│ ╙── ^ +//│ TEST CASE FAILURE: There was an unexpected type error +//│ ╔══[ERROR] Type error in `case` expression +//│ ║ l.80: if l is KS(e1) and r is KS(e2) then sig(e1, e2) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.16: class KS[type A](val ev: K[A]) extends K[S[A]] +//│ ║ ^ +//│ ╟── into type `~??A` +//│ ║ l.75: fun sig: (K['L], K['L]) -> Int +//│ ║ ^^ +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.75: fun sig: (K['L], K['L]) -> Int +//│ ╙── ^^ +//│ TEST CASE FAILURE: There was an unexpected type error +//│ fun fr: forall 'L. (l: K['L], r: K['L]) -> (Int | error) + + + + diff --git a/shared/src/test/diff/gadt/GADT1.mls b/shared/src/test/diff/gadt/GADT1.mls new file mode 100644 index 0000000000..18cf475ae9 --- /dev/null +++ b/shared/src/test/diff/gadt/GADT1.mls @@ -0,0 +1,390 @@ +:NewDefs + +// natural numbers for index // + +class Z +class S[type P] +//│ class Z { +//│ constructor() +//│ } +//│ class S[P] { +//│ constructor() +//│ } + +// sized list // + +abstract class Vec[type L, type T]: Nil[T] | Cons[?, T] +class Nil[T] extends Vec[Z, T] +class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ abstract class Vec[L, T]: Cons[?, T] | Nil[T] +//│ class Nil[T] extends Vec { +//│ constructor() +//│ } +//│ class Cons[H, T](h: T, t: Vec[H, T]) extends Vec + +// functions // + +fun head[T](xs: Vec[S['l], T]): T = + if xs is Cons(h, t) then h : xs.T else error +//│ fun head: forall 'l 'T. (xs: Vec[S['l], 'T]) -> 'T + +fun tail[L, T](xs: Vec[S[L], T]): Vec[L, T] = + if xs is Cons(h, t) then t : Vec[xs.L.P, xs.T] else error +//│ fun tail: forall 'L 'T. (xs: Vec[S['L], 'T]) -> Vec['L, 'T] + +fun len: Vec['l, 'a] -> Int +fun len(xs: Vec['l, 'a]) = if xs is + Nil then 0 + Cons(h, t) then 1 + len(t) +//│ fun len: forall 'l 'a. (xs: Vec['l, 'a]) -> Int +//│ fun len: forall 'l0 'a0. Vec['l0, 'a0] -> Int + +fun map: ('A -> 'B, Vec['L, 'A]) -> Vec['L, 'B] +fun map[L, A, B](f, xs: Vec[L, A]): Vec[xs.L, 'B] = if xs is + Nil then new Nil + Cons(h, t) then Cons(f(h), map(f, t)) +//│ fun map: forall 'A 'B 'L 'L0 'B0 'B1. ((??T & 'A) -> 'B, xs: Vec['L, 'A]) -> Vec[in S[in ??H out nothing] & 'L0 | Z & 'L1 | 'L out 'L & (Z & 'L0 | 'L1 & (S[out ??H] | 'L0)), in 'B0 | 'B & 'B1 out 'B0 & ('B | 'B1)] +//│ fun map: forall 'A0 'B2 'L2. ('A0 -> 'B2, Vec['L2, 'A0]) -> Vec['L2, 'B2] + +// TODO +fun zipSum: (Vec['L, Int], Vec['L, Int]) -> Vec['L, Int] +fun zipSum[L, A](xs: Vec[L, Int], ys: Vec[L, Int]): Vec[L, Int] = + if xs is Nil and ys is Nil then + new Nil : Vec[xs.L, Int] + else if xs is Cons(x, tx) and ys is Cons(y, ty) then + Cons(x + y, zipSum(tx, ty)) : Vec[xs.L, Int] + else error +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.54: else if xs is Cons(x, tx) and ys is Cons(y, ty) then +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.55: Cons(x + y, zipSum(tx, ty)) : Vec[xs.L, Int] +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.56: else error +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── type `??H & ~??H0` does not match type `~??H1` +//│ ║ l.50: fun zipSum: (Vec['L, Int], Vec['L, Int]) -> Vec['L, Int] +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.52: if xs is Nil and ys is Nil then +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.53: new Nil : Vec[xs.L, Int] +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.54: else if xs is Cons(x, tx) and ys is Cons(y, ty) then +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.55: Cons(x + y, zipSum(tx, ty)) : Vec[xs.L, Int] +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.56: else error +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `~??H` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.50: fun zipSum: (Vec['L, Int], Vec['L, Int]) -> Vec['L, Int] +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.50: fun zipSum: (Vec['L, Int], Vec['L, Int]) -> Vec['L, Int] +//│ ║ ^^ +//│ ╟── Note: type parameter H is defined at: +//│ ║ l.18: class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ ╙── ^ +//│ fun zipSum: forall 'L. (xs: Vec['L, Int], ys: Vec['L, Int]) -> Vec['L, Int] +//│ fun zipSum: forall 'L0. (Vec['L0, Int], Vec['L0, Int]) -> Vec['L0, Int] + +// FIXME +fun zip: (Vec['L, 'A], Vec['L, 'B]) -> Vec['L, ['A, 'B]] +fun zip[L, A, B](xs: Vec[L, A], ys: Vec[L, B]): Vec[L, [A, B]] = + if xs is Nil and ys is Nil then + (new Nil) as Vec[xs.L, [A, B]] + else if xs is Cons(x, tx) and ys is Cons(y, ty) then + Cons([x, y], zip(tx, ty)) as Vec[xs.L, [A, B]] + else error +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.96: else if xs is Cons(x, tx) and ys is Cons(y, ty) then +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.97: Cons([x, y], zip(tx, ty)) as Vec[xs.L, [A, B]] +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.98: else error +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── type `??H & ~??H0` does not match type `~??H1` +//│ ║ l.92: fun zip: (Vec['L, 'A], Vec['L, 'B]) -> Vec['L, ['A, 'B]] +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.94: if xs is Nil and ys is Nil then +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.95: (new Nil) as Vec[xs.L, [A, B]] +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.96: else if xs is Cons(x, tx) and ys is Cons(y, ty) then +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.97: Cons([x, y], zip(tx, ty)) as Vec[xs.L, [A, B]] +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.98: else error +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `~??H` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.92: fun zip: (Vec['L, 'A], Vec['L, 'B]) -> Vec['L, ['A, 'B]] +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.92: fun zip: (Vec['L, 'A], Vec['L, 'B]) -> Vec['L, ['A, 'B]] +//│ ║ ^^ +//│ ╟── Note: type parameter H is defined at: +//│ ║ l.18: class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ ╙── ^ +//│ fun zip: forall 'L 'A 'B. (xs: Vec['L, 'A], ys: Vec['L, 'B]) -> Vec['L, ['A, 'B]] +//│ fun zip: forall 'L0 'A0 'B0. (Vec['L0, 'A0], Vec['L0, 'B0]) -> Vec['L0, ['A0, 'B0]] + +fun sum: Vec['l, Int] -> Int +fun sum(xs) = if xs is + Nil then 0 + Cons(h, t) then h + sum(t) +//│ fun sum: (Cons[?, in Int & ~??T out Int | ~??T0] | Nil[?]) -> Int +//│ fun sum: forall 'l. Vec['l, Int] -> Int + +// construct lisp style list lol +// fun toList: (Vec['l, 'a]) -> (['a, 'xs] as 'xs) +fun toList: (((Vec['l, 'a]) -> 'xs) where ['a, 'xs] | [] : 'xs) +fun toList(xs) = if xs is + Nil then [] + Cons(h, t) then [h, toList(t)] +//│ fun toList: forall 'T 'xs. (Cons[?, out 'T] | Nil[?]) -> 'xs +//│ fun toList: forall 'l 'a 'xs0. Vec['l, 'a] -> 'xs0 +//│ where +//│ 'xs0 :> Array['a | 'xs0] +//│ 'xs :> Array[??T & 'T | 'xs] + +:e +head(new Nil) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.153: head(new Nil) +//│ ║ ^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S['l]` +//│ ║ l.17: class Nil[T] extends Vec[Z, T] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.27: fun head[T](xs: Vec[S['l], T]): T = +//│ ╙── ^^^^^ +//│ error +//│ res +//│ Runtime error: +//│ Error: an error was thrown + +:e +tail(new Nil) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.169: tail(new Nil) +//│ ║ ^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S[?L]` +//│ ║ l.17: class Nil[T] extends Vec[Z, T] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.31: fun tail[L, T](xs: Vec[S[L], T]): Vec[L, T] = +//│ ╙── ^^^^ +//│ Vec['L, 'T] | error +//│ res +//│ Runtime error: +//│ Error: an error was thrown + +head(Cons(1, Cons(2, new Nil))) +//│ 1 | 2 +//│ res +//│ = 1 + +tail(Cons(1, Cons(2, new Nil))) +//│ Vec[S[Z], 'T] +//│ where +//│ 'T :> 1 | 2 +//│ res +//│ = Cons {} + +len(new Nil) +//│ Int +//│ res +//│ = 0 + +len(Cons(1, Cons(2, new Nil))) +//│ Int +//│ res +//│ = 2 + +:e +zip(Cons(1, new Nil), new Nil) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.207: zip(Cons(1, new Nil), new Nil) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S[?H]` +//│ ║ l.17: class Nil[T] extends Vec[Z, T] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.18: class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ ║ ^^^^ +//│ ╟── from type variable: +//│ ║ l.92: fun zip: (Vec['L, 'A], Vec['L, 'B]) -> Vec['L, ['A, 'B]] +//│ ╙── ^^ +//│ Vec[out S[Z] | Z, ['A, 'B]] | error +//│ where +//│ 'A :> 1 +//│ res +//│ Runtime error: +//│ Error: an error was thrown + +zip(Cons(1, new Nil), Cons(2, new Nil)) +//│ Vec[S[Z], ['A, 'B]] +//│ where +//│ 'B :> 2 +//│ 'A :> 1 +//│ res +//│ = Cons {} + +let vec1 = Cons(1, Cons(2, Cons(3, new Nil))) +//│ let vec1: Cons[S[S[Z]], 'T] +//│ where +//│ 'T :> 1 | 2 | 3 +//│ vec1 +//│ = Cons {} + +vec1 : Vec['l, Int] +//│ Vec[S[S[S[Z]]], Int] +//│ res +//│ = Cons {} + +:e +vec1 : Vec[Z, Int] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.248: vec1 : Vec[Z, Int] +//│ ║ ^^^^ +//│ ╟── type `S[?H]` is not an instance of `Z` +//│ ║ l.18: class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.248: vec1 : Vec[Z, Int] +//│ ╙── ^ +//│ Vec[Z, Int] +//│ res +//│ = Cons {} + +map(x => x * 2, vec1) +//│ Vec[S[S[S[Z]]], 'B] +//│ where +//│ 'B :> Int +//│ res +//│ = Cons {} + +sum(vec1) +//│ Int +//│ res +//│ = 6 + +toList(vec1) +//│ forall 'xs. 'xs +//│ where +//│ 'xs :> Array[Int | 'xs] +//│ res +//│ = [ 1, [ 2, [ 3, [] ] ] ] + +fun head2[A](h: Vec[S[S['a]], A]): A = + if h is Cons(_, Cons(h, _)) then h else error +//│ fun head2: forall 'a 'A. (h: Vec[S[S['a]], 'A]) -> 'A + +:e +head2(Cons(1, new Nil)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.286: head2(Cons(1, new Nil)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S['a]` +//│ ║ l.17: class Nil[T] extends Vec[Z, T] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.281: fun head2[A](h: Vec[S[S['a]], A]): A = +//│ ╙── ^^^^^ +//│ 1 | error +//│ res +//│ Runtime error: +//│ Error: an error was thrown + +// FIXME this should failed +fun verr: (Vec['L, Int], Vec['L, Int]) -> Bool +fun verr[L](xs: Vec[L, Int], ys: Vec[L, Int]): Bool = + if xs is Cons(x, tx) and ys is Cons(y, ty) + then verr(tx, Cons(0, ty)) // <- unequal size here + else false +//│ ╔══[ERROR] Type error in `case` expression +//│ ║ l.304: if xs is Cons(x, tx) and ys is Cons(y, ty) +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ║ l.305: then verr(tx, Cons(0, ty)) // <- unequal size here +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.306: else false +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `H` leaks out of its scope +//│ ║ l.18: class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ ║ ^ +//│ ╟── into type `nothing` +//│ ╟── adding a type annotation to any of the following terms may help resolve the problem +//│ ╟── • this application: +//│ ║ l.305: then verr(tx, Cons(0, ty)) // <- unequal size here +//│ ║ ^^^^^^^^^^^ +//│ ╟── • this reference: +//│ ║ l.305: then verr(tx, Cons(0, ty)) // <- unequal size here +//│ ╙── ^^^^ +//│ ╔══[ERROR] Type `??H` does not contain member `P` +//│ ║ l.6: class S[type P] +//│ ╙── ^ +//│ fun verr: forall 'L. (xs: Vec['L, Int], ys: Vec['L, Int]) -> Bool +//│ fun verr: forall 'L0. (Vec['L0, Int], Vec['L0, Int]) -> Bool + +// TODO somehow checks +fun vecEq: (Vec['L, Int], Vec['L, Int]) -> Bool +fun vecEq[L](xs: Vec[L, Int], ys: Vec[L, Int]): Bool = + if xs is Nil and ys is Nil then true + else if xs is Cons(x, tx) and ys is Cons(y, ty) then (x == y) && vecEq(tx, ty) + else false +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.335: else if xs is Cons(x, tx) and ys is Cons(y, ty) then (x == y) && vecEq(tx, ty) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.336: else false +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── type `??H & ~??H0` does not match type `~??H1` +//│ ║ l.332: fun vecEq: (Vec['L, Int], Vec['L, Int]) -> Bool +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.334: if xs is Nil and ys is Nil then true +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.335: else if xs is Cons(x, tx) and ys is Cons(y, ty) then (x == y) && vecEq(tx, ty) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.336: else false +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `~??H` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.332: fun vecEq: (Vec['L, Int], Vec['L, Int]) -> Bool +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.332: fun vecEq: (Vec['L, Int], Vec['L, Int]) -> Bool +//│ ║ ^^ +//│ ╟── Note: type parameter H is defined at: +//│ ║ l.18: class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ ╙── ^ +//│ fun vecEq: forall 'L. (xs: Vec['L, Int], ys: Vec['L, Int]) -> Bool +//│ fun vecEq: forall 'L0. (Vec['L0, Int], Vec['L0, Int]) -> Bool + +vecEq(Cons(1, Cons(2, new Nil)), Cons(1, Cons(2, new Nil))) +vecEq(Cons(2, Cons(1, new Nil)), Cons(1, Cons(2, new Nil))) +//│ Bool +//│ res +//│ = true +//│ res +//│ = false + +:e +vecEq(Cons(1, Cons(2, new Nil)), Cons(2, new Nil)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.374: vecEq(Cons(1, Cons(2, new Nil)), Cons(2, new Nil)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Z` is not an instance of `S[?H]` +//│ ║ l.17: class Nil[T] extends Vec[Z, T] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.18: class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ ║ ^^^^ +//│ ╟── Note: type parameter H is defined at: +//│ ║ l.18: class Cons[H, T](val h: T, val t: Vec[H, T]) extends Vec[S[H], T] +//│ ╙── ^ +//│ error | false | true +//│ res +//│ = false + diff --git a/shared/src/test/diff/gadt/GADT2.mls b/shared/src/test/diff/gadt/GADT2.mls new file mode 100644 index 0000000000..7ecb6abb6d --- /dev/null +++ b/shared/src/test/diff/gadt/GADT2.mls @@ -0,0 +1,175 @@ +:NewDefs + +fun fst([x, y]) = x +fun snd([x, y]) = y +//│ fun fst: forall 'a. (['a, anything]) -> 'a +//│ fun snd: forall 'b. ([anything, 'b]) -> 'b + +// dependent types // + +abstract class Rep[type T]: IntRep | BoolRep | PairRep[?,?] +class IntRep extends Rep[Int] +class BoolRep extends Rep[Bool] +class PairRep[A, B](val a: Rep[A], val b: Rep[B]) extends Rep[[A, B]] +//│ abstract class Rep[T]: BoolRep | IntRep | PairRep[?, ?] +//│ class IntRep extends Rep { +//│ constructor() +//│ } +//│ class BoolRep extends Rep { +//│ constructor() +//│ } +//│ class PairRep[A, B](a: Rep[A], b: Rep[B]) extends Rep + +fun equal: (Rep['T], 'T, 'T) -> Bool +fun equal[T](ev: Rep[T], x: T, y: T) = if ev is + IntRep then (x : ev.T) == (y : ev.T) + BoolRep then ((x : ev.T) && (y : ev.T)) || (not(x : ev.T) && not(y : ev.T)) + PairRep(a, b) then equal(a, fst(x : ev.T), fst(y : ev.T)) && equal(b, snd(x : ev.T), snd(y : ev.T)) +//│ fun equal: forall 'T. (ev: Rep['T], x: 'T, y: 'T) -> Bool +//│ fun equal: forall 'T0. (Rep['T0], 'T0, 'T0) -> Bool + +equal(new IntRep, 1+1, 2) +//│ Bool +//│ res +//│ = true + +:e +equal(new BoolRep, 1+1, true) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.37: equal(new BoolRep, 1+1, true) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── operator application of type `Int` is not an instance of type `Bool` +//│ ║ l.37: equal(new BoolRep, 1+1, true) +//│ ║ ^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.12: class BoolRep extends Rep[Bool] +//│ ║ ^^^^ +//│ ╟── from type variable: +//│ ║ l.23: fun equal: (Rep['T], 'T, 'T) -> Bool +//│ ╙── ^^ +//│ error | false | true +//│ res +//│ = true + +equal(PairRep(PairRep(new IntRep, new IntRep), new IntRep), [[1,0], 2], [[4,1], 3]) +//│ Bool +//│ res +//│ = false + +equal(PairRep(new IntRep, new BoolRep), [1, false], [1, false]) +//│ Bool +//│ res +//│ = true + +:e +equal(PairRep(new IntRep, new IntRep), [1, 3], [1, true]) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.65: equal(PairRep(new IntRep, new IntRep), [1, 3], [1, true]) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── reference of type `true` is not an instance of `Int` +//│ ║ l.65: equal(PairRep(new IntRep, new IntRep), [1, 3], [1, true]) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.11: class IntRep extends Rep[Int] +//│ ║ ^^^ +//│ ╟── Note: type parameter B is defined at: +//│ ║ l.13: class PairRep[A, B](val a: Rep[A], val b: Rep[B]) extends Rep[[A, B]] +//│ ╙── ^ +//│ error | false | true +//│ res +//│ = false + +fun equal: (Rep['T], 'T, 'T) -> Bool +fun equal[T](ev: Rep[T], x: T, y: T): Bool = if ev is + IntRep then (x as ev.T) == (y as ev.T) + BoolRep then ((x as ev.T) && (y as ev.T)) || (not(x as ev.T) && not(y as ev.T)) + PairRep(a, b) then equal(a, fst(x as ev.T), fst(y as ev.T)) && equal(b, snd(x as ev.T), snd(y as ev.T)) +//│ fun equal: forall 'T. (ev: Rep['T], x: 'T, y: 'T) -> Bool +//│ fun equal: forall 'T0. (Rep['T0], 'T0, 'T0) -> Bool + +// perfect binary tree // + +abstract class Perfect[type T]: Leaf | Node[?] +class Leaf(val a: Int) extends Perfect[Int] +class Node[A](val l: Perfect[A], val r: Perfect[A]) extends Perfect[[A, A]] +//│ abstract class Perfect[T]: Leaf | Node[?] +//│ class Leaf(a: Int) extends Perfect +//│ class Node[A](l: Perfect[A], r: Perfect[A]) extends Perfect + +fun size: Perfect['T] -> Int +fun size[T](t: Perfect[T]): Int = if t is + Node(l, r) then size(l) + size(r) + else 1 +//│ fun size: forall 'T. (t: Perfect['T]) -> Int +//│ fun size: forall 'T0. Perfect['T0] -> Int + +fun head: Perfect['T] -> Int +fun head[T](t: Perfect[T]): Int = if t is + Leaf(a) then a + Node(l, r) then head(l) +//│ fun head: forall 'T. (t: Perfect['T]) -> Int +//│ fun head: forall 'T0. Perfect['T0] -> Int + +fun flip: Perfect['A] -> Perfect['A] +fun flip[A](t: Perfect[A]): Perfect[t.T] = if t is + Leaf(a) then Leaf(a) + Node(l, r) then Node(flip(r), flip(l)) +//│ fun flip: forall 'A 'T. (t: Perfect['A]) -> Perfect[in Int & 'T0 | [nothing, nothing] & 'T | 'A out 'A & ([??A, ??A] & 'T0 | 'T & (Int | 'T0))] +//│ fun flip: forall 'A0. Perfect['A0] -> Perfect['A0] + +let test1 = Node(Node(Leaf(1), Leaf(2)), Node(Leaf(3), Leaf(4))) +//│ let test1: Node[[Int, Int]] +//│ test1 +//│ = Node {} + +:e +let test2 = Node(Leaf(1), Node(Leaf(2), Leaf(3))) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.126: let test2 = Node(Leaf(1), Node(Leaf(2), Leaf(3))) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `[?A, ?A]` is not an instance of type `Int` +//│ ║ l.94: class Node[A](val l: Perfect[A], val r: Perfect[A]) extends Perfect[[A, A]] +//│ ║ ^^^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.93: class Leaf(val a: Int) extends Perfect[Int] +//│ ║ ^^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.94: class Node[A](val l: Perfect[A], val r: Perfect[A]) extends Perfect[[A, A]] +//│ ╙── ^ +//│ let test2: Node[out Int | [Int, Int]] | error +//│ test2 +//│ = Node {} + +:e +head(Node(Node(Leaf(1), Leaf(2)), Leaf(3))) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.144: head(Node(Node(Leaf(1), Leaf(2)), Leaf(3))) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Int` is not a 2-element tuple +//│ ║ l.93: class Leaf(val a: Int) extends Perfect[Int] +//│ ║ ^^^ +//│ ╟── Note: constraint arises from tuple type: +//│ ║ l.94: class Node[A](val l: Perfect[A], val r: Perfect[A]) extends Perfect[[A, A]] +//│ ║ ^^^^^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.94: class Node[A](val l: Perfect[A], val r: Perfect[A]) extends Perfect[[A, A]] +//│ ╙── ^ +//│ Int +//│ res +//│ = 1 + +head(test1) +//│ Int +//│ res +//│ = 1 + +flip(test1) +//│ Perfect[[[Int, Int], [Int, Int]]] +//│ res +//│ = Node {} + +size(test1) +//│ Int +//│ res +//│ = 4 + diff --git a/shared/src/test/diff/gadt/GADT3.mls b/shared/src/test/diff/gadt/GADT3.mls new file mode 100644 index 0000000000..bac42cc3a9 --- /dev/null +++ b/shared/src/test/diff/gadt/GADT3.mls @@ -0,0 +1,243 @@ +:NewDefs + +abstract class Foo[type T]: Bar | Baz[?] +class Bar extends Foo[Int] +class Baz[T](val x: Foo[T]) extends Foo[[T]] +//│ abstract class Foo[T]: Bar | Baz[?] +//│ class Bar extends Foo { +//│ constructor() +//│ } +//│ class Baz[T](x: Foo[T]) extends Foo + +fun foo: Foo['T] -> Int +fun foo[T](f: Foo[T]): Int = if f is + Bar then 1 + Baz(x) then 1 + foo(x) +//│ fun foo: forall 'T. (f: Foo['T]) -> Int +//│ fun foo: forall 'T0. Foo['T0] -> Int + +foo(Baz(Baz(new Bar))) +//│ Int +//│ res +//│ = 3 + +fun foo: Foo['a] -> Int +fun foo(f: Foo['a]) = if f is + Bar then 1 + Baz(x) then 1 + foo(x) +//│ fun foo: forall 'a. (f: Foo['a]) -> Int +//│ fun foo: forall 'a0. Foo['a0] -> Int + +fun foo: Foo['a] -> Int +fun foo(f) = if f is + Bar then 1 + Baz(x) then 1 + foo(x) +//│ fun foo: (Bar | Baz[?]) -> Int +//│ fun foo: forall 'a. Foo['a] -> Int + +fun foo: Foo[?] -> Int +fun foo(f: Foo[?]): Int = if f is + Bar then 1 + Baz(x) then 1 + foo(x) +//│ fun foo: (f: Foo[?]) -> Int +//│ fun foo: Foo[?] -> Int + +fun bar(f) = if f is + Bar then 0 + Baz(_) then 1 +//│ fun bar: (Bar | Baz[?]) -> (0 | 1) + +bar(Baz(new Bar)) +//│ 0 | 1 +//│ res +//│ = 1 + +// FIXME +fun baz : (Foo['T], Foo['T]) -> Bool +fun baz[T](x: Foo[T], y: Foo[T]): Bool = + if x is Baz(a) and y is Baz(b) then baz(a, b) + else if x is Bar and y is Bar then true + else false +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.58: if x is Baz(a) and y is Baz(b) then baz(a, b) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.59: else if x is Bar and y is Bar then true +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.60: else false +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── type `??T & ~??T0` does not match type `~??T1` +//│ ║ l.56: fun baz : (Foo['T], Foo['T]) -> Bool +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.58: if x is Baz(a) and y is Baz(b) then baz(a, b) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.59: else if x is Bar and y is Bar then true +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.60: else false +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `~??T` +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.56: fun baz : (Foo['T], Foo['T]) -> Bool +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.56: fun baz : (Foo['T], Foo['T]) -> Bool +//│ ║ ^^ +//│ ╟── Note: type parameter T is defined at: +//│ ║ l.5: class Baz[T](val x: Foo[T]) extends Foo[[T]] +//│ ╙── ^ +//│ fun baz: forall 'T. (x: Foo['T], y: Foo['T]) -> Bool +//│ fun baz: forall 'T0. (Foo['T0], Foo['T0]) -> Bool + +// FIXME +fun baz : (Foo['T], Foo['T]) -> Bool +fun baz[T](x: Foo[T], y: Foo[T]): Bool = + if x is Baz(a) and y is Baz(b) then baz(a, (b as Foo[a.T])) + else if x is Bar and y is Bar then true + else false +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.94: if x is Baz(a) and y is Baz(b) then baz(a, (b as Foo[a.T])) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.95: else if x is Bar and y is Bar then true +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.96: else false +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── type `??T & ~[nothing]` does not match type `~(Int & ??T0)` +//│ ║ l.94: if x is Baz(a) and y is Baz(b) then baz(a, (b as Foo[a.T])) +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.94: if x is Baz(a) and y is Baz(b) then baz(a, (b as Foo[a.T])) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.95: else if x is Bar and y is Bar then true +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.96: else false +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `~([anything] & ??T)` +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.94: if x is Baz(a) and y is Baz(b) then baz(a, (b as Foo[a.T])) +//│ ║ ^^ +//│ ╟── Note: type parameter T is defined at: +//│ ║ l.5: class Baz[T](val x: Foo[T]) extends Foo[[T]] +//│ ╙── ^ +//│ fun baz: forall 'T. (x: Foo['T], y: Foo['T]) -> Bool +//│ fun baz: forall 'T0. (Foo['T0], Foo['T0]) -> Bool + +abstract class C[type T]: D1 | D2[?, ?] +class D1 extends C[Int] +class D2[A, B](val a: C[A], val b: C[B]) extends C[[A, B]] +//│ abstract class C[T]: D1 | D2[?, ?] +//│ class D1 extends C { +//│ constructor() +//│ } +//│ class D2[A, B](a: C[A], b: C[B]) extends C + +abstract class C[type T]: C1[T] | C2 +class C1[type A](c: A) extends C[A] +class C2 extends C[Int] +//│ abstract class C[T]: C1[T] | C2 +//│ class C1[A](c: A) extends C +//│ class C2 extends C { +//│ constructor() +//│ } + +:e // Needs type annot on parameter for GADT reasoning +fun foo: C['T] -> 'T +fun foo(x) = if x is + C1(c) then c : x.T + C2 then 0 : x.T +//│ ╔══[ERROR] Type mismatch in definition: +//│ ║ l.144: fun foo(x) = if x is +//│ ║ ^^^^^^^^^^^^^^^^ +//│ ║ l.145: C1(c) then c : x.T +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.146: C2 then 0 : x.T +//│ ║ ^^^^^^^^^^^^^^^^ +//│ ╟── type `Int` does not match type `'T` +//│ ║ l.135: class C2 extends C[Int] +//│ ║ ^^^ +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.143: fun foo: C['T] -> 'T +//│ ╙── ^^ +//│ fun foo: forall 'A. (C1['A] | C2) -> (Int | ??A & 'A) +//│ fun foo: forall 'T. C['T] -> 'T + +foo(C1(true)) +//│ true +//│ res +//│ = true + +foo(new C2) +//│ Int +//│ res +//│ = 0 + +fun foo(x: C['a]): x.T = if x is + C1(c) then c : x.T + C2 then 0 : x.T +//│ fun foo: forall 'a. (x: C['a]) -> (Int & 'a) + +abstract class Option[type out T]: None | Some[T] +module None extends Option[nothing] +class Some[A](get: A) extends Option[A] +//│ abstract class Option[T]: None | Some[T] +//│ module None extends Option +//│ class Some[A](get: A) extends Option + +fun getOr(x, d) = if x is + None then d + Some(g) then g +//│ fun getOr: forall 'A 'a. (None | Some['A], 'a) -> (??A & 'A | 'a) + +fun getOr(x: Option['a], d) = if x is + None then d + Some(g) then g +//│ fun getOr: forall 'a 'b. (x: Option['a], 'b) -> (??A & 'a | 'b) + +fun getOr[T](x: Option[T], d: T): T = if x is + None then d + Some(g) then g +//│ fun getOr: forall 'T. (x: Option['T], d: 'T) -> 'T + +fun get(x) = if x is Some(r) then r else error +//│ fun get: forall 'A. (Object & ~#Some | Some['A]) -> (??A & 'A) + +fun get(x: Option['a]): x.T = if x is Some(r) then r else error +//│ fun get: (x: Option[anything]) -> nothing + +None as Option[Int] +//│ Option[Int] +//│ res +//│ = None { class: [class None extends Option] } + +fun test(x, y) = + if x is Some(a) and y is Some(b) then eq(a)(b) + else if x is None and y is None then true + else false +//│ fun test: (Object & ~#Some | Some[anything], None | Object & ~#None & ~#Some | Some[anything]) -> Bool + +test(Some(1), Some(1)) +//│ Bool +//│ res +//│ = true + +test(Some(1), None) +//│ Bool +//│ res +//│ = false + + +fun test[T](x: Option[T], y: Option[T]): Bool = + if x is Some(a) and y is Some(b) then eq(a)(b) + else if x is None and y is None then true + else false +//│ fun test: (x: Option[anything], y: Option[anything]) -> Bool + +test(Some(None), Some(None)) +//│ Bool +//│ res +//│ = true + +test(Some(None), Some(1)) +//│ Bool +//│ res +//│ = false + diff --git a/shared/src/test/diff/gadt/GADT4.mls b/shared/src/test/diff/gadt/GADT4.mls new file mode 100644 index 0000000000..10b554dc6a --- /dev/null +++ b/shared/src/test/diff/gadt/GADT4.mls @@ -0,0 +1,169 @@ +:NewDefs + +fun fst([x, y]) = x +fun snd([x, y]) = y +fun (++) stringConcat(a, b) = concat(a)(b) +//│ fun fst: forall 'a. (['a, anything]) -> 'a +//│ fun snd: forall 'b. ([anything, 'b]) -> 'b +//│ fun (++) stringConcat: (Str, Str) -> Str + +// statically typed format // + +abstract class Format[type F]: D[?] | B[?] | L[F] | E +class D[F](fmt: Format[F]) extends Format[Int -> F] +class B[F](fmt: Format[F]) extends Format[Bool -> F] +class L[F](s: Str, fmt: Format[F]) extends Format[F] +module E extends Format[Str] +//│ abstract class Format[F]: B[?] | D[?] | E | L[F] +//│ class D[F](fmt: Format[F]) extends Format +//│ class B[F](fmt: Format[F]) extends Format +//│ class L[F](s: Str, fmt: Format[F]) extends Format +//│ module E extends Format + +fun fmtGo: (Str, Format['F]) -> 'F +fun fmtGo[F](acc: Str, f: Format[F]): F = if f is + D(fmt) then (i => fmtGo(acc ++ toString(i), fmt)) : f.F + B(fmt) then (i => fmtGo(acc ++ toString(i), fmt)) : f.F + L(s, fmt) then fmtGo(acc ++ s, fmt) : f.F + E then acc : f.F +//│ fun fmtGo: forall 'F. (acc: Str, f: Format['F]) -> 'F +//│ fun fmtGo: forall 'F0. (Str, Format['F0]) -> 'F0 + +fun fmt(f) = fmtGo("", f) +//│ fun fmt: forall 'F. Format['F] -> 'F + +let test = L("int i = ", D(L(", bool b = ", B(E)))) +//│ let test: L[Int -> Bool -> Str] +//│ test +//│ = L {} + +fmt(test) +//│ Int -> Bool -> Str +//│ res +//│ = [Function (anonymous)] + +fmt(test)(114)(false) +//│ Str +//│ res +//│ = 'int i = 114, bool b = false' + +:e +fmt(test)("hello")("world") +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.51: fmt(test)("hello")("world") +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── string literal of type `"hello"` is not an instance of type `Int` +//│ ║ l.51: fmt(test)("hello")("world") +//│ ║ ^^^^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.13: class D[F](fmt: Format[F]) extends Format[Int -> F] +//│ ╙── ^^^ +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.51: fmt(test)("hello")("world") +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── string literal of type `"world"` is not an instance of type `Bool` +//│ ║ l.51: fmt(test)("hello")("world") +//│ ║ ^^^^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.14: class B[F](fmt: Format[F]) extends Format[Bool -> F] +//│ ╙── ^^^^ +//│ Str | error +//│ res +//│ = 'int i = hello, bool b = world' + +fun fmt(f) = fmtGo("", f) +//│ fun fmt: forall 'F. Format['F] -> 'F + + +// typed ast // + +abstract class Expr[type T]: Lit | Plus| Equals | If[T] | Pair[?,?] | Fst[T,?] +// type Expr[type T] = Lit | Plus| Equals | If[?] | Pair[?,?] | Fst[?,?] +class Lit(i: Int) extends Expr[Int] +class Plus(a: Expr[Int], b: Expr[Int]) extends Expr[Int] +class Equals(a: Expr[Int], b: Expr[Int]) extends Expr[Bool] +class If[A](p: Expr[Bool],a: Expr[A],b: Expr[A]) extends Expr[A] +class Pair[A, B](a: Expr[A], b: Expr[B]) extends Expr[[A, B]] +class Fst[A, B](p: Expr[[A, B]]) extends Expr[A] +//│ abstract class Expr[T]: Equals | Fst[T, ?] | If[T] | Lit | Pair[?, ?] | Plus +//│ class Lit(i: Int) extends Expr +//│ class Plus(a: Expr[Int], b: Expr[Int]) extends Expr +//│ class Equals(a: Expr[Int], b: Expr[Int]) extends Expr +//│ class If[A](p: Expr[Bool], a: Expr[A], b: Expr[A]) extends Expr +//│ class Pair[A, B](a: Expr[A], b: Expr[B]) extends Expr +//│ class Fst[A, B](p: Expr[[A, B]]) extends Expr + +fun eval: Expr['T] -> 'T +fun eval[T](e: Expr[T]): T = if e is + Lit(i) then i : e.T + Plus(a, b) then eval(a) + eval(b) : e.T + Equals(a, b) then (eval(a) == eval(b)) : e.T + If(p, a, b) then if eval(p) then eval(a) : e.T else eval(b) : e.T + Pair(a, b) then [eval(a), eval(b)] : e.T + Fst(p) then fst(eval(p)) : e.T +//│ fun eval: forall 'T. (e: Expr['T]) -> 'T +//│ fun eval: forall 'T0. Expr['T0] -> 'T0 + +fun eval: Expr['T] -> 'T +fun eval[T](e: Expr[T]): e.T = if e is + Lit(i) then i + Plus(a, b) then eval(a) + eval(b) + Equals(a, b) then (eval(a) == eval(b)) + If(p, a, b) then if eval(p) then eval(a) else eval(b) + Pair(a, b) then [eval(a), eval(b)] + Fst(p) then fst(eval(p)) +//│ fun eval: forall 'T. (e: Expr['T]) -> (??A & 'T) +//│ fun eval: forall 'T0. Expr['T0] -> 'T0 + +eval(Plus(Lit(1), Lit(1))) +//│ Int +//│ res +//│ = 2 + +eval(If(Equals(Lit(3), Plus(Lit(1), Lit(1))), Fst(Pair(Lit(1), Lit(2))), Lit(3))) +//│ Int +//│ res +//│ = 3 + +:e +eval(Plus(Equals(Lit(1), Lit(2)), Lit(3))) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.129: eval(Plus(Equals(Lit(1), Lit(2)), Lit(3))) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Bool` is not an instance of type `Int` +//│ ║ l.84: class Equals(a: Expr[Int], b: Expr[Int]) extends Expr[Bool] +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.83: class Plus(a: Expr[Int], b: Expr[Int]) extends Expr[Int] +//│ ╙── ^^^ +//│ nothing +//│ res +//│ = 3 + +fun foo: Expr['T] -> 'T +fun foo[T](e: Expr[T]): T = if e is + Pair(a, b) then [foo(a), foo(b)] : e.T + else error +//│ fun foo: forall 'T. (e: Expr['T]) -> 'T +//│ fun foo: forall 'T0. Expr['T0] -> 'T0 + +:e +fun errval: Expr['T] -> 'T +fun errval[T](e: Expr[T]): T = if e is + Pair(a, b) then [errval(b), errval(a)] : e.T + else error +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.152: fun errval[T](e: Expr[T]): T = if e is +//│ ║ ^^^^ +//│ ║ l.153: Pair(a, b) then [errval(b), errval(a)] : e.T +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.154: else error +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── type `??A & ??B` does not match type `nothing` +//│ ║ l.151: fun errval: Expr['T] -> 'T +//│ ║ ^^ +//│ ╟── but it flows into application with expected type `nothing` +//│ ║ l.153: Pair(a, b) then [errval(b), errval(a)] : e.T +//│ ╙── ^^^^^^^^^ +//│ fun errval: forall 'T. (e: Expr['T]) -> 'T +//│ fun errval: forall 'T0. Expr['T0] -> 'T0 diff --git a/shared/src/test/diff/gadt/GADT5.mls b/shared/src/test/diff/gadt/GADT5.mls new file mode 100644 index 0000000000..c8e3922fc9 --- /dev/null +++ b/shared/src/test/diff/gadt/GADT5.mls @@ -0,0 +1,194 @@ +:NewDefs + +abstract class Option[out T]: None | Some[T] +module None extends Option[nothing] +class Some[A](get: A) extends Option[A] +//│ abstract class Option[T]: None | Some[T] +//│ module None extends Option +//│ class Some[A](get: A) extends Option + +abstract class U[type A]: MkU +module MkU extends U[()] +//│ abstract class U[A]: MkU +//│ module MkU extends U + +fun v1(u: U['a], a: ()) = if u is MkU then a +//│ fun v1: forall 'a. (u: U['a], a: ()) -> () + +fun v2(a, u: U['a]) = if u is MkU then if a is () then () +//│ fun v2: forall 'a. ((), u: U['a]) -> () + +fun v3[T](u: U[T]): T = if u is MkU then () as u.A +//│ fun v3: forall 'T. (u: U['T]) -> 'T + +abstract class F[type A, type B]: MkF[?, B] +class MkF[Z, Y](y: Y) extends F[Option[Z], Y] +//│ abstract class F[A, B]: MkF[?, B] +//│ class MkF[Z, Y](y: Y) extends F + +let t = MkF(true) +t : F[Option[nothing], Bool] +//│ let t: forall 'Z. MkF['Z, Bool] +//│ F[Option[nothing], Bool] +//│ t +//│ = MkF {} +//│ res +//│ = MkF {} + +let x: F[Option[nothing], Option[nothing]] = MkF(None) +//│ let x: F[Option[nothing], Option[nothing]] +//│ x +//│ = MkF {} + +:e +MkF(x) : F[Option[Int], Option[Int]] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.44: MkF(x) : F[Option[Int], Option[Int]] +//│ ║ ^^^^^^ +//│ ╟── type `MkF[?, ?B] & {B = Option[nothing], A = Option[nothing]}` is not an instance of type `Option` +//│ ║ l.38: let x: F[Option[nothing], Option[nothing]] = MkF(None) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── but it flows into reference with expected type `Option[anything]` +//│ ║ l.44: MkF(x) : F[Option[Int], Option[Int]] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.44: MkF(x) : F[Option[Int], Option[Int]] +//│ ║ ^^^^^^^^^^^ +//│ ╟── Note: type parameter B is defined at: +//│ ║ l.24: abstract class F[type A, type B]: MkF[?, B] +//│ ╙── ^ +//│ F[Option[Int], Option[Int]] +//│ res +//│ = MkF {} + +fun g: forall 'T: F['T, 'T] -> 'T +fun g[T](x: F[T, T]): T = if x is + MkF(m) then m : x.B +//│ fun g: forall 'T. (x: F['T, 'T]) -> 'T +//│ fun g: forall 'T0. F['T0, 'T0] -> 'T0 + +g(MkF(None)) +//│ None | Option[nothing] +//│ res +//│ = None { class: [class None extends Option] } + +g(MkF(Some(1))) +//│ Option['Z] | Some['Z] +//│ where +//│ 'Z :> 1 +//│ res +//│ = Some {} + +:e +g(MkF(1)) +g(t) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.83: g(MkF(1)) +//│ ║ ^^^^^^^^^ +//│ ╟── integer literal of type `1` is not an instance of type `Option` +//│ ║ l.83: g(MkF(1)) +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.25: class MkF[Z, Y](y: Y) extends F[Option[Z], Y] +//│ ║ ^^^^^^^^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.24: abstract class F[type A, type B]: MkF[?, B] +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.84: g(t) +//│ ║ ^^^^ +//│ ╟── type `None & {Option#T <: ?Z} | Some[?Z] & {Option#T <: ?Z}` does not match type `Bool` +//│ ║ l.25: class MkF[Z, Y](y: Y) extends F[Option[Z], Y] +//│ ║ ^^^^^^^^^ +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.64: fun g: forall 'T: F['T, 'T] -> 'T +//│ ║ ^^ +//│ ╟── from type variable: +//│ ║ l.64: fun g: forall 'T: F['T, 'T] -> 'T +//│ ╙── ^^ +//│ error +//│ res +//│ = 1 +//│ res +//│ = true + +fun g[T](x: MkF[T, Option[T]]): Option[T] = if x is + MkF(None) then None : x.B + else error +//│ fun g: forall 'T. (x: MkF['T, Option['T]]) -> Option['T] + +g(MkF(None)) +//│ Option[nothing] +//│ res +//│ = None { class: [class None extends Option] } + +fun g[T](x: F[Option[T], Option[T]]): Option[T] = if x is + MkF(None) then None : x.B + else error +//│ fun g: forall 'T. (x: F[Option['T], Option['T]]) -> Option['T] + +// * no refinement in nested patterns +:e // TODO +fun g[T](x: F[T, T]): T = if x is + MkF(Some(t)) then Some(t) : x.A + MkF(None) then None : x.A +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.132: fun g[T](x: F[T, T]): T = if x is +//│ ║ ^^^^ +//│ ║ l.133: MkF(Some(t)) then Some(t) : x.A +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.134: MkF(None) then None : x.A +//│ ║ ^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `T` does not match type `None | Some[?A] & {Some#A :> ?A0 <: ?A} | ~(T & ??Y)` +//│ ║ l.132: fun g[T](x: F[T, T]): T = if x is +//│ ║ ^ +//│ ╟── Note: constraint arises from application: +//│ ║ l.133: MkF(Some(t)) then Some(t) : x.A +//│ ║ ^^^^^^^ +//│ ╟── from field selection: +//│ ║ l.25: class MkF[Z, Y](y: Y) extends F[Option[Z], Y] +//│ ║ ^ +//│ ╟── Note: type parameter Y is defined at: +//│ ║ l.25: class MkF[Z, Y](y: Y) extends F[Option[Z], Y] +//│ ╙── ^ +//│ fun g: forall 'T. (x: F['T, 'T]) -> (error | 'T) + +fun g[T](x: F[T, T]): T = if x is + MkF(f) then if (f : x.A) is + Some(t) then Some(t) : x.A + None then None : x.A +//│ fun g: forall 'T. (x: F['T, 'T]) -> 'T + +fun g[T](x: F[T, T]): T = if x is + MkF(f) then if ((f : x.A) : Option['a]) is + Some(t) then Some(t) : x.A + None then None : x.A +//│ fun g: forall 'T. (x: F['T, 'T]) -> 'T + +g(MkF(None)) +g(MkF(Some(1))) +//│ Option['A] | Some['A] +//│ where +//│ 'A :> 1 +//│ res +//│ = None { class: [class None extends Option] } +//│ res +//│ = Some {} + +fun g[T](x: F[T, T]): T = if x is MkF(f) then f : x.A +//│ fun g: forall 'T. (x: F['T, 'T]) -> 'T + +fun g[T](x: F[T, T]): T = if x is MkF(f) then f : x.B +//│ fun g: forall 'T. (x: F['T, 'T]) -> 'T + + +abstract class Foo[type A, type B]: Bar +class Bar(val a: Option[Int]) extends Foo[Option[Int], Option[Int]] +//│ abstract class Foo[A, B]: Bar +//│ class Bar(a: Option[Int]) extends Foo + +fun foo[T](x: Foo[T, T]): T = if x is + Bar(Some(a)) then Some(a) as x.A + Bar(None) then None as x.A +//│ fun foo: forall 'T. (x: Foo['T, 'T]) -> 'T + diff --git a/shared/src/test/diff/gadt/GADT6.mls b/shared/src/test/diff/gadt/GADT6.mls new file mode 100644 index 0000000000..b1e2f95d17 --- /dev/null +++ b/shared/src/test/diff/gadt/GADT6.mls @@ -0,0 +1,151 @@ +:NewDefs + +abstract class R[type A]: RI | RB | RC +class RI(x: Int) extends R[Int] +class RB(x: Bool) extends R[Bool] +class RC(x: Str) extends R[Str] +//│ abstract class R[A]: RB | RC | RI +//│ class RI(x: Int) extends R +//│ class RB(x: Bool) extends R +//│ class RC(x: Str) extends R + +fun req[A](x: R[A], y: R[A]): Bool = if x is RI(a) and y is RI(b) then a == b else false +//│ fun req: forall 'A. (x: R['A], y: R['A]) -> Bool + +fun f1[A](e: R[A]) = [ if e is RI(i) then i as e.A else error , if e is RB(i) then i as e.A else error , if e is RC(i) then i as e.A else error ] +//│ fun f1: forall 'A. (e: R['A]) -> [Int & 'A | Str | false | true] + +fun h1[A](x: R[A], y: A) = (if x is + RI(_) then RI as (x.A => R[x.A]) + RB(_) then RB as (x.A => R[x.A]) + else error + ) (y as x.A) +//│ fun h1: forall 'A. (x: R['A], y: 'A) -> R[in Int & 'A0 | 'A | 'A1 & Bool out 'A & (Int & 'A1 | 'A0 & (Bool | 'A1))] + +h1(RI(1), 1) +//│ R[in Int & 'A | Int & 'A0 | 'A1 & Bool out Int & 'A1 | 'A & 'A0 & (Bool | 'A1)] +//│ res +//│ = RI {} + +:e +h1(RC("hi"), true) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.31: h1(RC("hi"), true) +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── reference of type `true` is not an instance of `Str` +//│ ║ l.31: h1(RC("hi"), true) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.6: class RC(x: Str) extends R[Str] +//│ ║ ^^^ +//│ ╟── Note: method type parameter A is defined at: +//│ ║ l.18: fun h1[A](x: R[A], y: A) = (if x is +//│ ╙── ^ +//│ R[in Int & 'A | Str & 'A0 | 'A1 & Bool out Int & 'A0 & 'A1 | 'A & (false & 'A0 | true | 'A1 & (Str | 'A0))] | error +//│ res +//│ Runtime error: +//│ Error: an error was thrown + +fun h2[A](x: R[A], y: R[A]) = (if x is + RI(_) then RI as (x.A => R[x.A]) + RB(_) then RB as (x.A => R[x.A]) + else error + ) (if y is + RI(a) then (a as y.A) as x.A + RB(a) then (a as y.A) as x.A + else error + ) +//│ fun h2: forall 'A. (x: R['A], y: R['A]) -> R[in Int & 'A0 | 'A | 'A1 & Bool out 'A & (Int & 'A1 | 'A0 & (Bool | 'A1))] + +h2(RI(1), RI(2)) +//│ R[in Int & 'A | Int & 'A0 | 'A1 & Bool out Int & 'A1 | 'A & 'A0 & (Bool | 'A1)] +//│ res +//│ = RI {} + +:e +h2(RB(true), RI(0)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.66: h2(RB(true), RI(0)) +//│ ║ ^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Int` is not an instance of type `Bool` +//│ ║ l.4: class RI(x: Int) extends R[Int] +//│ ║ ^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.5: class RB(x: Bool) extends R[Bool] +//│ ║ ^^^^ +//│ ╟── Note: method type parameter A is defined at: +//│ ║ l.49: fun h2[A](x: R[A], y: R[A]) = (if x is +//│ ╙── ^ +//│ error +//│ res +//│ = RB {} + +abstract class Eq[type A, type B]: Refl[A] +class Refl[A]() extends Eq[A, A] +//│ abstract class Eq[A, B]: Refl[A] +//│ class Refl[A]() extends Eq + +fun e1[A, B](e: Eq[A, B], x: A): B = if e is Refl() then (x as e.A) as e.B +//│ fun e1: forall 'A 'B. (e: Eq['A, 'B], x: 'A) -> 'B + +e1(Refl(), 1) +//│ 1 +//│ res +//│ = 1 + +:e +Refl() : Eq[Int, Bool] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.97: Refl() : Eq[Int, Bool] +//│ ║ ^^^^^^ +//│ ╙── expression of type `Int` does not match type `Bool` +//│ Eq[Int, Bool] +//│ res +//│ = Refl {} + +fun e2[A, B, C](e1: Eq[A, B], e2: Eq[B, C], x: A): C = + if e1 is Refl() and e2 is Refl() then + (((x as e1.A) as e1.B) as e2.A) as e2.B +//│ fun e2: forall 'A 'B 'C. (e1: Eq['A, 'B], e2: Eq['B, 'C], x: 'A) -> 'C + +e2(Refl(), Refl(), true) +//│ true +//│ res +//│ = true + + +abstract class R[type A]: RI | RB +class RI(x: Int) extends R[Int] +class RB(x: Bool) extends R[Bool] +//│ abstract class R[A]: RB | RI +//│ class RI(x: Int) extends R +//│ class RB(x: Bool) extends R + + + +fun u2[A](x: R[A], y: R[A]) = (if x is + RI(_) then RI as (x.A => R[x.A]) + RB(_) then RB as (x.A => R[x.A]) + ) (if y is + RI(a) then (a as y.A) as x.A + RB(a) then (a as y.A) as x.A + ) +//│ fun u2: forall 'A. (x: R['A], y: R['A]) -> R[in Int & 'A0 | 'A | 'A1 & Bool out 'A & (Int & 'A1 | 'A0 & (Bool | 'A1))] + +:e +u2(RB(false), RI(1)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.136: u2(RB(false), RI(1)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Int` is not an instance of type `Bool` +//│ ║ l.118: class RI(x: Int) extends R[Int] +//│ ║ ^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.119: class RB(x: Bool) extends R[Bool] +//│ ║ ^^^^ +//│ ╟── Note: method type parameter A is defined at: +//│ ║ l.126: fun u2[A](x: R[A], y: R[A]) = (if x is +//│ ╙── ^ +//│ error +//│ res +//│ = RB {} diff --git a/shared/src/test/diff/gadt/HOA.mls b/shared/src/test/diff/gadt/HOA.mls new file mode 100644 index 0000000000..56d7482bbc --- /dev/null +++ b/shared/src/test/diff/gadt/HOA.mls @@ -0,0 +1,88 @@ +:NewDefs + +abstract class HOA[type T]: Lit[T] | Abs[?,?] | App[?,T] +class Lit[A](x: A) extends HOA[A] +class Abs[A, B](f: A => HOA[B]) extends HOA[A => B] +class App[A, B](f: HOA[A => B], x: HOA[A]) extends HOA[B] +//│ abstract class HOA[T]: Abs[nothing, ?] | App[?, T] | Lit[T] +//│ class Lit[A](x: A) extends HOA +//│ class Abs[A, B](f: A -> HOA[B]) extends HOA +//│ class App[A, B](f: HOA[A -> B], x: HOA[A]) extends HOA + +fun eval: forall 'T : HOA['T] -> 'T +fun eval(e: HOA['T]): e.T = if e is + Lit(x) then x + Abs(f) then x => eval(f(x)) + App(f, x) then eval(f)(eval(x)) +//│ fun eval: forall 'T 'a. (e: HOA['T]) -> 'a +//│ fun eval: forall 'T0. HOA['T0] -> 'T0 +//│ where +//│ 'T <: 'a | ~(nothing -> ??B) + +eval(App(Abs(x => Lit(x + 1)), Lit(1))) +//│ Int +//│ res +//│ = 2 + +:e +eval(App(Abs(x => Lit(x + 1)), Lit(true))) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.28: eval(App(Abs(x => Lit(x + 1)), Lit(true))) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── reference of type `true` is not an instance of `Int` +//│ ║ l.28: eval(App(Abs(x => Lit(x + 1)), Lit(true))) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from reference: +//│ ║ l.28: eval(App(Abs(x => Lit(x + 1)), Lit(true))) +//│ ║ ^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.6: class App[A, B](f: HOA[A => B], x: HOA[A]) extends HOA[B] +//│ ╙── ^ +//│ Int +//│ res +//│ = 2 + +abstract class HList[type T]: HNil | HCons[?,?] +module HNil extends HList[[]] +class HCons[type A, type B](h: A, t: HList[B]) extends HList[[A, B]] +//│ abstract class HList[T]: HCons[anything, ?] | HNil +//│ module HNil extends HList +//│ class HCons[A, B](h: A, t: HList[B]) extends HList + +// FIXME +fun hhead : HList[['A, 'B]] -> 'A +fun hhead[A, B](xs: HList[[A, B]]): A = + if xs is HCons(h, t) then h : xs.A else error +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.55: if xs is HCons(h, t) then h : xs.A else error +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `anything` does not match type `A | ~??A` +//│ ║ l.55: if xs is HCons(h, t) then h : xs.A else error +//│ ║ ^^ +//│ ╟── Note: method type parameter A is defined at: +//│ ║ l.54: fun hhead[A, B](xs: HList[[A, B]]): A = +//│ ╙── ^ +//│ fun hhead: forall 'A 'B. (xs: HList[['A, 'B]]) -> 'A +//│ fun hhead: forall 'A0 'B0. HList[['A0, 'B0]] -> 'A0 + +// FIXME +fun htail : HList[['A, 'B]] -> HList['B] +fun htail[A, B](xs: HList[[A, B]]): HList[B] = + if xs is HCons(h, t) then t : HList[xs.B] else error +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.71: if xs is HCons(h, t) then t : HList[xs.B] else error +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `B` does not match type `nothing` +//│ ║ l.70: fun htail[A, B](xs: HList[[A, B]]): HList[B] = +//│ ║ ^ +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.71: if xs is HCons(h, t) then t : HList[xs.B] else error +//│ ╙── ^^ +//│ fun htail: forall 'A 'B. (xs: HList[['A, 'B]]) -> HList['B] +//│ fun htail: forall 'A0 'B0. HList[['A0, 'B0]] -> HList['B0] + +fun hlen : HList['A] -> Int +fun hlen(xs: HList['a]): Int = + if xs is HCons(h, t) then 1 + hlen(t) else 0 +//│ fun hlen: forall 'a. (xs: HList['a]) -> Int +//│ fun hlen: forall 'A. HList['A] -> Int diff --git a/shared/src/test/diff/gadt/Intensivity.mls b/shared/src/test/diff/gadt/Intensivity.mls new file mode 100644 index 0000000000..397767da6d --- /dev/null +++ b/shared/src/test/diff/gadt/Intensivity.mls @@ -0,0 +1,68 @@ +:NewDefs + +// * Notice that when doing pattern matching, +// * we can recover the type argument of the Bar case +// * even though it was left off in the self-signature clause: + + +abstract class Foo[type T]: Bar | Int +class Bar[S](val a: S) extends Foo[S] +//│ abstract class Foo[T]: Bar[anything] | Int +//│ class Bar[S](a: S) extends Foo + +fun foo(x: Foo['a]) = if x is + Bar then x.a : x.T +//│ fun foo: forall 'a 'b. (x: Foo['a]) -> 'b +//│ where +//│ 'a <: 'b | ~(??S & ??S0) + + +abstract class Foo[type T]: Bar +class Bar[type S](val a: S) extends Foo[S] +//│ abstract class Foo[T]: Bar[anything] +//│ class Bar[S](a: S) extends Foo + +fun foo(x: Foo['a]) = if x is + Bar then x.a : x.S +//│ fun foo: forall 'a. (x: Foo['a]) -> (??S & ??S0) + + +// * But this information is NOT accessible purely from the type level, +// * in that subtyping expands the raw self signatures and doesn't perform the local reasoning: + +:e +(error : Foo[Int]) : Bar['a] | Int +//│ ╔══[ERROR] Type error in type ascription +//│ ║ l.34: (error : Foo[Int]) : Bar['a] | Int +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `S` leaks out of its scope +//│ ║ l.34: (error : Foo[Int]) : Bar['a] | Int +//│ ║ ^^ +//│ ╟── back into type variable `S` +//│ ║ l.21: class Bar[type S](val a: S) extends Foo[S] +//│ ╙── ^ +//│ Bar['a] | Int +//│ where +//│ 'a :> ??S +//│ <: ??S0 +//│ res +//│ Runtime error: +//│ Error: an error was thrown + + + +// * Some other tests: + +abstract class Foo[T](val x: T): Bar +class Bar extends Foo[Int](42) +//│ abstract class Foo[T](x: T): Bar +//│ class Bar extends Foo { +//│ constructor() +//│ } + +fun foo(x: Foo[Int]) = if x is + Bar then x.x +//│ fun foo: (x: Foo[Int]) -> 42 + + + diff --git a/shared/src/test/diff/gadt/LocalSkolem.mls b/shared/src/test/diff/gadt/LocalSkolem.mls new file mode 100644 index 0000000000..3d267e1aab --- /dev/null +++ b/shared/src/test/diff/gadt/LocalSkolem.mls @@ -0,0 +1,270 @@ +:NewDefs + + + +abstract class Cls[A] { fun x: A; fun g: A -> Int } +//│ abstract class Cls[A] { +//│ fun g: A -> Int +//│ fun x: A +//│ } + +fun test(a) = if a is + Cls then a.x +//│ fun test: forall 'A. Cls[out 'A] -> (??A & 'A) + +fun test(a) = if a is + Cls then a.x + else error +//│ fun test: forall 'A. (Cls[out 'A] | Object & ~#Cls) -> (??A & 'A) + +fun test(a: Cls['a]) = if a is + Cls then a.x +//│ fun test: forall 'a. (a: Cls['a]) -> (??A & 'a) + +fun test(a: Object) = if a is + Cls then a.x + else error +//│ fun test: (a: Object) -> (??A & ??A0) + +module Impl extends Cls[Int] { + fun x = 42 + fun g(x) = x + 1 +} +//│ module Impl extends Cls { +//│ fun g: Int -> Int +//│ fun x: 42 +//│ } + +fun test(a: Object) = if a is + Cls then [a.g(a.x), a.x] // a.x : a.A ; a.g : a.A -> a.A + else [0, 1] +//│ fun test: (a: Object) -> [Int, ??A & ??A0] + +test(Impl) +//│ [Int, ??A & ??A0] +//│ res +//│ = [ 43, 42 ] + +fun test(a: Cls['a]) = if a is + Cls then [a.g(a.x), a.x] // a.x : a.A ; a.g : a.A -> a.A +//│ fun test: forall 'a. (a: Cls['a]) -> [Int, ??A & 'a] + +let r = test(Impl) +//│ let r: [Int, Int & ??A] +//│ r +//│ = [ 43, 42 ] + +r : [Int, Int] +//│ [Int, Int] +//│ res +//│ = [ 43, 42 ] + +module Impl extends Cls { + fun x = 42 + fun g(x) = x + 1 +} +//│ module Impl extends Cls { +//│ fun g: Int -> Int +//│ fun x: 42 +//│ } + +let r = test(Impl) +//│ let r: [Int, 42 & ??A] +//│ r +//│ = [ 43, 42 ] + +r : [Int, Int] +//│ [Int, Int] +//│ res +//│ = [ 43, 42 ] + + + +class Cls[A](val x: A) { fun g: A -> Int; fun g(x) = 42 } +//│ class Cls[A](x: A) { +//│ fun g: A -> Int +//│ } + +fun test(a) = if a is + Cls then a.x +//│ fun test: forall 'A. Cls[out 'A] -> (??A & 'A) + +fun test(a: Object) = if a is + Cls then a.x + else error +//│ fun test: (a: Object) -> (??A & ??A0) + +fun test(a: Object) = if a is + Cls then [a.g(a.x), a.x] // a.x : a.A ; a.g : a.A -> a.A + else [0, 1] +//│ fun test: (a: Object) -> [Int, ??A & ??A0] + +fun test(a: Cls['a]) = if a is + Cls then [a.g(a.x), a.x] // a.x : a.A ; a.g : a.A -> a.A +//│ fun test: forall 'a. (a: Cls['a]) -> [Int, ??A & 'a] + +let r = test(Cls(42)) +//│ let r: [Int, 42 & ??A] +//│ r +//│ = [ 42, 42 ] + +r : [Int, Int] +//│ [Int, Int] +//│ res +//│ = [ 42, 42 ] + + + +class Cls[out A] { fun x: A = x } +//│ class Cls[A] { +//│ constructor() +//│ fun x: A +//│ } + +fun test(a: Object) = if a is + Cls then a.x + else error +//│ fun test: (a: Object) -> (??A & ??A0) + +fun test(a: Object) = if a is + Cls then a + else error +//│ fun test: (a: Object) -> Cls[??A & ??A0] + +:re +test(0).x +//│ ??A & ??A0 +//│ res +//│ Runtime error: +//│ Error: an error was thrown + + + +abstract class Foo[A]: (Bar | Baz) { fun f: A -> A; fun f = id } +module Bar extends Foo[Int] +module Baz extends Foo[Str] +//│ abstract class Foo[A]: Bar | Baz { +//│ fun f: A -> A +//│ } +//│ module Bar extends Foo { +//│ fun f: 'A -> 'A +//│ } +//│ module Baz extends Foo { +//│ fun f: 'A0 -> 'A0 +//│ } +//│ where +//│ 'A0 := Str +//│ 'A := Int + + +fun test(f) = if f is + Bar then 123 + Baz then "hello" +//│ fun test: (Bar | Baz) -> ("hello" | 123) + +test : Foo['A] -> 'A +//│ Foo['A] -> 'A +//│ where +//│ 'A :> "hello" | 123 +//│ res +//│ = [Function: test12] + + +fun test[A](f: Foo[A]) = if f is + Bar then 123 + Baz then "hello" +//│ fun test: forall 'A. (f: Foo['A]) -> ("hello" | 123) + +:e // * Expected: we lost the locally-known fact that `foo`'s branches each returned an `A` +test : forall 'A: Foo['A] -> 'A +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.179: test : forall 'A: Foo['A] -> 'A +//│ ║ ^^^^ +//│ ╟── integer literal of type `123` does not match type `'A` +//│ ║ l.174: Bar then 123 +//│ ║ ^^^ +//│ ╟── Note: constraint arises from type variable: +//│ ║ l.179: test : forall 'A: Foo['A] -> 'A +//│ ╙── ^^ +//│ forall 'A. Foo['A] -> 'A +//│ res +//│ = [Function: test13] + + +// * TODO reject this confusing code: each 'A here is a distinct fresh var +fun test(f: Foo['A]) = if f is + Bar then 123 : 'A + Baz then "hello" : 'A +//│ fun test: forall 'A. (f: Foo['A]) -> ("hello" | 123) + +:e // * Expected +fun test[A](f: Foo[A]) = if f is // here `f : Bar & { Foo#A = A }` + Bar then 123 : A // here `f : Bar & { Foo#A = Int | A .. Int & A }` + Baz then "hello" : A +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.202: Bar then 123 : A // here `f : Bar & { Foo#A = Int | A .. Int & A }` +//│ ║ ^^^ +//│ ╟── integer literal of type `123` does not match type `A` +//│ ╟── Note: constraint arises from method type parameter: +//│ ║ l.201: fun test[A](f: Foo[A]) = if f is // here `f : Bar & { Foo#A = A }` +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.203: Baz then "hello" : A +//│ ║ ^^^^^^^ +//│ ╟── string literal of type `"hello"` does not match type `A` +//│ ╟── Note: constraint arises from method type parameter: +//│ ║ l.201: fun test[A](f: Foo[A]) = if f is // here `f : Bar & { Foo#A = A }` +//│ ╙── ^ +//│ fun test: forall 'A. (f: Foo['A]) -> 'A + +:e // * Expected +fun test[A](f: Foo[A]) = (if f is + Bar then 123 + Baz then "hello") : A +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.221: fun test[A](f: Foo[A]) = (if f is +//│ ║ ^^^^^^^^ +//│ ║ l.222: Bar then 123 +//│ ║ ^^^^^^^^^^^^^^ +//│ ║ l.223: Baz then "hello") : A +//│ ║ ^^^^^^^^^^^^^^^^^^^ +//│ ╟── integer literal of type `123` does not match type `A` +//│ ║ l.222: Bar then 123 +//│ ║ ^^^ +//│ ╟── Note: constraint arises from method type parameter: +//│ ║ l.221: fun test[A](f: Foo[A]) = (if f is +//│ ╙── ^ +//│ fun test: forall 'A. (f: Foo['A]) -> 'A + + + +fun test[A](f: Foo[A]) = if f is + Bar then f.f(123) + Baz then f.f("hello") +//│ fun test: forall 'A. (f: Foo['A]) -> (Int | Str) + +:e // * Expected +fun test[A](f: Foo[A]) = f.f(if f is + Bar then 123 + Baz then "hello") +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.247: fun test[A](f: Foo[A]) = f.f(if f is +//│ ║ ^^^^^^^^^^^ +//│ ║ l.248: Bar then 123 +//│ ║ ^^^^^^^^^^^^^^ +//│ ║ l.249: Baz then "hello") +//│ ║ ^^^^^^^^^^^^^^^^^^^ +//│ ╟── integer literal of type `123` is not an instance of type `Str` +//│ ║ l.248: Bar then 123 +//│ ║ ^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.145: module Baz extends Foo[Str] +//│ ║ ^^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.143: abstract class Foo[A]: (Bar | Baz) { fun f: A -> A; fun f = id } +//│ ╙── ^ +//│ fun test: forall 'A. (f: Foo['A]) -> (Int | Str | error) + + + + diff --git a/shared/src/test/diff/gadt/Misc.mls b/shared/src/test/diff/gadt/Misc.mls new file mode 100644 index 0000000000..33d1a9ded8 --- /dev/null +++ b/shared/src/test/diff/gadt/Misc.mls @@ -0,0 +1,373 @@ +:NewDefs + +class Ty[type T] +//│ class Ty[T] { +//│ constructor() +//│ } + +abstract class Foo[type A](val a: A): Bar | Baz +module Bar extends Foo[Int](1) +module Baz extends Foo[Bool](true) +//│ abstract class Foo[A](a: A): Bar | Baz +//│ module Bar extends Foo +//│ module Baz extends Foo + +fun foo(t)(x: Foo[t.T]): t.T = if x is + Bar then x.a + Baz then x.a +//│ fun foo: forall 'T 'T0. {T :> 1 | true | 'T <: 'T0} -> (x: Foo[in 'T out 'T0]) -> 'T0 + +foo(new Ty)(Bar) +//│ 1 | true +//│ res +//│ = 1 + +abstract class S[type T]: A | B +module A extends S[Int] +module B extends S[Bool] +//│ abstract class S[T]: A | B +//│ module A extends S +//│ module B extends S + +fun f(x: S['a]) = if x is + A then 1 : x.T + B then 2 : x.T +//│ fun f: forall 'a. (x: S['a]) -> ('a & (Int | false | true)) +//│ where +//│ 'a :> 2 + +f(A) +//│ Int +//│ res +//│ = 1 + +:e +f(B) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.45: f(B) +//│ ║ ^^^^ +//│ ╟── integer literal of type `2` is not an instance of type `Bool` +//│ ║ l.34: B then 2 : x.T +//│ ║ ^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.27: module B extends S[Bool] +//│ ║ ^^^^ +//│ ╟── Note: type parameter T is defined at: +//│ ║ l.25: abstract class S[type T]: A | B +//│ ╙── ^ +//│ 2 | error | false | true +//│ res +//│ = 2 + +:e +fun f(x: S): x.T = if x is A then 1 else 0 +//│ ╔══[ERROR] Type error in `case` expression +//│ ║ l.63: fun f(x: S): x.T = if x is A then 1 else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `T` leaks out of its scope +//│ ║ l.63: fun f(x: S): x.T = if x is A then 1 else 0 +//│ ╙── ^ +//│ fun f: (x: S[?]) -> anything + +fun f(x: S[?]) = if x is + A then 1 : x.T + B then true : x.T +//│ fun f: (x: S[?]) -> (Int | false | true) + +f(A) +//│ Int | false | true +//│ res +//│ = 1 + +fun f(x: S[?]): x.T = if x is + A then 1 : x.T + B then true : x.T +//│ fun f: (x: S[?]) -> (Int | false | true) + +f(A) +//│ Int | false | true +//│ res +//│ = 1 + +abstract class C[type S, type T]: R[S | T] | I[S] // TODO just a trick +class R[A] extends C[A, A] +class I[A](val f: A => Int) extends C[A, Int] +//│ abstract class C[S, T]: I[S] | R[S | T] +//│ class R[A] extends C { +//│ constructor() +//│ } +//│ class I[A](f: A -> Int) extends C + +fun foo[A, B](x: A, ev: C[A, B]): B = if ev is + R then (x : ev.S) : ev.T + I(f) then ev.f(x : ev.S) : ev.T +//│ fun foo: forall 'A 'B. (x: 'A, ev: C['A, 'B]) -> 'B + +foo(true, new R) +//│ true +//│ res +//│ = true + +foo(1, I(x => x + 1)) +//│ Int +//│ res +//│ = 2 + +module Foo { val a = 1 } +//│ module Foo { +//│ val a: 1 +//│ } + +Foo.a +//│ 1 +//│ res +//│ = 1 + +abstract class Option[type out T]: None | Some[T] +module None extends Option[nothing] +class Some[A](get: A) extends Option[A] +//│ abstract class Option[T]: None | Some[T] +//│ module None extends Option +//│ class Some[A](get: A) extends Option + +fun optToInt(w: Option[?]) = if w is Some then 1 else 0 +//│ fun optToInt: (w: Option[anything]) -> (0 | 1) + +optToInt(Some(11)) +//│ 0 | 1 +//│ res +//│ = 1 + +optToInt(Some(1) as Option[Int]) +//│ 0 | 1 +//│ res +//│ = 1 + +optToInt(None) +//│ 0 | 1 +//│ res +//│ = 0 + +optToInt(None as Option[nothing]) +//│ 0 | 1 +//│ res +//│ = 0 + +let x = Some(Some(1)) +let y = Some(None) +//│ let x: Some['A] +//│ let y: Some['A0] +//│ where +//│ 'A0 :> None +//│ 'A :> Some['A1] +//│ 'A1 :> 1 +//│ x +//│ = Some {} +//│ y +//│ = Some {} + +x : Option[Option[Int]] +//│ Option[Option[Int]] +//│ res +//│ = Some {} + +y : Option[Option[nothing]] +//│ Option[Option[nothing]] +//│ res +//│ = Some {} + +abstract class W[type T]: MkW[?] +class MkW[A](val w: A) extends W[Ty[A]] +//│ abstract class W[T]: MkW[anything] +//│ class MkW[A](w: A) extends W + +fun test(w: W[Ty[Int]]) = if w is MkW(x) then x +//│ fun test: (w: W[Ty[Int]]) -> ??A + +test(MkW(1)) +//│ ??A +//│ res +//│ = 1 + +fun test(w: W[?]) = if w is MkW(x) then x +//│ fun test: (w: W[?]) -> ??A + +test(MkW(1)) +//│ ??A +//│ res +//│ = 1 + +:e +fun test(a: Some[Int]) = true as a.T +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.201: fun test(a: Some[Int]) = true as a.T +//│ ║ ^^^^ +//│ ╟── reference of type `true` is not an instance of type `Int` +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.201: fun test(a: Some[Int]) = true as a.T +//│ ╙── ^^ +//│ fun test: (a: Some[Int]) -> Int + +fun test() = + let a = Some(1) + true as a.T +//│ fun test: () -> (1 | true) + +let x = Some(1) +//│ let x: Some['A] +//│ where +//│ 'A :> 1 +//│ x +//│ = Some {} + +true as x.T +//│ 1 | true +//│ res +//│ = true + +let x: Ty[Int] = new Ty +//│ let x: Ty[Int] +//│ x +//│ = Ty {} + +1 as x.T +//│ Int +//│ res +//│ = 1 + +:e +true as x.T +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.239: true as x.T +//│ ║ ^^^^ +//│ ╟── reference of type `true` is not an instance of type `Int` +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.239: true as x.T +//│ ╙── ^^ +//│ Int +//│ res +//│ = true + +let x: Some[Int] = Some(1) +//│ let x: Some[Int] +//│ x +//│ = Some {} + +1 as x.T +//│ Int +//│ res +//│ = 1 + +:e +true as x.T +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.262: true as x.T +//│ ║ ^^^^ +//│ ╟── reference of type `true` is not an instance of type `Int` +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.262: true as x.T +//│ ╙── ^^ +//│ Int +//│ res +//│ = true + +1 : (Some(1)).T +//│ 1 +//│ res +//│ = 1 + +abstract class U[type A, type B]: MkU[?] +class MkU[S](x: S) extends U[S, Int] +//│ abstract class U[A, B]: MkU[anything] +//│ class MkU[S](x: S) extends U + +fun uu[T](x: MkU[T]): T = if x is + MkU(s) then s : x.A +//│ fun uu: forall 'T. (x: MkU['T]) -> 'T + +uu(MkU(true)) +//│ true +//│ res +//│ = true + +fun u(x: U[?, ?]): x.A = if x is + MkU(s) then s : x.A +//│ fun u: (x: U[?, ?]) -> ??S + +u(MkU(1)) +//│ ??S +//│ res +//│ = 1 + +:e +fun w[T](x: U[T, T]): Bool = if x is + MkU(s) then (s : x.A) : x.B +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.304: MkU(s) then (s : x.A) : x.B +//│ ║ ^^^^^^^^^ +//│ ╟── type `T & ?B` is not an instance of type `Bool` +//│ ║ l.304: MkU(s) then (s : x.A) : x.B +//│ ║ ^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.303: fun w[T](x: U[T, T]): Bool = if x is +//│ ╙── ^^^^ +//│ fun w: forall 'T. (x: U['T, 'T]) -> Bool + +fun w[T](x: U[T, T]): Int = if x is + MkU(s) then (s : x.A) : x.B +//│ fun w: forall 'T. (x: U['T, 'T]) -> Int + +fun u[T](x: U[T, 'b]): T = if x is + MkU(s) then s : x.A +//│ fun u: forall 'T 'b. (x: U['T, 'b]) -> 'T + +u(MkU(1)) +//│ 1 +//│ res +//│ = 1 + +abstract class U[type A, type B]: MkU[A] +class MkU[S](x: S) extends U[S, Int] +//│ abstract class U[A, B]: MkU[A] +//│ class MkU[S](x: S) extends U + +fun u[T](x: U[T, 'b]): T = if x is + MkU(s) then s : x.A +//│ fun u: forall 'T 'b. (x: U['T, 'b]) -> 'T + +fun w[T](x: U[T, T]): Int = if x is + MkU(s) then (s : x.A) : x.B +//│ fun w: forall 'T. (x: U['T, 'T]) -> Int + +w(MkU(1)) +//│ Int +//│ res +//│ = 1 + +:e +w(MkU(true)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.348: w(MkU(true)) +//│ ║ ^^^^^^^^^^^^ +//│ ╟── reference of type `true` is not an instance of `Int` +//│ ║ l.348: w(MkU(true)) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.330: class MkU[S](x: S) extends U[S, Int] +//│ ║ ^^^ +//│ ╟── Note: type parameter B is defined at: +//│ ║ l.329: abstract class U[type A, type B]: MkU[A] +//│ ╙── ^ +//│ Int | error +//│ res +//│ = true + +abstract class U[type A, type B]: MkU +class MkU[S](x: S) extends U[S, Int] +//│ abstract class U[A, B]: MkU[anything] +//│ class MkU[S](x: S) extends U + +fun u[T](x: U[T, 'b]): T = if x is + MkU(s) then s : x.A +//│ fun u: forall 'T 'b. (x: U['T, 'b]) -> 'T + diff --git a/shared/src/test/diff/gadt/Nested.mls b/shared/src/test/diff/gadt/Nested.mls new file mode 100644 index 0000000000..b2d42bacb5 --- /dev/null +++ b/shared/src/test/diff/gadt/Nested.mls @@ -0,0 +1,245 @@ +:NewDefs + +abstract class Option[type out T]: None | Some[T] +class None extends Option[nothing] +class Some[A](val get: A) extends Option[A] +//│ abstract class Option[T]: None | Some[T] +//│ class None extends Option { +//│ constructor() +//│ } +//│ class Some[A](get: A) extends Option + +class Box[type A](val get: A) +//│ class Box[A](get: A) + +abstract class F[type A]: MkF[?] +class MkF[T](t: T) extends F[Box[T]] +//│ abstract class F[A]: MkF[anything] +//│ class MkF[T](t: T) extends F + +fun f[T](x: F[T]): T = if x is MkF(t) then Box(t) as x.A +//│ fun f: forall 'T. (x: F['T]) -> 'T + +abstract class H[type A]: HI | HB | HG[?] +module HI extends H[Option[Int]] +module HB extends H[Box[Bool]] +class HG[T](t: T) extends H[Option[Box[T]]] +//│ abstract class H[A]: HB | HG[anything] | HI +//│ module HI extends H +//│ module HB extends H +//│ class HG[T](t: T) extends H + +fun h[A](x: H[A]): A = if x is + HI then Some(1) as x.A + HB then Box(false) as x.A + HG(t) then Some(Box(t)) as x.A +//│ fun h: forall 'A. (x: H['A]) -> 'A + +h(HG(1)) +//│ Option[Box['T]] +//│ where +//│ 'T :> 1 +//│ res +//│ = Some {} + +abstract class F[type A, type B]: MkF[A] +class MkF[X](x: X) extends F[X, Some[Box[Int]]] +//│ abstract class F[A, B]: MkF[A] +//│ class MkF[X](x: X) extends F + +fun f[T](x: F[T, T]): Int = if x is + MkF(m) then ((m as x.A) as x.B).get.get +//│ fun f: forall 'T. (x: F['T, 'T]) -> Int + +f(MkF(Some(Box(1)))) +//│ Int +//│ res +//│ = 1 + +MkF(1) +//│ MkF['X] +//│ where +//│ 'X :> 1 +//│ res +//│ = MkF {} + +:e +MkF(1) : F['a, 'a] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.67: MkF(1) : F['a, 'a] +//│ ║ ^^^^^^ +//│ ╟── integer literal of type `1` is not an instance of type `Some` +//│ ║ l.67: MkF(1) : F['a, 'a] +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.46: class MkF[X](x: X) extends F[X, Some[Box[Int]]] +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── Note: type parameter B is defined at: +//│ ║ l.45: abstract class F[type A, type B]: MkF[A] +//│ ╙── ^ +//│ F[in Some[Box[Int]] out Some[Box[Int]] | 1, in Some[Box[Int]] out Some[Box[Int]] | 1] +//│ res +//│ = MkF {} + +abstract class F[type A, type B]: MkF[?] +class MkF[type X](x: X) extends F[Some[X], Some[Box[Int]]] +//│ abstract class F[A, B]: MkF[anything] +//│ class MkF[X](x: X) extends F + +fun f[R](x: F['t, R]): R = if x is + MkF(m) then Some(Box(1)) : x.B +//│ fun f: forall 't 'R. (x: F['t, 'R]) -> 'R + +:e +fun f[R](x: F['t, R]): R = if x is + MkF(m) then Some(Box(false)) : x.B +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.95: MkF(m) then Some(Box(false)) : x.B +//│ ║ ^^^^^^^^^^^^^^^^ +//│ ╟── reference of type `false` is not an instance of type `Int` +//│ ║ l.95: MkF(m) then Some(Box(false)) : x.B +//│ ╙── ^^^^^ +//│ fun f: forall 't 'R. (x: F['t, 'R]) -> 'R + +fun g[T](x: F[T, T], y: F[T, T]): Int = if x is MkF(n) and y is MkF(m) then + ((Some(n) as x.A) as x.B).get.get + ((Some(m) as y.A) as y.B).get.get +//│ fun g: forall 'T. (x: F['T, 'T], y: F['T, 'T]) -> Int + +fun f[T](x: F[T, T]): Int = if x is + MkF(m) then ((Some(m) as x.A) as x.B).get.get +//│ fun f: forall 'T. (x: F['T, 'T]) -> Int + +f(MkF(Box(1))) +//│ Int +//│ res +//│ = 1 + +:e +f(MkF(1)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.118: f(MkF(1)) +//│ ║ ^^^^^^^^^ +//│ ╟── integer literal of type `1` is not an instance of type `Box` +//│ ║ l.118: f(MkF(1)) +//│ ║ ^ +//│ ╟── Note: constraint arises from applied type reference: +//│ ║ l.85: class MkF[type X](x: X) extends F[Some[X], Some[Box[Int]]] +//│ ╙── ^^^^^^^^ +//│ Int | error +//│ res +//│ = undefined + +abstract class U[type A, type B, type C]: MkU[A, B] +class MkU[S, T](s: S, t: T) extends U[S, T, Int] +//│ abstract class U[A, B, C]: MkU[A, B] +//│ class MkU[S, T](s: S, t: T) extends U + +fun u[A](x: U[A, A, A]): A = if x is + MkU(s, t) then (((s as x.A) as x.C) + ((t as x.B) as x.C)) as x.C +//│ fun u: forall 'A. (x: U['A, 'A, 'A]) -> 'A + +u(MkU(1, 2)) +//│ Int +//│ res +//│ = 3 + +:e +u(MkU(1, true)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.147: u(MkU(1, true)) +//│ ║ ^^^^^^^^^^^^^^^ +//│ ╟── reference of type `true` is not an instance of `Int` +//│ ║ l.147: u(MkU(1, true)) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.133: class MkU[S, T](s: S, t: T) extends U[S, T, Int] +//│ ║ ^^^ +//│ ╟── Note: type parameter C is defined at: +//│ ║ l.132: abstract class U[type A, type B, type C]: MkU[A, B] +//│ ╙── ^ +//│ Int | error | true +//│ res +//│ = 2 + +:e +fun u2[A, B](x: U[A, B, A]): A = if x is + MkU(s, t) then (((s as x.A) as x.C) + ((t as x.B) as x.C)) as x.C +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.165: fun u2[A, B](x: U[A, B, A]): A = if x is +//│ ║ ^^^^ +//│ ║ l.166: MkU(s, t) then (((s as x.A) as x.C) + ((t as x.B) as x.C)) as x.C +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── type `B` does not match type `Int | A | ~(B & ??T)` +//│ ║ l.165: fun u2[A, B](x: U[A, B, A]): A = if x is +//│ ║ ^ +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.166: MkU(s, t) then (((s as x.A) as x.C) + ((t as x.B) as x.C)) as x.C +//│ ║ ^^ +//│ ╟── from type selection: +//│ ║ l.166: MkU(s, t) then (((s as x.A) as x.C) + ((t as x.B) as x.C)) as x.C +//│ ║ ^^ +//│ ╟── Note: type parameter T is defined at: +//│ ║ l.133: class MkU[S, T](s: S, t: T) extends U[S, T, Int] +//│ ╙── ^ +//│ fun u2: forall 'A 'B. (x: U['A, 'B, 'A]) -> (error | 'A) + +u2(MkU(1, false)) +//│ Int | error +//│ res +//│ = 1 + +fun eu[A, B](x: U[A,B,A], y: U[A,B,A]): Bool = + if x is MkU(s1, t1) and y is MkU(s2, t2) then + ((s1 as x.A) as x.C) == ((s2 as y.A) as y.C) + else false +//│ fun eu: forall 'A 'B. (x: U['A, 'B, 'A], y: U['A, 'B, 'A]) -> Bool + +eu(MkU(1, 2), MkU(1, 3)) +//│ Bool +//│ res +//│ = true + +eu(MkU(1, true), MkU(2, false)) +//│ Bool +//│ res +//│ = false + +eu(MkU(1, 2), MkU(1, "ha")) +//│ Bool +//│ res +//│ = true + +fun su[A, B](x: U[A,B,A], y: U[B,A,B]): Int = + if x is MkU(s1, t1) and y is MkU(s2, t2) then + (t1 as y.A) as y.C + else 0 +//│ fun su: forall 'A 'B. (x: U['A, 'B, 'A], y: U['B, 'A, 'B]) -> Int + +fun su[A, B](x: U[A,B,A], y: U[B,A,B]): Int = + if x is MkU(s1, t1) and y is MkU(s2, t2) then + ((s1 as x.A) as x.C) + ((t1 as y.A) as y.C) + ((s2 as y.A) as y.C) + ((t2 as x.A) as x.C) + else 0 +//│ fun su: forall 'A 'B. (x: U['A, 'B, 'A], y: U['B, 'A, 'B]) -> Int + +su(MkU(1,2), MkU(3,4)) +//│ Int +//│ res +//│ = 10 + +:e +su(MkU(1,true), MkU(3,4)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.230: su(MkU(1,true), MkU(3,4)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── reference of type `true` is not an instance of `Int` +//│ ║ l.230: su(MkU(1,true), MkU(3,4)) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.133: class MkU[S, T](s: S, t: T) extends U[S, T, Int] +//│ ║ ^^^ +//│ ╟── Note: type parameter C is defined at: +//│ ║ l.132: abstract class U[type A, type B, type C]: MkU[A, B] +//│ ╙── ^ +//│ Int | error +//│ res +//│ = 9 diff --git a/shared/src/test/diff/gadt/ThisMatching.mls b/shared/src/test/diff/gadt/ThisMatching.mls index a279d6abd5..743eaf6da4 100644 --- a/shared/src/test/diff/gadt/ThisMatching.mls +++ b/shared/src/test/diff/gadt/ThisMatching.mls @@ -165,11 +165,14 @@ class Pair(lhs: Exp, rhs: Exp) extends Exp //│ ╔══[ERROR] Indirectly-recursive member should have a type signature //│ ║ l.150: Pair(l, r) then l.test + r.test //│ ╙── ^^^^^ +//│ ╔══[ERROR] Indirectly-recursive member should have a type signature +//│ ║ l.150: Pair(l, r) then l.test + r.test +//│ ╙── ^^^^^ //│ abstract class Exp: Lit | Pair { -//│ fun test: Int | error +//│ fun test: Int //│ } //│ class Lit(n: Int) extends Exp { -//│ fun test: Int | error +//│ fun test: Int //│ } //│ class Pair(lhs: Exp, rhs: Exp) extends Exp @@ -184,17 +187,17 @@ abstract class Exp: (Pair | Lit) { class Lit(n: Int) extends Exp class Pair(lhs: Exp, rhs: Exp) extends Exp //│ ╔══[ERROR] Unhandled cyclic definition -//│ ║ l.178: abstract class Exp: (Pair | Lit) { +//│ ║ l.181: abstract class Exp: (Pair | Lit) { //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.179: fun test : Int +//│ ║ l.182: fun test : Int //│ ║ ^^^^^^^^^^^^^^^^ -//│ ║ l.180: fun test = if this is +//│ ║ l.183: fun test = if this is //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.181: Lit then 0 +//│ ║ l.184: Lit then 0 //│ ║ ^^^^^^^^^^^^^^ -//│ ║ l.182: Pair(l, r) then l.test + r.test +//│ ║ l.185: Pair(l, r) then l.test + r.test //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.183: } +//│ ║ l.186: } //│ ╙── ^ //│ abstract class Exp: Lit | Pair { //│ fun test: Int @@ -214,26 +217,16 @@ abstract class Exp[A]: (Pair | Lit) { class Lit(n: Int) extends Exp[Int] class Pair[L, R](lhs: L, rhs: R) extends Exp[[L, R]] //│ ╔══[ERROR] Unhandled cyclic definition -//│ ║ l.209: abstract class Exp[A]: (Pair | Lit) { +//│ ║ l.212: abstract class Exp[A]: (Pair | Lit) { //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.210: fun test = if this is +//│ ║ l.213: fun test = if this is //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.211: Lit then 0 +//│ ║ l.214: Lit then 0 //│ ║ ^^^^^^^^^^^^^^ -//│ ║ l.212: Pair then 1 +//│ ║ l.215: Pair then 1 //│ ║ ^^^^^^^^^^^^^^^ -//│ ║ l.213: } +//│ ║ l.216: } //│ ╙── ^ -//│ ╔══[ERROR] Type error in `case` expression -//│ ║ l.210: fun test = if this is -//│ ║ ^^^^^^^ -//│ ║ l.211: Lit then 0 -//│ ║ ^^^^^^^^^^^^^^ -//│ ║ l.212: Pair then 1 -//│ ║ ^^^^^^^^^^^^^^^ -//│ ╟── type variable `L` leaks out of its scope -//│ ║ l.215: class Pair[L, R](lhs: L, rhs: R) extends Exp[[L, R]] -//│ ╙── ^ //│ abstract class Exp[A]: Lit | Pair[anything, anything] { //│ fun test: 0 | 1 //│ } diff --git a/shared/src/test/diff/gadt/Wildcard.mls b/shared/src/test/diff/gadt/Wildcard.mls new file mode 100644 index 0000000000..64978f18b7 --- /dev/null +++ b/shared/src/test/diff/gadt/Wildcard.mls @@ -0,0 +1,543 @@ +:NewDefs + +class Foo[type T](val x: T) +//│ class Foo[T](x: T) + +fun foo(f: Foo[?]) = f +//│ fun foo: (f: Foo[anything]) -> Foo[anything] + +foo(Foo(0)) +//│ Foo[anything] +//│ res +//│ = Foo {} + +fun foo(f: Foo[?]) = 0 +//│ fun foo: (f: Foo[anything]) -> 0 + +let f: Foo[?] = Foo(1) +//│ let f: Foo[anything] +//│ f +//│ = Foo {} + +foo(f) +foo(Foo(1)) +//│ 0 +//│ res +//│ = 0 +//│ res +//│ = 0 + +fun y: Foo[Foo[Int]] +//│ fun y: Foo[Foo[Int]] + +// * Foo is invariant so this doesn't work +:e +let f: Foo[Foo[?]] = y +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.35: let f: Foo[Foo[?]] = y +//│ ║ ^ +//│ ╙── expression of type `Int` does not match type `nothing` +//│ let f: Foo[Foo[anything]] +//│ f +//│ = +//│ y is not implemented + + +fun foo(f: Foo[?]) = f.x +//│ fun foo: (f: Foo[anything]) -> anything + +foo(Foo(Foo(1))) +foo(Foo(1)) +//│ anything +//│ res +//│ = Foo {} +//│ res +//│ = 1 + +:e // * To allow this, we'd need to either introduce more levels even outside pattern matching branches + // * or support proper path-dependent types internally. +fun foo(f: Foo[?]) = f.x as f.T +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.59: fun foo(f: Foo[?]) = f.x as f.T +//│ ║ ^^^ +//│ ╟── field selection of type `anything` does not match type `nothing` +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.59: fun foo(f: Foo[?]) = f.x as f.T +//│ ╙── ^^ +//│ fun foo: (f: Foo[anything]) -> anything + +fun foo(f: Foo[?]) = if f is Foo(x) then x as f.T +//│ fun foo: (f: Foo[anything]) -> ??T + +foo(Foo(1)) +//│ ??T +//│ res +//│ = 1 + +class Foo[out T](val x: T) +//│ class Foo[T](x: T) + +let f: Foo[?] = Foo(1) +//│ let f: Foo[anything] +//│ f +//│ = Foo {} + +let f: Foo[Foo[?]] = Foo(Foo(1)) +//│ let f: Foo[Foo[anything]] +//│ f +//│ = Foo {} + +class Foo[in T](val x: T) +//│ class Foo[T](x: T) + +let f: Foo[?] = Foo(1) +//│ let f: Foo[nothing] +//│ f +//│ = Foo {} + +let y: Foo[Foo[Int]] = Foo(Foo(0)) +//│ let y: Foo[Foo[Int]] +//│ y +//│ = Foo {} + +// * Correct error: Foo[Int] <: Foo[?] so Foo[Foo[?]] <: Foo[Foo[Int]] and not the other way around +:e +let f: Foo[Foo[?]] = y +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.105: let f: Foo[Foo[?]] = y +//│ ║ ^ +//│ ╟── type `anything` is not an instance of type `Int` +//│ ║ l.105: let f: Foo[Foo[?]] = y +//│ ║ ^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.98: let y: Foo[Foo[Int]] = Foo(Foo(0)) +//│ ╙── ^^^ +//│ let f: Foo[Foo[nothing]] +//│ f +//│ = Foo {} + +(x: Foo[Foo[?]]) => x as Foo[Foo[Int]] +//│ (x: Foo[Foo[nothing]]) -> Foo[Foo[Int]] +//│ res +//│ = [Function: res] + +abstract class Bar[type A]: MkBarInt | MkBarBool | MkBarFoo[?] +class MkBarInt() extends Bar[Int] +class MkBarBool() extends Bar[Bool] +class MkBarFoo[A](ev: A) extends Bar[Foo[A]] +//│ abstract class Bar[A]: MkBarBool | MkBarFoo[anything] | MkBarInt +//│ class MkBarInt() extends Bar +//│ class MkBarBool() extends Bar +//│ class MkBarFoo[A](ev: A) extends Bar + +fun bar(b: Bar[?]) = if b is + MkBarInt then 1 + MkBarBool then 2 + MkBarFoo then 3 +//│ fun bar: (b: Bar[?]) -> (1 | 2 | 3) + +bar(MkBarInt()) +bar(MkBarBool() as Bar[?]) +bar(MkBarFoo("hello")) +bar(MkBarFoo(Foo(1))) +//│ 1 | 2 | 3 +//│ res +//│ = 1 +//│ res +//│ = 2 +//│ res +//│ = 3 +//│ res +//│ = 3 + +let x: Bar[?] = MkBarInt() +//│ let x: Bar[?] +//│ x +//│ = MkBarInt {} + +:e +x as Bar[Bool] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.159: x as Bar[Bool] +//│ ║ ^ +//│ ╟── type `Bool` does not match type `nothing` +//│ ║ l.159: x as Bar[Bool] +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from wildcard: +//│ ║ l.153: let x: Bar[?] = MkBarInt() +//│ ╙── ^ +//│ Bar[Bool] +//│ res +//│ = MkBarInt {} + +MkBarFoo(Foo(1)) as Bar[Foo[Foo[Int]]] +//│ Bar[Foo[Foo[Int]]] +//│ res +//│ = MkBarFoo {} + +MkBarFoo(Foo(1)) as Bar[?] +//│ Bar[?] +//│ res +//│ = MkBarFoo {} + +MkBarFoo(Foo(1)) as Bar[Foo[?]] +//│ Bar[Foo[nothing]] +//│ res +//│ = MkBarFoo {} + +let x: Bar[Foo[?]] = MkBarFoo(1) +//│ let x: Bar[Foo[nothing]] +//│ x +//│ = MkBarFoo {} + +let x: Bar[Foo[?]] = MkBarFoo(1) +//│ let x: Bar[Foo[nothing]] +//│ x +//│ = MkBarFoo {} + +:e +x as Bar[Foo[Int]] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.199: x as Bar[Foo[Int]] +//│ ║ ^ +//│ ╟── type `anything` is not an instance of type `Int` +//│ ║ l.193: let x: Bar[Foo[?]] = MkBarFoo(1) +//│ ║ ^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.199: x as Bar[Foo[Int]] +//│ ╙── ^^^ +//│ Bar[Foo[Int]] +//│ res +//│ = MkBarFoo {} + +abstract class C[type A]: MkC +class MkC() extends C[Int] +//│ abstract class C[A]: MkC +//│ class MkC() extends C + +fun fc(c: C[?]) = if c is MkC then 1 as c.A +//│ fun fc: (c: C[?]) -> Int + +fc(MkC()) +//│ Int +//│ res +//│ = 1 + +abstract class Baz[type A]: BI | BB +class BI() extends Baz[Int] +class BB() extends Baz[Bool] +//│ abstract class Baz[A]: BB | BI +//│ class BI() extends Baz +//│ class BB() extends Baz + +fun baz[T](b: Baz[T]): T = if b is + BI then 1 as b.A + BB then true as b.A +//│ fun baz: forall 'T. (b: Baz['T]) -> 'T + +fun baz(b: Baz['a]): b.A = if b is + BI then 1 as b.A + BB then true as b.A +//│ fun baz: forall 'a. (b: Baz['a]) -> ('a & (Int | false | true)) + +fun baz(b: Baz[?]) = if b is + BI then 1 as b.A + BB then true as b.A +//│ fun baz: (b: Baz[?]) -> (Int | false | true) + +// * Note: this didn't work before we pushed ascriptions in, +// * as we don't yet have proper path-dependent type forms like b.A, which is basically ? here. +fun baz(b: Baz[?]): b.A = if b is + BI then 1 as b.A + BB then true as b.A +//│ fun baz: (b: Baz[?]) -> (Int | false | true) + +class Foo[T](val x: T) +//│ class Foo[T](x: T) + +fun e: Foo[?] +fun f: Foo[?] -> Foo[?] +//│ fun e: Foo[anything] +//│ fun f: Foo[anything] -> Foo[anything] + +f(e) +//│ Foo[anything] +//│ res +//│ = +//│ f is not implemented + +fun e: Foo[Int] +fun f: Foo[?] -> Foo[?] +//│ fun e: Foo[Int] +//│ fun f: Foo[anything] -> Foo[anything] + +f(e) +//│ Foo[anything] +//│ res +//│ = +//│ f is not implemented + +fun e: Foo[?] +fun f: Foo[Int] -> Foo[?] +//│ fun e: Foo[anything] +//│ fun f: Foo[Int] -> Foo[anything] + +:e +e as Foo[Int] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.286: e as Foo[Int] +//│ ║ ^ +//│ ╙── expression of type `anything` is not an instance of type `Int` +//│ Foo[Int] +//│ res +//│ = +//│ e is not implemented + +:e +f(e) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.297: f(e) +//│ ║ ^^^^ +//│ ╙── expression of type `anything` is not an instance of type `Int` +//│ Foo[anything] | error +//│ res +//│ = +//│ f is not implemented + +class Foo[T](val x: T => T) +//│ class Foo[T](x: T -> T) + +fun e: Foo[?] +fun f: Foo[?] -> Foo[?] +//│ fun e: Foo[?] +//│ fun f: Foo[?] -> Foo[?] + +:e +fun f(x: ?) = x +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.316: fun f(x: ?) = x +//│ ╙── ^ +//│ fun f: (x: error) -> error + +:e +fun f(x): ? = x +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.323: fun f(x): ? = x +//│ ╙── ^ +//│ fun f: error -> error + +:e +fun f(x: Int): ? = x +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.330: fun f(x: Int): ? = x +//│ ╙── ^ +//│ fun f: (x: Int) -> error + +:e +fun f(x: ?): ? = x +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.337: fun f(x: ?): ? = x +//│ ╙── ^ +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.337: fun f(x: ?): ? = x +//│ ╙── ^ +//│ fun f: (x: error) -> error + +:e +let x: ? = 1 +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.347: let x: ? = 1 +//│ ╙── ^ +//│ let x: error +//│ x +//│ = 1 + +:e +1 as ? +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.356: 1 as ? +//│ ╙── ^ +//│ error +//│ res +//│ = 1 + +:e +fun f: (? -> ?) -> ? +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.365: fun f: (? -> ?) -> ? +//│ ╙── ^ +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.365: fun f: (? -> ?) -> ? +//│ ╙── ^ +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.365: fun f: (? -> ?) -> ? +//│ ╙── ^ +//│ fun f: (error -> error) -> error + +:e +fun f: ? -> ? +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.378: fun f: ? -> ? +//│ ╙── ^ +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.378: fun f: ? -> ? +//│ ╙── ^ +//│ fun f: error -> error + +:e +fun f: ? -> Int +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.388: fun f: ? -> Int +//│ ╙── ^ +//│ fun f: error -> Int + +:e +fun f: Int -> ? +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.395: fun f: Int -> ? +//│ ╙── ^ +//│ fun f: Int -> error + +:e +let x: ? -> ? +//│ ╔══[ERROR] `let` bindings must have a right-hand side +//│ ║ l.402: let x: ? -> ? +//│ ╙── ^^^^^^^^^^^^^ +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.402: let x: ? -> ? +//│ ╙── ^ +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.402: let x: ? -> ? +//│ ╙── ^ +//│ let x: error -> error +//│ x +//│ = + +:e +let x = ? +//│ ╔══[ERROR] Cannot use ? as expression +//│ ║ l.417: let x = ? +//│ ╙── ^ +//│ let x: error +//│ Code generation encountered an error: +//│ unresolved symbol ? + +:e +if ? is 1 then 1 +//│ ╔══[ERROR] Cannot use ? as expression +//│ ║ l.426: if ? is 1 then 1 +//│ ╙── ^ +//│ 1 +//│ Code generation encountered an error: +//│ unresolved symbol ? + +:e +if x is ? then 1 +//│ ╔══[ERROR] Cannot match on wildcard ? +//│ ║ l.435: if x is ? then 1 +//│ ╙── ^ +//│ error +//│ Code generation encountered an error: +//│ if expression was not desugared + +:e +let x: ?[?] +//│ ╔══[ERROR] `let` bindings must have a right-hand side +//│ ║ l.444: let x: ?[?] +//│ ╙── ^^^^^^^^^^^ +//│ ╔══[ERROR] type identifier not found: ? +//│ ║ l.444: let x: ?[?] +//│ ╙── ^^^^ +//│ let x: error +//│ x +//│ = + +:e +class Bar extends ? +//│ ╔══[ERROR] Could not find definition `?` +//│ ║ l.456: class Bar extends ? +//│ ╙── ^ +//│ class Bar { +//│ constructor() +//│ } +//│ Code generation encountered an error: +//│ unresolved parent ?. + +:e +abstract class Bar: ? +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.467: abstract class Bar: ? +//│ ╙── ^ +//│ abstract class Bar: error + +:e +class ? +//│ ╔══[ERROR] Type name '?' is reserved +//│ ║ l.474: class ? +//│ ╙── ^^^^^^^ +//│ class ? { +//│ constructor() +//│ } +//│ Syntax error: +//│ Invalid or unexpected token + +:e +type ? = Int +//│ ╔══[ERROR] Type name '?' is reserved +//│ ║ l.485: type ? = Int +//│ ╙── ^^^^^^ +//│ type ? = Int + +:e +type W = ? +//│ ╔══[ERROR] Invalid use of wildcard type `?` here +//│ ║ l.492: type W = ? +//│ ╙── ^ +//│ type W = error + +// TODO reject +fun (?) wc: (Int, Int) -> Bool +fun (?) wc(x, y) = x == y +//│ fun (?) wc: (Num, Num) -> Bool +//│ fun (?) wc: (Int, Int) -> Bool + +:e +1 ? 1 +//│ ╔══[ERROR] Cannot use ? as expression +//│ ║ l.505: 1 ? 1 +//│ ╙── ^ +//│ error +//│ res +//│ = true + +class Foo[T](val a: T) +let f: Foo[?] = Foo(1) +//│ class Foo[T](a: T) +//│ let f: Foo[anything] +//│ f +//│ = Foo {} + +:e +f.a : Int +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.521: f.a : Int +//│ ║ ^^^ +//│ ╟── field selection of type `anything` is not an instance of type `Int` +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.521: f.a : Int +//│ ╙── ^^^ +//│ Int +//│ res +//│ = 1 + +// * FIXME strange error! +:e +42 : f.a +//│ ╔══[ERROR] Type mismatch in type selection: +//│ ║ l.535: 42 : f.a +//│ ║ ^^ +//│ ╙── type `anything` cannot be reassigned +//│ anything +//│ res +//│ = 42 + diff --git a/shared/src/test/diff/mlf-examples/ex_demo.mls b/shared/src/test/diff/mlf-examples/ex_demo.mls index cef2977fe3..2b1977a2da 100644 --- a/shared/src/test/diff/mlf-examples/ex_demo.mls +++ b/shared/src/test/diff/mlf-examples/ex_demo.mls @@ -1073,24 +1073,24 @@ rec def c_fact_ n = (fun _ -> c_mul_ n (c_fact_ (c_pred_ n))) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: (forall 'b. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> ? -> 'd) -> ((forall 'e. ? -> ? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> ? -> 'g) -> (forall 'h 'i. ? -> ('h -> 'i) -> 'h -> 'i) -> (? -> 'j) -> 'k & (forall 'l. ((forall 'm 'n 'o 'p. ('m -> 'n -> 'o) -> ('p -> 'n & 'm) -> 'p -> 'o) -> 'k -> 'l) -> 'l) -> (forall 'c. ? -> 'c -> 'c) -> 'j & (forall 'q 'r 's 't 'u 'v. ((forall 'w. ? -> 'w -> 'w) -> ('q -> 'r -> 's & 't)) -> ('t -> (('u -> 'r & 'q) -> 'u -> 's) -> 'v) -> 'v) -> 'a) +//│ 'a <: (forall 'b. ((forall 'c. #? -> 'c -> 'c) -> (forall 'c. #? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> #? -> 'd) -> ((forall 'e. #? -> #? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> #? -> 'g) -> (forall 'h 'i. #? -> ('h -> 'i) -> 'h -> 'i) -> (#? -> 'j) -> 'k & (((forall 'l 'm 'n 'o. ('l -> 'm -> 'n) -> ('o -> 'm & 'l) -> 'o -> 'n) -> 'k -> 'p) -> 'p) -> (forall 'c. #? -> 'c -> 'c) -> 'j & (forall 'q 'r 's 't 'u 'v. ((forall 'w. #? -> 'w -> 'w) -> ('q -> 'r -> 's & 't)) -> ('t -> (('u -> 'r & 'q) -> 'u -> 's) -> 'v) -> 'v) -> 'a) //│ ║ l.963: c_1_2_ (n s z) //│ ╙── ^^^ //│ c_fact_: 'a -> 'b //│ where -//│ 'a <: (forall 'c. anything -> anything -> ((forall 'd. 'd -> 'd) -> 'c) -> 'c) -> (forall 'e. ((forall 'd. 'd -> 'd) -> 'e) -> anything -> 'e) -> (forall 'f 'g. anything -> ('f -> 'g) -> 'f -> 'g) -> (anything -> 'h) -> 'b & (forall 'i. ((forall 'j 'k 'l 'm. ('j -> 'k -> 'l) -> ('m -> 'k & 'j) -> 'm -> 'l) -> 'b -> 'i) -> 'i) -> (forall 'n. anything -> 'n -> 'n) -> 'h & (forall 'o 'p 'q 'r 's 't. ((forall 'u. anything -> 'u -> 'u) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (('s -> 'p & 'o) -> 's -> 'q) -> 't) -> 't) -> (forall 'v. ((forall 'n. anything -> 'n -> 'n) -> (forall 'n. anything -> 'n -> 'n) -> 'v) -> 'v) -> (forall 'w. 'w -> anything -> 'w) -> 'a +//│ 'a <: (forall 'c. anything -> anything -> ((forall 'd. 'd -> 'd) -> 'c) -> 'c) -> (forall 'e. ((forall 'd. 'd -> 'd) -> 'e) -> anything -> 'e) -> (forall 'f 'g. anything -> ('f -> 'g) -> 'f -> 'g) -> (anything -> 'h) -> 'b & (((forall 'i 'j 'k 'l. ('i -> 'j -> 'k) -> ('l -> 'j & 'i) -> 'l -> 'k) -> 'b -> 'm) -> 'm) -> (forall 'n. anything -> 'n -> 'n) -> 'h & (forall 'o 'p 'q 'r 's 't. ((forall 'u. anything -> 'u -> 'u) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (('s -> 'p & 'o) -> 's -> 'q) -> 't) -> 't) -> (forall 'v. ((forall 'n. anything -> 'n -> 'n) -> (forall 'n. anything -> 'n -> 'n) -> 'v) -> 'v) -> (forall 'w. 'w -> anything -> 'w) -> 'a //│ = [Function: c_fact_] :e // * The type we infer without any annotations can't be checked against the desired signature c_fact_A = c_fact_ //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: (forall 'b. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> ? -> 'd) -> ((forall 'e. ? -> ? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> ? -> 'g) -> (forall 'h 'i. ? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. ? -> (? -> 'j -> 'j | 'k)) -> 'l & (forall 'm. ((forall 'n 'o 'p 'q. ('n -> 'o -> 'p) -> ('q -> 'o & 'n) -> 'q -> 'p) -> (forall 'r 's. ('r -> 's) -> 'r -> 's | 'l) -> 'm) -> 'm) -> (forall 'c. ? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. ? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a) +//│ 'a <: (forall 'b. ((forall 'c. #? -> 'c -> 'c) -> (forall 'c. #? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> #? -> 'd) -> ((forall 'e. #? -> #? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> #? -> 'g) -> (forall 'h 'i. #? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. #? -> (#? -> 'j -> 'j | 'k)) -> 'l & (((forall 'm 'n 'o 'p. ('m -> 'n -> 'o) -> ('p -> 'n & 'm) -> 'p -> 'o) -> (forall 'q 'r. ('q -> 'r) -> 'q -> 'r | 'l) -> 's) -> 's) -> (forall 'c. #? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. #? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a) //│ ║ l.963: c_1_2_ (n s z) //│ ╙── ^^^ //│ 'a -> 'b //│ where -//│ 'a <: (forall 'c. anything -> anything -> ((forall 'd. 'd -> 'd) -> 'c) -> 'c) -> (forall 'e. ((forall 'd. 'd -> 'd) -> 'e) -> anything -> 'e) -> (forall 'f 'g. anything -> ('f -> 'g) -> 'f -> 'g) -> (anything -> 'h) -> 'b & (forall 'i. ((forall 'j 'k 'l 'm. ('j -> 'k -> 'l) -> ('m -> 'k & 'j) -> 'm -> 'l) -> 'b -> 'i) -> 'i) -> (forall 'n. anything -> 'n -> 'n) -> 'h & (forall 'o 'p 'q 'r 's 't. ((forall 'u. anything -> 'u -> 'u) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (('s -> 'p & 'o) -> 's -> 'q) -> 't) -> 't) -> (forall 'v. ((forall 'n. anything -> 'n -> 'n) -> (forall 'n. anything -> 'n -> 'n) -> 'v) -> 'v) -> (forall 'w. 'w -> anything -> 'w) -> 'a +//│ 'a <: (forall 'c. anything -> anything -> ((forall 'd. 'd -> 'd) -> 'c) -> 'c) -> (forall 'e. ((forall 'd. 'd -> 'd) -> 'e) -> anything -> 'e) -> (forall 'f 'g. anything -> ('f -> 'g) -> 'f -> 'g) -> (anything -> 'h) -> 'b & (((forall 'i 'j 'k 'l. ('i -> 'j -> 'k) -> ('l -> 'j & 'i) -> 'l -> 'k) -> 'b -> 'm) -> 'm) -> (forall 'n. anything -> 'n -> 'n) -> 'h & (forall 'o 'p 'q 'r 's 't. ((forall 'u. anything -> 'u -> 'u) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (('s -> 'p & 'o) -> 's -> 'q) -> 't) -> 't) -> (forall 'v. ((forall 'n. anything -> 'n -> 'n) -> (forall 'n. anything -> 'n -> 'n) -> 'v) -> 'v) -> (forall 'w. 'w -> anything -> 'w) -> 'a //│ <: c_fact_A: //│ Fint -> Fint //│ ╔══[ERROR] Cyclic-looking constraint while typing def definition; a type annotation may be required @@ -1125,7 +1125,7 @@ def print_fact_ n = print_string "\n" //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: (forall 'b. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> ? -> 'd) -> ((forall 'e. ? -> ? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> ? -> 'g) -> (forall 'h 'i. ? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. ? -> (? -> 'j -> 'j | 'k)) -> 'l & (forall 'm. ((forall 'n 'o 'p 'q. ('n -> 'o -> 'p) -> ('q -> 'o & 'n) -> 'q -> 'p) -> (forall 'r 's. ('r -> 's) -> 'r -> 's | 'l) -> 'm) -> 'm) -> (forall 'c. ? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. ? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a) +//│ 'a <: (forall 'b. ((forall 'c. #? -> 'c -> 'c) -> (forall 'c. #? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> #? -> 'd) -> ((forall 'e. #? -> #? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> #? -> 'g) -> (forall 'h 'i. #? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. #? -> (#? -> 'j -> 'j | 'k)) -> 'l & (((forall 'm 'n 'o 'p. ('m -> 'n -> 'o) -> ('p -> 'n & 'm) -> 'p -> 'o) -> (forall 'q 'r. ('q -> 'r) -> 'q -> 'r | 'l) -> 's) -> 's) -> (forall 'c. #? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. #? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a) //│ ║ l.963: c_1_2_ (n s z) //│ ╙── ^^^ //│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required @@ -1160,7 +1160,7 @@ def print_fact2_ n = (c_printint2_ (c_fact_ (to_church_ n))) )) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: (forall 'b. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> ? -> 'd) -> ((forall 'e. ? -> ? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> ? -> 'g) -> (forall 'h 'i. ? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. ? -> (? -> 'j -> 'j | 'k)) -> 'l & (forall 'm. ((forall 'n 'o 'p 'q. ('n -> 'o -> 'p) -> ('q -> 'o & 'n) -> 'q -> 'p) -> (forall 'r 's. ('r -> 's) -> 'r -> 's | 'l) -> 'm) -> 'm) -> (forall 'c. ? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. ? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a) +//│ 'a <: (forall 'b. ((forall 'c. #? -> 'c -> 'c) -> (forall 'c. #? -> 'c -> 'c) -> 'b) -> 'b) -> (forall 'd. 'd -> #? -> 'd) -> ((forall 'e. #? -> #? -> ((forall 'f. 'f -> 'f) -> 'e) -> 'e) -> (forall 'g. ((forall 'f. 'f -> 'f) -> 'g) -> #? -> 'g) -> (forall 'h 'i. #? -> ('h -> 'i) -> 'h -> 'i) -> (forall 'j. #? -> (#? -> 'j -> 'j | 'k)) -> 'l & (((forall 'm 'n 'o 'p. ('m -> 'n -> 'o) -> ('p -> 'n & 'm) -> 'p -> 'o) -> (forall 'q 'r. ('q -> 'r) -> 'q -> 'r | 'l) -> 's) -> 's) -> (forall 'c. #? -> 'c -> 'c) -> 'k & (forall 't 'u 'v 'w 'x 'y. ((forall 'z. #? -> 'z -> 'z) -> ('t -> 'u -> 'v & 'w)) -> ('w -> (('x -> 'u & 't) -> 'x -> 'v) -> 'y) -> 'y) -> 'a) //│ ║ l.963: c_1_2_ (n s z) //│ ╙── ^^^ //│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required @@ -1276,7 +1276,7 @@ c_i9_ = c_pred_ c_i10_ c_99_ = c_add_ (c_mul_ c_i9_ c_i10_) c_i9_ //│ ╔══[ERROR] Inferred recursive type: 'b //│ where -//│ 'b <: (forall 'c 'd 'e 'f. ('c -> 'd -> 'e) -> ('f -> 'd & 'c) -> 'f -> 'e) -> ((forall 'a 'g 'a0 'a1 'a2. (('a | 'g) -> 'a & ('a0 | 'g) -> 'a0 & ('a1 | 'g) -> 'a1 & ('a2 | 'g) -> 'a2) -> 'g -> ('a | 'a0 | 'a1 | 'a2) | Fint) -> ? & (forall 'a3 'h 'a4. (('a3 | 'h) -> 'a3 & ('a4 | 'h) -> 'a4) -> 'h -> ('a3 | 'a4) | Fint) -> anything) +//│ 'b <: (forall 'c 'd 'e 'f. ('c -> 'd -> 'e) -> ('f -> 'd & 'c) -> 'f -> 'e) -> ((forall 'a 'g 'a0 'a1 'a2. (('a | 'g) -> 'a & ('a0 | 'g) -> 'a0 & ('a1 | 'g) -> 'a1 & ('a2 | 'g) -> 'a2) -> 'g -> ('a | 'a0 | 'a1 | 'a2) | Fint) -> #? & (forall 'a3 'h 'a4. (('a3 | 'h) -> 'a3 & ('a4 | 'h) -> 'a4) -> 'h -> ('a3 | 'a4) | Fint) -> anything) //│ ║ l.903: def c_succ_ n = fun f -> fun x -> n f (f x) //│ ╙── ^^^ //│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required diff --git a/shared/src/test/diff/mlf-examples/ex_hashtbl.mls b/shared/src/test/diff/mlf-examples/ex_hashtbl.mls index adb9abcb54..4578dd7e21 100644 --- a/shared/src/test/diff/mlf-examples/ex_hashtbl.mls +++ b/shared/src/test/diff/mlf-examples/ex_hashtbl.mls @@ -99,7 +99,7 @@ def find_A table key = if isnil table then none else if eq (fst (car table)) key then some (snd (car table)) else find_A (cdr table) key -//│ List[(anything, 'b,)] -> anything -> Option['b] +//│ List[(anything, anything,)] -> anything -> Option[in anything out nothing] //│ <: find_A: //│ List[(anything, 'b,)] -> anything -> Option['b] diff --git a/shared/src/test/diff/mlf-examples/ex_predicative.mls b/shared/src/test/diff/mlf-examples/ex_predicative.mls index e69de0364a..3321742ad8 100644 --- a/shared/src/test/diff/mlf-examples/ex_predicative.mls +++ b/shared/src/test/diff/mlf-examples/ex_predicative.mls @@ -197,15 +197,15 @@ t id succ 0 def t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) two //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: ? -> (forall 'b. 'b) -> 'c -//│ 'b :> forall 'd 'e. ((forall 'f. ? -> 'f -> 'f) -> (forall 'f. ? -> 'f -> 'f) -> 'd & 'e) -> (? -> 'e | 'd) | 'c +//│ 'a <: #? -> (forall 'b. 'b) -> 'c +//│ 'b :> forall 'd 'e. ((forall 'f. #? -> 'f -> 'f) -> (forall 'f. #? -> 'f -> 'f) -> 'd & 'e) -> (#? -> 'e | 'd) | 'c //│ 'c :> 'g -//│ <: (forall 'f. ? -> 'f -> 'f) -> (? -> ? -> ? & 'h) +//│ <: (forall 'f. #? -> 'f -> 'f) -> (#? -> #? -> #? & 'h) //│ 'g :> forall 'b 'i. 'i -> 'i | 'b -//│ <: (forall 'f. ? -> 'f -> 'f) -> (? -> ? -> ? & 'h) -//│ 'h <: (forall 'j. ? -> ? -> 'j -> 'j) -> (forall 'k. 'k -> ? -> 'k) -> (forall 'l 'm. ('l -> 'm) -> 'l -> 'm) -> (? -> 'n -> 'g) -> 'a & (forall 'o 'p 'q 'r 's. ((forall 'f. ? -> 'f -> 'f) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (forall 't. ('q -> 't & 'o) -> 'p -> 't) -> 's) -> 's) -> (forall 'u. ((forall 'f. ? -> 'f -> 'f) -> (forall 'f. ? -> 'f -> 'f) -> 'u) -> 'u) -> (forall 'k. 'k -> ? -> 'k) -> ? & ? -> 'n -> 'g +//│ <: (forall 'f. #? -> 'f -> 'f) -> (#? -> #? -> #? & 'h) +//│ 'h <: (forall 'j. #? -> #? -> 'j -> 'j) -> (forall 'k. 'k -> #? -> 'k) -> (forall 'l 'm. ('l -> 'm) -> 'l -> 'm) -> (#? -> 'n -> 'g) -> 'a & (forall 'o 'p 'q 'r 's. ((forall 'f. #? -> 'f -> 'f) -> ('o -> 'p -> 'q & 'r)) -> ('r -> (forall 't. ('q -> 't & 'o) -> 'p -> 't) -> 's) -> 's) -> (forall 'u. ((forall 'f. #? -> 'f -> 'f) -> (forall 'f. #? -> 'f -> 'f) -> 'u) -> 'u) -> (forall 'k. 'k -> #? -> 'k) -> #? & #? -> 'n -> 'g //│ 'n :> forall 'b. 'b -//│ <: ? & 'g +//│ <: #? & 'g //│ ║ l.197: def t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) two //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required @@ -283,7 +283,7 @@ def t y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun (n: ChurchInt) -> n (f :Fuel 6000 :e // occurs-check def t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) three -//│ ╔══[ERROR] Inferred recursive type: ? -> (((forall 'a. nothing -> ('a -> 'a | ?) | ?) | 'b) -> ((forall 'c. ? -> 'c -> 'c) -> nothing & 'd) & (forall 'e 'f. ((forall 'c. ? -> 'c -> 'c) -> (forall 'c. ? -> 'c -> 'c) -> 'e & 'f) -> (? -> 'f | 'e) | ? | 'd) -> ((forall 'c. ? -> 'c -> 'c) -> nothing & 'b)) +//│ ╔══[ERROR] Inferred recursive type: #? -> (((forall 'a. nothing -> ('a -> 'a | #?) | #?) | 'b) -> ((forall 'c. #? -> 'c -> 'c) -> nothing & 'd) & (forall 'e 'f. ((forall 'c. #? -> 'c -> 'c) -> (forall 'c. #? -> 'c -> 'c) -> 'e & 'f) -> (#? -> 'f | 'e) | #? | 'd) -> ((forall 'c. #? -> 'c -> 'c) -> nothing & 'b)) //│ ║ l.285: def t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) three //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ t_: ('a -> ((forall 'b 'c. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'b & 'c) -> (anything -> 'c | 'b) | 'e | 'f | 'g | 'h | 'i | 'j) -> 'g & 'k)) -> ('a & 'l) -> ((forall 'd. anything -> 'd -> 'd) -> ((forall 'm 'n 'o 'p 'q 'r. ((forall 'd. anything -> 'd -> 'd) -> ('m -> 'n -> 'o & 'p)) -> ('p -> (forall 's. ('o -> 's & 'm) -> 'n -> 's) -> 'q) -> ('r -> 'r | 'q) | 'k | 't) -> (forall 'u 'v. ((forall 'd. anything -> 'd -> 'd) -> (forall 'd. anything -> 'd -> 'd) -> 'u & 'v) -> (anything -> 'v | 'u) | 'f | 'g | 'h | 'i | 'w) -> 'e & 'x) & 'i) -> ('g | 'h) @@ -314,7 +314,7 @@ t_ id succ 0 //│ ╔══[ERROR] Inferred recursive type: 'a //│ where //│ 'a :> int -> int -//│ <: (forall 'b 'c 'd 'e 'f 'g 'h. ((forall 'i. ? -> 'i -> 'i) -> (forall 'i. ? -> 'i -> 'i) -> 'b & 'c) -> (? -> 'c | 'b) | ((forall 'i. ? -> 'i -> 'i) -> (forall 'i. ? -> 'i -> 'i) -> 'd & 'e & 'f) -> (? -> 'f | 'e | 'd) | nothing -> ('g -> 'g | ?) | 'j | ? | nothing -> ('h -> 'h | ?)) -> nothing +//│ <: (forall 'b 'c 'd 'e 'f 'g 'h. ((forall 'i. #? -> 'i -> 'i) -> (forall 'i. #? -> 'i -> 'i) -> 'b & 'c) -> (#? -> 'c | 'b) | ((forall 'i. #? -> 'i -> 'i) -> (forall 'i. #? -> 'i -> 'i) -> 'd & 'e & 'f) -> (#? -> 'f | 'e | 'd) | nothing -> ('g -> 'g | #?) | 'j | #? | nothing -> ('h -> 'h | #?)) -> nothing //│ ║ l.285: def t_ y = (fun h -> h (h (h (fun x -> y)))) (fun f -> fun n -> n (fun v -> k2) k app (fun g -> fun x -> n (f (n (fun p -> fun s -> s (p k2) (fun f -> fun x -> f (p k2 f x))) (fun s -> s k2 k2) k) g) x)) three //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╔══[ERROR] Type mismatch in application: @@ -372,7 +372,7 @@ def t (z: nothing) = let x = fun (y: forall 't. 'a -> 't) -> y z in x x :e (fun f -> fun x -> f (f x)) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v) -//│ ╔══[ERROR] Inferred recursive type: ? -> ? -> ? +//│ ╔══[ERROR] Inferred recursive type: #? -> #? -> #? //│ ║ l.374: (fun f -> fun x -> f (f x)) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v) //│ ╙── ^^^ //│ res: 'a -> anything -> 'b @@ -396,7 +396,7 @@ def t (z: nothing) = let x = fun (y: forall 't. 'a -> 't) -> y z in x x :e (fun two -> fun k -> two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v) -//│ ╔══[ERROR] Inferred recursive type: ? -> ? -> ? +//│ ╔══[ERROR] Inferred recursive type: #? -> #? -> #? //│ ║ l.398: (fun two -> fun k -> two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v) //│ ╙── ^^^ //│ res: 'a -> anything -> 'b @@ -421,9 +421,9 @@ def t (z: nothing) = let x = fun (y: forall 't. 'a -> 't) -> y z in x x // :d :e (fun two -> fun k -> two two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v) -//│ ╔══[ERROR] Inferred recursive type: ? -> 'a +//│ ╔══[ERROR] Inferred recursive type: #? -> 'a //│ where -//│ 'a :> ? -> ('a | ?) +//│ 'a :> #? -> ('a | #?) //│ ║ l.423: (fun two -> fun k -> two two two k) (fun f -> fun x -> f (f x)) (fun v -> fun w -> v) //│ ╙── ^^^ //│ res: 'a -> anything -> 'b @@ -502,10 +502,10 @@ def t (z: nothing) = let x = fun (y: forall 't. 'a -> 't) -> y z in x x (fun h -> (fun x -> h (x x)) (fun x -> h (x x))) (fun f -> fun n -> n (fun v -> fun x -> fun y -> y) k (fun f -> fun x -> f x)(fun g -> fun x -> n (f (n (fun p -> fun s -> s (p (fun x -> fun y -> y)) (fun f -> fun x -> f (p (fun x -> fun y -> y) f x))) (fun s -> s (fun f -> fun x -> x) (fun f -> fun x -> x)) k) g) x)) (fun f -> fun x -> f (f x)) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: (nothing -> ('b | 'c) | 'd) -> 'e & (forall 'f 'g 'h 'i 'j. ((forall 'k. ? -> 'k -> 'k) -> 'f & (forall 'l. ? -> 'l -> 'l) -> 'g -> 'h -> 'i) -> ('f -> (forall 'm. ('i -> 'm & 'g) -> 'h -> 'm) -> 'j) -> 'j) -> (forall 'n. ((forall 'o. ? -> 'o -> 'o) -> (forall 'p. ? -> 'p -> 'p) -> 'n) -> 'n) -> (forall 'q. 'q -> ? -> 'q) -> 'a & (forall 'r. ? -> ? -> 'r -> 'r) -> (forall 'q. 'q -> ? -> 'q) -> (forall 's 't. ('s -> 't) -> 's -> 't) -> (((forall 'u. ? -> ? -> 'u -> 'u | ?) -> ((nothing -> ? -> ?) -> 'e & 'b) & (forall 'v. ? -> ? -> 'v -> 'v | ?) -> ((nothing -> ? -> ?) -> 'e & 'b) & (forall 'w. ? -> ? -> 'w -> 'w) -> (nothing -> ? -> ?) -> 'e & (forall 'x. ? -> ? -> 'x -> 'x | ?) -> ((nothing -> ? -> ?) -> 'e & 'b) & (forall 'y. ? -> ? -> 'y -> 'y | ?) -> ((nothing -> ? -> ?) -> 'e & 'b) & 'd & 'z) -> nothing -> 'c) -> 'z -> ((forall 'a1. ? -> ? -> 'a1 -> 'a1) -> (nothing -> ? -> ?) -> 'e & 'd) -//│ 'c :> forall 'b1 'c1. (? & 'b1) -> (? -> 'c1 -> 'c1 | 'b1 | ?) -//│ <: (nothing -> ? -> ?) -> 'e -//│ 'e <: (forall 'd1. ? -> ? -> 'd1 -> 'd1 | ?) -> 'c +//│ 'a <: (nothing -> ('b | 'c) | 'd) -> 'e & (forall 'f 'g 'h 'i 'j. ((forall 'k. #? -> 'k -> 'k) -> 'f & (forall 'l. #? -> 'l -> 'l) -> 'g -> 'h -> 'i) -> ('f -> (forall 'm. ('i -> 'm & 'g) -> 'h -> 'm) -> 'j) -> 'j) -> (forall 'n. ((forall 'o. #? -> 'o -> 'o) -> (forall 'p. #? -> 'p -> 'p) -> 'n) -> 'n) -> (forall 'q. 'q -> #? -> 'q) -> 'a & (forall 'r. #? -> #? -> 'r -> 'r) -> (forall 'q. 'q -> #? -> 'q) -> (forall 's 't. ('s -> 't) -> 's -> 't) -> (((forall 'u. #? -> #? -> 'u -> 'u | #?) -> ((nothing -> #? -> #?) -> 'e & 'b) & (forall 'v. #? -> #? -> 'v -> 'v | #?) -> ((nothing -> #? -> #?) -> 'e & 'b) & (forall 'w. #? -> #? -> 'w -> 'w) -> (nothing -> #? -> #?) -> 'e & (forall 'x. #? -> #? -> 'x -> 'x | #?) -> ((nothing -> #? -> #?) -> 'e & 'b) & (forall 'y. #? -> #? -> 'y -> 'y | #?) -> ((nothing -> #? -> #?) -> 'e & 'b) & 'd & 'z) -> nothing -> 'c) -> 'z -> ((forall 'a1. #? -> #? -> 'a1 -> 'a1) -> (nothing -> #? -> #?) -> 'e & 'd) +//│ 'c :> forall 'b1 'c1. (#? & 'b1) -> (#? -> 'c1 -> 'c1 | 'b1 | #?) +//│ <: (nothing -> #? -> #?) -> 'e +//│ 'e <: (forall 'd1. #? -> #? -> 'd1 -> 'd1 | #?) -> 'c //│ ║ l.502: (fun h -> (fun x -> h (x x)) (fun x -> h (x x))) (fun f -> fun n -> n (fun v -> fun x -> fun y -> y) k (fun f -> fun x -> f x)(fun g -> fun x -> n (f (n (fun p -> fun s -> s (p (fun x -> fun y -> y)) (fun f -> fun x -> f (p (fun x -> fun y -> y) f x))) (fun s -> s (fun f -> fun x -> x) (fun f -> fun x -> x)) k) g) x)) (fun f -> fun x -> f (f x)) //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required diff --git a/shared/src/test/diff/mlf-examples/ex_selfapp.mls b/shared/src/test/diff/mlf-examples/ex_selfapp.mls index 47e22ccbdb..8b121a3873 100644 --- a/shared/src/test/diff/mlf-examples/ex_selfapp.mls +++ b/shared/src/test/diff/mlf-examples/ex_selfapp.mls @@ -135,7 +135,7 @@ def build_ = fun g -> g (fun x -> fun xs -> Cons (x, xs)) Nil build_ : forall 'a. (forall 'b. (('a -> 'b -> 'b) -> 'b -> 'b)) -> List['a] //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> Cons[?] with {tail: forall 'a. Nil | 'a} +//│ 'a :> Cons[#?] with {tail: forall 'a. Nil | 'a} //│ ║ l.130: def build_ = fun g -> g (fun x -> fun xs -> Cons (x, xs)) Nil //│ ╙── ^^^^^^^^^^^^ //│ ╔══[ERROR] Cyclic-looking constraint while typing type ascription; a type annotation may be required @@ -149,7 +149,7 @@ build_ : forall 'a. (forall 'b. (('a -> 'b -> 'b) -> 'b -> 'b)) -> List['a] def build = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> Cons (x, xs)) Nil //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a :> Cons[?] with {tail: forall 'a. Nil | 'a} +//│ 'a :> Cons[#?] with {tail: forall 'a. Nil | 'a} //│ ║ l.149: def build = fun (g: forall 'b. ('a -> 'b -> 'b) -> 'b -> 'b) -> g (fun x -> fun xs -> Cons (x, xs)) Nil //│ ╙── ^^^^^^^^^^^^ //│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required @@ -212,7 +212,7 @@ rec def foldr = fun k -> fun z -> fun xs -> Cons -> k xs.head (foldr k z xs.tail) //│ ╔══[ERROR] Inferred recursive type: 'a //│ where -//│ 'a <: {head: ?, tail: Cons[?] & 'a} +//│ 'a <: {head: #?, tail: Cons[?] & 'a} //│ ║ l.210: case xs of //│ ╙── ^^ //│ foldr: ('head -> 'a -> 'a) -> 'a -> 'b -> 'a @@ -491,7 +491,7 @@ k = k_ // nope //│ 'c :> 'e -> 'f -> 'd //│ <: 'g //│ 'e :> int -> 'g -> 'e -> 'f -> 'd -//│ <: int -> 'a & ? -> 'b -> 'b +//│ <: int -> 'a & #? -> 'b -> 'b //│ 'b :> 'e -> 'f -> 'd //│ <: 'g //│ 'g <: (int -> 'g -> 'e -> 'f -> 'd) -> Baa -> 'h @@ -516,7 +516,7 @@ k = k_ // nope rec def k_ = fun x -> fun xs -> fun c -> fun n -> c (x + 1) (xs k_ z_ c n) //│ ╔══[ERROR] Inferred recursive type: 'k_ //│ where -//│ 'k_ :> int -> ('k_ -> (forall 'a. ? -> 'a -> 'a) -> 'b -> 'c -> 'd) -> (int -> 'd -> 'e & 'b) -> 'c -> 'e +//│ 'k_ :> int -> ('k_ -> (forall 'a. #? -> 'a -> 'a) -> 'b -> 'c -> 'd) -> (int -> 'd -> 'e & 'b) -> 'c -> 'e //│ ╙── //│ k_: 'k_ //│ where diff --git a/shared/src/test/diff/mlf-examples/ex_validate.mls b/shared/src/test/diff/mlf-examples/ex_validate.mls index 56290ff1cf..0cafd97566 100644 --- a/shared/src/test/diff/mlf-examples/ex_validate.mls +++ b/shared/src/test/diff/mlf-examples/ex_validate.mls @@ -466,7 +466,7 @@ def myNil l = eq l nil rec def append x l = if eq l nil then cons x nil else cons (head l) (append x (tail l)) -//│ append: 'a -> List['a] -> List['a] +//│ append: ('a & 'b) -> List['b] -> List['a & 'b] //│ = [Function: append] // let rec map l f = diff --git a/shared/src/test/diff/mlscript/AdtStyle.mls b/shared/src/test/diff/mlscript/AdtStyle.mls index 9291bee0db..bcd38e5057 100644 --- a/shared/src/test/diff/mlscript/AdtStyle.mls +++ b/shared/src/test/diff/mlscript/AdtStyle.mls @@ -76,7 +76,7 @@ fun x -> | Cons(1, b) -> Cons(0, b) | Cons(a, b) -> b | Nil -> Nil -//│ res: List[int & 'A] -> List[0 | 'A] +//│ res: List[int] -> List[nothing] fun x -> match x with diff --git a/shared/src/test/diff/mlscript/Annoying.mls b/shared/src/test/diff/mlscript/Annoying.mls index 2a08eae7f7..b7b62ee84c 100644 --- a/shared/src/test/diff/mlscript/Annoying.mls +++ b/shared/src/test/diff/mlscript/Annoying.mls @@ -63,11 +63,13 @@ def test x = case x of { int -> x.f | _ -> x.x } //│ ╔══[ERROR] Type mismatch in def definition: //│ ║ l.59: def test x = case x of { int -> x.f | _ -> x.x } //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── expression of type `int & {x: 'a} | {x: 'a} & ~?a` does not have field 'f' +//│ ╟── type `int & {x: 'a}` does not have field 'f' +//│ ║ l.55: def test: (int & { f: 'a } | { x: 'a } | { y: 'a }) -> 'a +//│ ║ ^^^^^^^^^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.59: def test x = case x of { int -> x.f | _ -> x.x } //│ ║ ^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.59: def test x = case x of { int -> x.f | _ -> x.x } //│ ╙── ^ @@ -102,13 +104,13 @@ test (error: C & { c: int }) :e test (error: B & { c: int }) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.103: test (error: B & { c: int }) +//│ ║ l.105: test (error: B & { c: int }) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type `B & {c: int}` does not match type `A & {a: 'a} | B & {b: 'a} | C & {c: 'a}` -//│ ║ l.103: test (error: B & { c: int }) +//│ ║ l.105: test (error: B & { c: int }) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from union type: -//│ ║ l.92: def test: (A & { a: 'a } | B & { b: 'a } | C & { c: 'a }) -> 'a +//│ ║ l.94: def test: (A & { a: 'a } | B & { b: 'a } | C & { c: 'a }) -> 'a //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ res: error @@ -126,13 +128,13 @@ test (error: C & { x: int; y: string }) :e test (error: A & { x: int }) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.127: test (error: A & { x: int }) +//│ ║ l.129: test (error: A & { x: int }) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type `A & {x: int}` does not match type `A & {x: 'a, y: 'b} | B & {x: 'a, y: 'b} | C & {x: 'a, y: 'b}` -//│ ║ l.127: test (error: A & { x: int }) +//│ ║ l.129: test (error: A & { x: int }) //│ ║ ^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from union type: -//│ ║ l.116: def test: (A & { x: 'a; y: 'b } | B & { x: 'a; y: 'b } | C & { x: 'a; y: 'b }) -> { l: 'a; r: 'b } +//│ ║ l.118: def test: (A & { x: 'a; y: 'b } | B & { x: 'a; y: 'b } | C & { x: 'a; y: 'b }) -> { l: 'a; r: 'b } //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ res: error | {l: int, r: nothing} @@ -163,16 +165,16 @@ v.x :e negInt: A | { x: 'a } //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.164: negInt: A | { x: 'a } +//│ ║ l.166: negInt: A | { x: 'a } //│ ║ ^^^^^^ //│ ╟── type `~int` does not match type `A | {x: 'a}` -//│ ║ l.151: def negInt: ~int +//│ ║ l.153: def negInt: ~int //│ ║ ^^^^ //│ ╟── but it flows into reference with expected type `A | {x: 'a}` -//│ ║ l.164: negInt: A | { x: 'a } +//│ ║ l.166: negInt: A | { x: 'a } //│ ║ ^^^^^^ //│ ╟── Note: constraint arises from union type: -//│ ║ l.164: negInt: A | { x: 'a } +//│ ║ l.166: negInt: A | { x: 'a } //│ ╙── ^^^^^^^^^^^^^ //│ res: A | {x: nothing} @@ -227,13 +229,13 @@ funny.x :e (error: { x: int }): int | string //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.228: (error: { x: int }): int | string +//│ ║ l.230: (error: { x: int }): int | string //│ ║ ^^^^^^^^^^^^^^^^^^^ //│ ╟── type `{x: int}` does not match type `int | string` -//│ ║ l.228: (error: { x: int }): int | string +//│ ║ l.230: (error: { x: int }): int | string //│ ║ ^^^^^^^^^^ //│ ╟── Note: constraint arises from union type: -//│ ║ l.228: (error: { x: int }): int | string +//│ ║ l.230: (error: { x: int }): int | string //│ ╙── ^^^^^^^^^^^^ //│ res: int | string @@ -271,19 +273,19 @@ def takeFunOrRecord: (int -> int | { x: int }) -> int :pe takeFunOrRecord x = case x of { { x = v } -> 0 | _ -> 1 } -//│ /!\ Parse error: Expected "}":1:33, found "{ x = v } " at l.273:33: takeFunOrRecord x = case x of { { x = v } -> 0 | _ -> 1 } +//│ /!\ Parse error: Expected "}":1:33, found "{ x = v } " at l.275:33: takeFunOrRecord x = case x of { { x = v } -> 0 | _ -> 1 } :pe takeFunOrRecord x = case x of { { x } -> 0 | _ -> 1 } -//│ /!\ Parse error: Expected "}":1:33, found "{ x } -> 0" at l.277:33: takeFunOrRecord x = case x of { { x } -> 0 | _ -> 1 } +//│ /!\ Parse error: Expected "}":1:33, found "{ x } -> 0" at l.279:33: takeFunOrRecord x = case x of { { x } -> 0 | _ -> 1 } :pe takeFunOrRecord x = case x of { (int -> int) -> 0 | _ -> 1 } -//│ /!\ Parse error: Expected "}":1:33, found "(int -> in" at l.281:33: takeFunOrRecord x = case x of { (int -> int) -> 0 | _ -> 1 } +//│ /!\ Parse error: Expected "}":1:33, found "(int -> in" at l.283:33: takeFunOrRecord x = case x of { (int -> int) -> 0 | _ -> 1 } :pe takeFunOrRecord x = case x of { (->) -> 0 | _ -> 1 } -//│ /!\ Parse error: Expected "}":1:33, found "(->) -> 0 " at l.285:33: takeFunOrRecord x = case x of { (->) -> 0 | _ -> 1 } +//│ /!\ Parse error: Expected "}":1:33, found "(->) -> 0 " at l.287:33: takeFunOrRecord x = case x of { (->) -> 0 | _ -> 1 } class AA @@ -302,16 +304,16 @@ ty = ty2 //│ <: ty: //│ AA | nothing\x //│ ╔══[ERROR] Type mismatch in def definition: -//│ ║ l.300: ty = ty2 +//│ ║ l.302: ty = ty2 //│ ║ ^^^^^^^^ //│ ╟── type `TT & {x: int}` does not match type `AA | 'a\x` -//│ ║ l.292: def ty2: TT & { x: int } +//│ ║ l.294: def ty2: TT & { x: int } //│ ║ ^^^^^^^^^^^^^^^ //│ ╟── but it flows into reference with expected type `AA | 'a\x` -//│ ║ l.300: ty = ty2 +//│ ║ l.302: ty = ty2 //│ ║ ^^^ //│ ╟── Note: constraint arises from union type: -//│ ║ l.291: def ty: AA | ('a \ x) +//│ ║ l.293: def ty: AA | ('a \ x) //│ ╙── ^^^^^^^^^^^^^ diff --git a/shared/src/test/diff/mlscript/BadMethods.mls b/shared/src/test/diff/mlscript/BadMethods.mls index 785e75aa21..63c31579b4 100644 --- a/shared/src/test/diff/mlscript/BadMethods.mls +++ b/shared/src/test/diff/mlscript/BadMethods.mls @@ -552,7 +552,7 @@ t : Dup[bool, int] //│ res: Dup[?, int] //│ constrain calls : 25 //│ annoying calls : 21 -//│ subtyping calls : 54 +//│ subtyping calls : 52 :stats t : Dup[int, bool] @@ -567,8 +567,8 @@ t : Dup[int, bool] //│ ╙── ^^^^ //│ res: Dup[?, bool] //│ constrain calls : 28 -//│ annoying calls : 24 -//│ subtyping calls : 67 +//│ annoying calls : 25 +//│ subtyping calls : 65 :stats t.MthDup (fun x -> mul 2 x) diff --git a/shared/src/test/diff/mlscript/David.mls b/shared/src/test/diff/mlscript/David.mls index 081e345a75..6a92d420a9 100644 --- a/shared/src/test/diff/mlscript/David.mls +++ b/shared/src/test/diff/mlscript/David.mls @@ -85,13 +85,15 @@ r4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp | _ -> 0 } //│ ╔══[ERROR] Type mismatch in `case` expression: //│ ║ l.84: r4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp | _ -> 0 } //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── expression of type `1` is not an instance of type `bool` +//│ ╟── integer literal of type `1` is not an instance of type `bool` +//│ ║ l.15: selectBoolOrInt = fun x -> if isInt x then 1 else true +//│ ║ ^ +//│ ╟── but it flows into reference with expected type `bool` +//│ ║ l.84: r4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp | _ -> 0 } +//│ ║ ^^^ //│ ╟── Note: constraint arises from reference: //│ ║ l.3: bb = (fun a -> fun b -> toBool (if b then not a else not a)) true -//│ ║ ^ -//│ ╟── from refined scrutinee: -//│ ║ l.84: r4 = let tmp = selectBoolOrInt 1 in case tmp of { int -> addOne tmp | _ -> 0 } -//│ ╙── ^^^ +//│ ╙── ^ //│ r4: int | true //│ = 2 @@ -141,16 +143,16 @@ def addOne = fun x -> if isInt x then addOneI x else addOneS x :e addOne "hello" //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.142: addOne "hello" +//│ ║ l.144: addOne "hello" //│ ║ ^^^^^^^^^^^^^^ //│ ╟── string literal of type `"hello"` is not an instance of type `int` -//│ ║ l.142: addOne "hello" +//│ ║ l.144: addOne "hello" //│ ║ ^^^^^^^ //│ ╟── Note: constraint arises from reference: //│ ║ l.18: addOneI = fun x -> add x 1 //│ ║ ^ //│ ╟── from reference: -//│ ║ l.137: def addOne = fun x -> if isInt x then addOneI x else addOneS x +//│ ║ l.139: def addOne = fun x -> if isInt x then addOneI x else addOneS x //│ ╙── ^ //│ res: error | int | string //│ = 'helloOne' @@ -175,24 +177,24 @@ addOne "Two" (addOne 1) + 1 concat "Three" (addOne "Two") //│ ╔══[ERROR] Type mismatch in operator application: -//│ ║ l.175: (addOne 1) + 1 +//│ ║ l.177: (addOne 1) + 1 //│ ║ ^^^^^^^^^^^^ //│ ╟── application of type `string` is not an instance of type `int` -//│ ║ l.112: def addOneS = fun x -> concat x "One" +//│ ║ l.114: def addOneS = fun x -> concat x "One" //│ ║ ^^^^^^^^^^^^^^ //│ ╟── but it flows into application with expected type `int` -//│ ║ l.175: (addOne 1) + 1 +//│ ║ l.177: (addOne 1) + 1 //│ ╙── ^^^^^^^^ //│ res: error | int //│ = 3 //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.176: concat "Three" (addOne "Two") +//│ ║ l.178: concat "Three" (addOne "Two") //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── application of type `int` is not an instance of type `string` //│ ║ l.18: addOneI = fun x -> add x 1 //│ ║ ^^^^^^^ //│ ╟── but it flows into application with expected type `string` -//│ ║ l.176: concat "Three" (addOne "Two") +//│ ║ l.178: concat "Three" (addOne "Two") //│ ╙── ^^^^^^^^^^^^ //│ res: error | string //│ = 'ThreeTwoOne' diff --git a/shared/src/test/diff/mlscript/Dmitry.mls b/shared/src/test/diff/mlscript/Dmitry.mls index 0c1d437b7d..730fc6846b 100644 --- a/shared/src/test/diff/mlscript/Dmitry.mls +++ b/shared/src/test/diff/mlscript/Dmitry.mls @@ -9,11 +9,13 @@ class Hidden[A] //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.8: method Main (a: A) = this.Foo a //│ ║ ^^^^^^^^^^ -//│ ╟── expression of type `A & (Class1 | ~?a)` does not have field 'payload' +//│ ╟── reference of type `Class1 & A` does not have field 'payload' +//│ ║ l.8: method Main (a: A) = this.Foo a +//│ ║ ^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.7: method Foo s = case s of { Class1 -> s.payload | _ -> 123 } //│ ║ ^^^^^^^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.7: method Foo s = case s of { Class1 -> s.payload | _ -> 123 } //│ ╙── ^ //│ Defined class Hidden[-A] @@ -39,16 +41,16 @@ arg = if true then "B" else if false then "C" else "D" :e foo arg //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.40: foo arg +//│ ║ l.42: foo arg //│ ║ ^^^^^^^ //│ ╟── string literal of type `"C"` does not match type `"A" | "B" | "D" | "E" | "F" | "G" | "H" | "I" | "J"` -//│ ║ l.35: arg = if true then "B" else if false then "C" else "D" +//│ ║ l.37: arg = if true then "B" else if false then "C" else "D" //│ ║ ^^^ //│ ╟── but it flows into reference with expected type `"A" | "B" | "D" | "E" | "F" | "G" | "H" | "I" | "J"` -//│ ║ l.40: foo arg +//│ ║ l.42: foo arg //│ ║ ^^^ //│ ╟── Note: constraint arises from union type: -//│ ║ l.31: def foo: ("A" | "B" | "D" | "E" | "F" | "G" | "H" | "I" | "J") -> int +//│ ║ l.33: def foo: ("A" | "B" | "D" | "E" | "F" | "G" | "H" | "I" | "J") -> int //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ res: error | int //│ = @@ -71,16 +73,16 @@ foo2 x = case x of { :e foo2 arg //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.72: foo2 arg +//│ ║ l.74: foo2 arg //│ ║ ^^^^^^^^ //│ ╟── string literal of type `"C"` does not match type `"A" & ?a | "B" & ?b | "D" & ?c | "E" & ?d | "F" & ?e | "G" & ?f | "H" & ?g | "I" & ?h | "J" & ?i` -//│ ║ l.35: arg = if true then "B" else if false then "C" else "D" +//│ ║ l.37: arg = if true then "B" else if false then "C" else "D" //│ ║ ^^^ //│ ╟── but it flows into reference with expected type `"A" & ?a | "B" & ?j | "D" & ?c | "E" & ?d | "F" & ?e | "G" & ?f | "H" & ?g | "I" & ?h | "J" & ?i` -//│ ║ l.72: foo2 arg +//│ ║ l.74: foo2 arg //│ ║ ^^^ //│ ╟── Note: constraint arises from reference: -//│ ║ l.57: foo2 x = case x of { +//│ ║ l.59: foo2 x = case x of { //│ ╙── ^ //│ res: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | error //│ = 2 diff --git a/shared/src/test/diff/mlscript/ExprProb.mls b/shared/src/test/diff/mlscript/ExprProb.mls index d960f926d0..80c0eff8fe 100644 --- a/shared/src/test/diff/mlscript/ExprProb.mls +++ b/shared/src/test/diff/mlscript/ExprProb.mls @@ -153,7 +153,7 @@ def eval1_ty_ugly = eval1 //│ 'b <: Add['b] | Lit | 'a & ~Add[?] & ~Lit //│ = [Function: eval1_ty_ugly] //│ constrain calls : 71 -//│ annoying calls : 37 +//│ annoying calls : 40 //│ subtyping calls : 580 :ns @@ -181,7 +181,7 @@ def eval1_ty = eval1 //│ 'b <: Add['b] | Lit | 'a & ~#Add & ~#Lit //│ = [Function: eval1_ty] //│ constrain calls : 71 -//│ annoying calls : 37 +//│ annoying calls : 40 //│ subtyping calls : 576 :stats @@ -195,7 +195,7 @@ eval1_ty_ugly = eval1_ty //│ 'b <: Add['b] | Lit | 'a & ~Add[?] & ~Lit //│ = [Function: eval1] //│ constrain calls : 36 -//│ annoying calls : 33 +//│ annoying calls : 34 //│ subtyping calls : 372 :stats @@ -208,9 +208,9 @@ eval1_ty = eval1_ty_ugly //│ where //│ 'b <: Add['b] | Lit | 'a & ~#Add & ~#Lit //│ = [Function: eval1] -//│ constrain calls : 208 -//│ annoying calls : 529 -//│ subtyping calls : 2710 +//│ constrain calls : 250 +//│ annoying calls : 1905 +//│ subtyping calls : 2075 // Workaround: @@ -235,7 +235,7 @@ def eval1_ty = eval1 //│ ('a -> int) -> E1['a] -> int //│ = [Function: eval1_ty2] //│ constrain calls : 67 -//│ annoying calls : 37 +//│ annoying calls : 40 //│ subtyping calls : 471 @@ -335,8 +335,8 @@ prettier12 done (eval1 done) e1 //│ res: string //│ = '123' //│ constrain calls : 1109 -//│ annoying calls : 500 -//│ subtyping calls : 9419 +//│ annoying calls : 538 +//│ subtyping calls : 9454 e1 = add (lit 1) (add (lit 2) (lit 3)) @@ -427,7 +427,7 @@ eval2 done e1 //│ res: int //│ = 6 //│ constrain calls : 140 -//│ annoying calls : 60 +//│ annoying calls : 65 //│ subtyping calls : 947 e2 = add (lit 1) (nega e1) @@ -451,7 +451,7 @@ eval2 done e2 //│ res: int //│ = -5 //│ constrain calls : 217 -//│ annoying calls : 103 +//│ annoying calls : 112 //│ subtyping calls : 1458 d2 = nega (add (lit 1) (nega (lit 1))) @@ -463,7 +463,7 @@ eval2 done d2 //│ res: int //│ = 0 //│ constrain calls : 147 -//│ annoying calls : 71 +//│ annoying calls : 78 //│ subtyping calls : 940 @@ -558,7 +558,7 @@ prettier22 done (eval2 done) d2 //│ res: string //│ = '-1' //│ constrain calls : 940 -//│ annoying calls : 390 +//│ annoying calls : 425 //│ subtyping calls : 7495 @@ -643,7 +643,7 @@ prettier2 done (eval1 done) e2 //│ Runtime error: //│ Error: non-exhaustive case expression //│ constrain calls : 543 -//│ annoying calls : 238 +//│ annoying calls : 254 //│ subtyping calls : 6309 :e @@ -711,7 +711,7 @@ prettier2 done eval2 e1 //│ res: error //│ = '123' //│ constrain calls : 299 -//│ annoying calls : 108 +//│ annoying calls : 113 //│ subtyping calls : 3130 :e @@ -749,7 +749,7 @@ prettier2 done eval2 e2 //│ res: error //│ = '1-123' //│ constrain calls : 346 -//│ annoying calls : 131 +//│ annoying calls : 139 //│ subtyping calls : 3539 :e @@ -787,7 +787,7 @@ prettier2 done eval2 d2 //│ res: error | string //│ = '-1-1' //│ constrain calls : 253 -//│ annoying calls : 95 +//│ annoying calls : 102 //│ subtyping calls : 2422 :e @@ -825,6 +825,6 @@ prettier2 done eval1 e2 //│ res: error //│ = '1-123' //│ constrain calls : 346 -//│ annoying calls : 131 +//│ annoying calls : 139 //│ subtyping calls : 3493 diff --git a/shared/src/test/diff/mlscript/ExprProb2.mls b/shared/src/test/diff/mlscript/ExprProb2.mls index 4537d42740..ebd0574e20 100644 --- a/shared/src/test/diff/mlscript/ExprProb2.mls +++ b/shared/src/test/diff/mlscript/ExprProb2.mls @@ -185,7 +185,7 @@ eval2_fixed_2 e1 //│ res: int //│ = 6 //│ constrain calls : 267 -//│ annoying calls : 140 +//│ annoying calls : 158 //│ subtyping calls : 1865 :stats @@ -193,7 +193,7 @@ eval2_fixed_2 e2 //│ res: int //│ = -5 //│ constrain calls : 648 -//│ annoying calls : 345 +//│ annoying calls : 389 //│ subtyping calls : 5049 @@ -375,7 +375,7 @@ fix eval2f_oops e2 //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.+1: fix eval2f_oops e2 //│ ║ ^^^^^^^^^^^^^^^ -//│ ╟── function of type `?a -> (forall ?b. ?b)` does not match type `Add[?] & ?c | Lit & ?d` +//│ ╟── function of type `?a -> ?b` does not match type `Add[?] & ?c | Lit & ?d` //│ ║ l.173: def fix f = let fixed = fun x -> f (fun v -> (x x) v) in fixed fixed! //│ ║ ^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from reference: diff --git a/shared/src/test/diff/mlscript/ExprProb_Inv.mls b/shared/src/test/diff/mlscript/ExprProb_Inv.mls index 782e1a91b6..cb8ab7e4a5 100644 --- a/shared/src/test/diff/mlscript/ExprProb_Inv.mls +++ b/shared/src/test/diff/mlscript/ExprProb_Inv.mls @@ -155,7 +155,7 @@ def eval1_ty_ugly = eval1 //│ 'b := Add['b] | Lit | 'a & ~Add[?] & ~Lit //│ = [Function: eval1_ty_ugly] //│ constrain calls : 71 -//│ annoying calls : 37 +//│ annoying calls : 40 //│ subtyping calls : 596 :ns @@ -183,7 +183,7 @@ def eval1_ty = eval1 //│ 'b := Add['b] | Lit | 'a & ~#Add & ~#Lit //│ = [Function: eval1_ty] //│ constrain calls : 71 -//│ annoying calls : 37 +//│ annoying calls : 40 //│ subtyping calls : 588 :stats @@ -197,7 +197,7 @@ eval1_ty_ugly = eval1_ty //│ 'b := Add['b] | Lit | 'a & ~Add[?] & ~Lit //│ = [Function: eval1] //│ constrain calls : 150 -//│ annoying calls : 1810 +//│ annoying calls : 1811 //│ subtyping calls : 2699 :stats @@ -210,9 +210,9 @@ eval1_ty = eval1_ty_ugly //│ where //│ 'b := Add['b] | Lit | 'a & ~#Add & ~#Lit //│ = [Function: eval1] -//│ constrain calls : 752 -//│ annoying calls : 674 -//│ subtyping calls : 71116 +//│ constrain calls : 658 +//│ annoying calls : 2169 +//│ subtyping calls : 44128 // Workaround: @@ -237,7 +237,7 @@ def eval1_ty = eval1 //│ ('a -> int) -> E1['a] -> int //│ = [Function: eval1_ty2] //│ constrain calls : 67 -//│ annoying calls : 37 +//│ annoying calls : 40 //│ subtyping calls : 487 @@ -289,7 +289,7 @@ rec def prettier11 k ev e = case e of { //│ = [Function: prettier11] //│ constrain calls : 178 //│ annoying calls : 0 -//│ subtyping calls : 758 +//│ subtyping calls : 763 // Doesn't make much sense, but generates very ugly type unless aggressively simplified: :stats @@ -308,7 +308,7 @@ rec def prettier12 k ev e = case e of { //│ = [Function: prettier12] //│ constrain calls : 158 //│ annoying calls : 0 -//│ subtyping calls : 834 +//│ subtyping calls : 839 :stats @@ -337,8 +337,8 @@ prettier12 done (eval1 done) e1 //│ res: string //│ = '123' //│ constrain calls : 1109 -//│ annoying calls : 500 -//│ subtyping calls : 9272 +//│ annoying calls : 538 +//│ subtyping calls : 9307 e1 = add (lit 1) (add (lit 2) (lit 3)) @@ -429,7 +429,7 @@ eval2 done e1 //│ res: int //│ = 6 //│ constrain calls : 140 -//│ annoying calls : 60 +//│ annoying calls : 65 //│ subtyping calls : 947 e2 = add (lit 1) (nega e1) @@ -451,7 +451,7 @@ eval2 done e2 //│ res: int //│ = -5 //│ constrain calls : 217 -//│ annoying calls : 103 +//│ annoying calls : 112 //│ subtyping calls : 1458 d2 = nega (add (lit 1) (nega (lit 1))) @@ -465,7 +465,7 @@ eval2 done d2 //│ res: int //│ = 0 //│ constrain calls : 147 -//│ annoying calls : 71 +//│ annoying calls : 78 //│ subtyping calls : 940 @@ -559,7 +559,7 @@ prettier22 done (eval2 done) d2 //│ res: string //│ = '-1' //│ constrain calls : 940 -//│ annoying calls : 390 +//│ annoying calls : 425 //│ subtyping calls : 7554 @@ -644,7 +644,7 @@ prettier2 done (eval1 done) e2 //│ Runtime error: //│ Error: non-exhaustive case expression //│ constrain calls : 543 -//│ annoying calls : 238 +//│ annoying calls : 254 //│ subtyping calls : 6175 :e @@ -712,7 +712,7 @@ prettier2 done eval2 e1 //│ res: error //│ = '123' //│ constrain calls : 299 -//│ annoying calls : 108 +//│ annoying calls : 113 //│ subtyping calls : 3050 :e @@ -750,7 +750,7 @@ prettier2 done eval2 e2 //│ res: error //│ = '1-123' //│ constrain calls : 346 -//│ annoying calls : 131 +//│ annoying calls : 139 //│ subtyping calls : 3457 :e @@ -788,7 +788,7 @@ prettier2 done eval2 d2 //│ res: error | string //│ = '-1-1' //│ constrain calls : 253 -//│ annoying calls : 95 +//│ annoying calls : 102 //│ subtyping calls : 2432 :e @@ -826,7 +826,7 @@ prettier2 done eval1 e2 //│ res: error //│ = '1-123' //│ constrain calls : 346 -//│ annoying calls : 131 +//│ annoying calls : 139 //│ subtyping calls : 3407 diff --git a/shared/src/test/diff/mlscript/GenericClasses.mls b/shared/src/test/diff/mlscript/GenericClasses.mls index 1844d8ee15..e151820e37 100644 --- a/shared/src/test/diff/mlscript/GenericClasses.mls +++ b/shared/src/test/diff/mlscript/GenericClasses.mls @@ -205,7 +205,7 @@ mrg.Foo2 42 def mrg: Foo2[int] | Foo2[string] -//│ mrg: Foo2[out int | string] +//│ mrg: Foo2[in int | string out nothing] //│ = @@ -271,7 +271,7 @@ mrg = Foo2_Co{} //│ = Foo2_Co {} def mrg: Foo2_Co[int] | Foo2_Co[string] -//│ mrg: in Foo2_Co[nothing] out Foo2_Co[int | string] +//│ mrg: Foo2_Co[nothing] //│ = diff --git a/shared/src/test/diff/mlscript/HeadOption.mls b/shared/src/test/diff/mlscript/HeadOption.mls index 0c9a563e6d..7dcc8cec14 100644 --- a/shared/src/test/diff/mlscript/HeadOption.mls +++ b/shared/src/test/diff/mlscript/HeadOption.mls @@ -67,7 +67,7 @@ Cons.HeadOption l0 //│ res: Some[1] //│ constrain calls : 45 //│ annoying calls : 22 -//│ subtyping calls : 137 +//│ subtyping calls : 131 :stats l1 = Cons { head = 1; tail = Cons { head = 2; tail = Cons { head = 3; tail = Nil {} } } } @@ -81,7 +81,7 @@ Cons.HeadOption l1 //│ res: Some[1] //│ constrain calls : 42 //│ annoying calls : 21 -//│ subtyping calls : 140 +//│ subtyping calls : 134 :stats l2 = Cons { head = 0; tail = l1 } @@ -95,7 +95,7 @@ Cons.HeadOption l2 //│ res: Some[0] //│ constrain calls : 48 //│ annoying calls : 22 -//│ subtyping calls : 143 +//│ subtyping calls : 137 :stats l3 = Cons { head = 0-1; tail = l2 } @@ -111,7 +111,7 @@ Cons.HeadOption l3 //│ res: Some[int] //│ constrain calls : 50 //│ annoying calls : 22 -//│ subtyping calls : 148 +//│ subtyping calls : 142 :stats @@ -128,7 +128,7 @@ Cons.HeadOption lr1 //│ res: Some[0] //│ constrain calls : 45 //│ annoying calls : 21 -//│ subtyping calls : 147 +//│ subtyping calls : 141 :stats rec def lr2 = Cons { head = 0; tail = Cons { head = 1; tail = Cons { head = 3; tail = lr2 } } } @@ -144,7 +144,7 @@ Cons.HeadOption lr2 //│ res: Some[0] //│ constrain calls : 44 //│ annoying calls : 21 -//│ subtyping calls : 142 +//│ subtyping calls : 136 :e diff --git a/shared/src/test/diff/mlscript/MethodAndMatches.mls b/shared/src/test/diff/mlscript/MethodAndMatches.mls index 5fad780c59..71c4705187 100644 --- a/shared/src/test/diff/mlscript/MethodAndMatches.mls +++ b/shared/src/test/diff/mlscript/MethodAndMatches.mls @@ -67,11 +67,13 @@ def bar0 = foo //│ ╔══[ERROR] Type mismatch in def definition: //│ ║ l.63: def bar0 = foo //│ ║ ^^^^^^^^^^^^^^ -//│ ╟── expression of type `Base1[int] & ~?a | Derived1` does not have field 'x' +//│ ╟── type `Derived1` does not have field 'x' +//│ ║ l.49: def bar0: Base1[int] -> int -> Base1[int] +//│ ║ ^^^^^^^^^^ //│ ╟── Note: constraint arises from record type: //│ ║ l.4: class Derived1: Base1[int] & { x: int } //│ ║ ^^^^^^^^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.31: def foo b x = case b of { //│ ╙── ^ //│ = [Function: bar0] @@ -94,10 +96,10 @@ def bar1 = foo //│ <: bar1: //│ Type1[?] -> int -> Type1[?] //│ ╔══[ERROR] Type mismatch in def definition: -//│ ║ l.92: def bar1 = foo +//│ ║ l.94: def bar1 = foo //│ ║ ^^^^^^^^^^^^^^ //│ ╟── type `int` is not a record (expected a record with fields: c, d) -//│ ║ l.79: def bar1: Type1[int] -> int -> Type1[int] +//│ ║ l.81: def bar1: Type1[int] -> int -> Type1[int] //│ ║ ^^^ //│ ╟── Note: constraint arises from record type: //│ ║ l.10: class Derived3[C, D]: Base1[{ c: C; d: D }] & { c: C; d: D } @@ -126,13 +128,13 @@ def bar2 = foo //│ <: bar2: //│ Base1['a] -> 'a -> Base1['a] //│ ╔══[ERROR] Type mismatch in def definition: -//│ ║ l.124: def bar2 = foo +//│ ║ l.126: def bar2 = foo //│ ║ ^^^^^^^^^^^^^^ //│ ╟── type `int` does not match type `'a` //│ ║ l.4: class Derived1: Base1[int] & { x: int } //│ ║ ^^^ //│ ╟── Note: constraint arises from type variable: -//│ ║ l.110: def bar2: Base1['a] -> 'a -> Base1['a] +//│ ║ l.112: def bar2: Base1['a] -> 'a -> Base1['a] //│ ╙── ^^ //│ = [Function: bar2] diff --git a/shared/src/test/diff/mlscript/MiscExtrusion.mls b/shared/src/test/diff/mlscript/MiscExtrusion.mls index a97950199a..c7cb4a549c 100644 --- a/shared/src/test/diff/mlscript/MiscExtrusion.mls +++ b/shared/src/test/diff/mlscript/MiscExtrusion.mls @@ -32,10 +32,7 @@ def alsoPrintSizeSimple f = let rec nested expr = f (asExpr expr) nested in nested -//│ alsoPrintSizeSimple: (Expr[in 'a out 'a | 'a0] -> (Expr[in 'a0 & 'a1 out 'a2] -> 'b) -> 'b) -> Expr['a2] -> 'b -//│ where -//│ 'a2 :> 'a | 'a1 -//│ <: 'a0 +//│ alsoPrintSizeSimple: (Expr['a] -> (Expr['a] -> 'b) -> 'b) -> Expr['a] -> 'b class Program @@ -53,17 +50,17 @@ def alsoPrintSize f = :e alsoPrintSize id //│ ╔══[ERROR] Type error in application -//│ ║ l.54: alsoPrintSize id +//│ ║ l.51: alsoPrintSize id //│ ║ ^^^^^^^^^^^^^^^^ //│ ╟── type variable `'a` leaks out of its scope -//│ ║ l.44: def mapExpr: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program +//│ ║ l.41: def mapExpr: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program //│ ║ ^^ //│ ╟── back into type variable `'a` -//│ ║ l.44: def mapExpr: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program +//│ ║ l.41: def mapExpr: (forall 'a. Expr['a] -> Expr['a]) -> Program -> Program //│ ║ ^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this application: -//│ ║ l.50: mapExpr(fun e -> let tmp = print e in f e) +//│ ║ l.47: mapExpr(fun e -> let tmp = print e in f e) //│ ╙── ^^^ //│ res: error | Program -> Program @@ -92,17 +89,17 @@ def alsoPrintSizeCo f = :e alsoPrintSizeCo id //│ ╔══[ERROR] Type error in application -//│ ║ l.93: alsoPrintSizeCo id +//│ ║ l.90: alsoPrintSizeCo id //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'a` leaks out of its scope -//│ ║ l.83: def mapExprCo: (forall 'a. ExprCo['a] -> ExprCo['a]) -> Program -> Program +//│ ║ l.80: def mapExprCo: (forall 'a. ExprCo['a] -> ExprCo['a]) -> Program -> Program //│ ║ ^^ //│ ╟── back into type variable `'a` -//│ ║ l.83: def mapExprCo: (forall 'a. ExprCo['a] -> ExprCo['a]) -> Program -> Program +//│ ║ l.80: def mapExprCo: (forall 'a. ExprCo['a] -> ExprCo['a]) -> Program -> Program //│ ║ ^^ //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this application: -//│ ║ l.89: mapExprCo(fun e -> let tmp = printCo e in f e) +//│ ║ l.86: mapExprCo(fun e -> let tmp = printCo e in f e) //│ ╙── ^^^ //│ res: error | Program -> Program diff --git a/shared/src/test/diff/mlscript/Mohammad.mls b/shared/src/test/diff/mlscript/Mohammad.mls index d4a2b68559..50def3e481 100644 --- a/shared/src/test/diff/mlscript/Mohammad.mls +++ b/shared/src/test/diff/mlscript/Mohammad.mls @@ -102,11 +102,16 @@ useTrt c //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.101: useTrt c //│ ║ ^^^^^^^^ -//│ ╟── expression of type `Class & {x: ?x} & ~?a | Class & {x: ?x} & #T` does not have field 'y' +//│ ╟── application of type `Class & {x: ?x} & #T` does not have field 'y' +//│ ║ l.16: c = Class{x = 1} +//│ ║ ^^^^^^^^^^^^ +//│ ╟── but it flows into reference with expected type `{y: ?y}` +//│ ║ l.101: useTrt c +//│ ║ ^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.96: def useTrt t = case t of { T -> t.y | Class -> t.x } //│ ║ ^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.96: def useTrt t = case t of { T -> t.y | Class -> t.x } //│ ╙── ^ //│ res: 1 | error @@ -119,13 +124,18 @@ useTrt (c with { y = 1 }) :e useTrt c //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.120: useTrt c +//│ ║ l.125: useTrt c //│ ║ ^^^^^^^^ -//│ ╟── expression of type `Class & {x: ?x} & ~?a | Class & {x: ?x} & #T` does not have field 'y' +//│ ╟── application of type `Class & {x: ?x} & #T` does not have field 'y' +//│ ║ l.16: c = Class{x = 1} +//│ ║ ^^^^^^^^^^^^ +//│ ╟── but it flows into reference with expected type `{y: ?y}` +//│ ║ l.125: useTrt c +//│ ║ ^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.96: def useTrt t = case t of { T -> t.y | Class -> t.x } //│ ║ ^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.96: def useTrt t = case t of { T -> t.y | Class -> t.x } //│ ╙── ^ //│ res: 1 | error diff --git a/shared/src/test/diff/mlscript/NestedRecursiveMatch.mls b/shared/src/test/diff/mlscript/NestedRecursiveMatch.mls index c27d65dff2..1eff55f6e2 100644 --- a/shared/src/test/diff/mlscript/NestedRecursiveMatch.mls +++ b/shared/src/test/diff/mlscript/NestedRecursiveMatch.mls @@ -34,7 +34,7 @@ rec def f w = case w of Some -> let m = (tmp0).value in Some (m,) -//│ f: (Leaf | Node & 'b) -> (None | Some[in 'a out 0 | 'a]) +//│ f: (Leaf | Node & 'b) -> (None | Some[in 'value & 'a | 'value & 'a0 | 'value & 'a1 out (0 | 'a) & (0 | 'value | 'a0) & (0 | 'value | 'a1)]) //│ where //│ 'b <: {left: Leaf | Node & 'b, right: Leaf | Node & 'b} @@ -49,7 +49,7 @@ rec def f w = case w of Some -> let m = (tmp0).value in Some (m,) -//│ f: 'left -> Some[in 'a out 0 | 'a] +//│ f: 'left -> Some[in 'value & 'a | 'value & 'a0 out (0 | 'a) & (0 | 'value | 'a0)] //│ where //│ 'left <: Node & {left: 'left} @@ -61,7 +61,7 @@ rec def f w = case w of Some -> // Some tmp0.value // * produces different result! let m = tmp0.value in Some m -//│ f: 'b -> Some[in 'a out 0 | 'a] +//│ f: 'b -> Some[in 'value & 'a | 'value & 'a0 out (0 | 'a) & (0 | 'value | 'a0)] //│ where //│ 'b <: Node & {left: 'b} @@ -71,7 +71,7 @@ def f w = None -> Some 0, Some -> let m = tmp0.value in Some m -//│ f: 'b -> Some[in 'a out 0 | 'a] +//│ f: 'b -> Some[in 'a | 'a0 out (0 | 'a) & (0 | 'a0)] //│ where //│ 'b <: {left: Node & 'b} diff --git a/shared/src/test/diff/mlscript/OccursCheck.mls b/shared/src/test/diff/mlscript/OccursCheck.mls index 86d6ca94f3..ea05c96fc8 100644 --- a/shared/src/test/diff/mlscript/OccursCheck.mls +++ b/shared/src/test/diff/mlscript/OccursCheck.mls @@ -14,7 +14,7 @@ rec def f x = f x rec def f x = f //│ ╔══[ERROR] Inferred recursive type: 'f //│ where -//│ 'f :> ? -> 'f +//│ 'f :> #? -> 'f //│ ╙── //│ f: 'f //│ where diff --git a/shared/src/test/diff/mlscript/PolyVariant.mls b/shared/src/test/diff/mlscript/PolyVariant.mls index af5df93f64..f7e6532f9e 100644 --- a/shared/src/test/diff/mlscript/PolyVariant.mls +++ b/shared/src/test/diff/mlscript/PolyVariant.mls @@ -193,7 +193,7 @@ class Tuple[a, b]: { _1: a; _2: b } //│ Defined class Tuple[+a, +b] def t2: Tuple[A | B, anything] | Tuple[anything, A | B] -//│ t2: in Tuple[A | B, A | B] out Tuple[?, ?] +//│ t2: Tuple[A | B, A | B] //│ = def t3: Tuple[anything, anything] //│ t3: Tuple[?, ?] @@ -201,7 +201,7 @@ def t3: Tuple[anything, anything] t3 = t2 t2 = t3 -//│ Tuple[?, ?] +//│ Tuple[A | B, A | B] //│ <: t3: //│ Tuple[?, ?] //│ = diff --git a/shared/src/test/diff/mlscript/PolyVariantCodeReuse.mls b/shared/src/test/diff/mlscript/PolyVariantCodeReuse.mls index 1e5f694785..f441574a83 100644 --- a/shared/src/test/diff/mlscript/PolyVariantCodeReuse.mls +++ b/shared/src/test/diff/mlscript/PolyVariantCodeReuse.mls @@ -426,16 +426,16 @@ rec def eval4 subst = eval_lexpr' eval4 subst //│ 'tail3 <: Cons[?] & 'f | Nil //│ 'f <: {head: {0: string, 1: 'result0}, tail: 'tail3} //│ 'tail2 <: Cons[?] & 'e | Nil -//│ 'e <: {head: {0: string, 1: 'result0}, tail: 'tail2} +//│ 'e <: {head: {0: string, 1: 'result}, tail: 'tail2} //│ 'tail1 <: Cons[?] & 'd | Nil -//│ 'd <: {head: {0: string, 1: 'result0}, tail: 'tail1} +//│ 'd <: {head: {0: string, 1: 'result}, tail: 'tail1} //│ 'tail0 <: Cons[?] & 'c | Nil -//│ 'c <: {head: {0: string, 1: 'result}, tail: 'tail0} +//│ 'c <: {head: {0: string, 1: 'result0}, tail: 'tail0} //│ 'tail <: Cons[?] & 'b | Nil -//│ 'b <: {head: {0: string, 1: 'result}, tail: 'tail} -//│ 'result :> 'i -//│ <: Abs[?] & 'j & 'k | 'lhs & (Abs[?] & 'k & ~#Abs | Add[?] & 'l | App[?] & 'm | Mul[?] & 'n | Numb & 'o | Var & 'p) -//│ 'i :> Abs['i] | App['a]\lhs\rhs & {lhs: 'lhs, rhs: 'rhs} | Numb | 'result0 | Add['i]\lhs\rhs & {lhs: 'i, rhs: 'i} | Mul['i]\lhs\rhs & {lhs: 'i, rhs: 'i} | 'q | 'result +//│ 'b <: {head: {0: string, 1: 'result0}, tail: 'tail} +//│ 'result0 :> 'i +//│ <: Abs[?] & 'j & 'k | 'lhs & (Abs[?] & 'k & ~#Abs | Add[?] & 'l | App[?] & 'm | Mul[?] & 'n | Numb & 'o | Var & 'p) +//│ 'i :> Abs['i] | App['a]\lhs\rhs & {lhs: 'lhs, rhs: 'rhs} | Numb | 'result | Add['i]\lhs\rhs & {lhs: 'i, rhs: 'i} | Mul['i]\lhs\rhs & {lhs: 'i, rhs: 'i} | 'q | 'result0 //│ 'a :> Add['i]\lhs\rhs & {lhs: 'i, rhs: 'i} | App['a]\lhs\rhs & {lhs: 'lhs, rhs: 'rhs} | Mul['i]\lhs\rhs & {lhs: 'i, rhs: 'i} | Numb | 'i //│ 'lhs :> Add['i]\lhs\rhs & {lhs: 'i, rhs: 'i} | App['a]\lhs\rhs & {lhs: 'lhs, rhs: 'rhs} | Mul['i]\lhs\rhs & {lhs: 'i, rhs: 'i} | Numb | Var //│ <: 'h & 'a @@ -443,11 +443,11 @@ rec def eval4 subst = eval_lexpr' eval4 subst //│ 'k <: Abs[?] | App[?] | Var & 'q //│ 'q :> Var //│ <: Abs[?] & 'j & 'k | 'lhs & (Abs[?] & 'k & ~#Abs | Add[?] & {name: string} & 'l | App[?] & {name: string} & 'm | Mul[?] & {name: string} & 'n | Numb & {name: string} & 'o | Var & 'p) -//│ 'l <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'p & 'lhs -//│ 'result0 :> Numb | Var | 'i -//│ <: Abs[?] & 'j & 'k | 'lhs & (Add[?] & 'l | App[?] & 'm | Mul[?] & 'n | Numb & 'o | Var & 'p) -//│ 'o <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'p & 'lhs -//│ 'n <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result0 | Var & 'p & 'lhs +//│ 'l <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result | Var & 'p & 'lhs +//│ 'result :> Numb | Var | 'i +//│ <: Abs[?] & 'j & 'k | 'lhs & (Add[?] & 'l | App[?] & 'm | Mul[?] & 'n | Numb & 'o | Var & 'p) +//│ 'o <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result | Var & 'p & 'lhs +//│ 'n <: Add[?] & {lhs: 'h, rhs: 'h} | Mul[?] & {lhs: 'h, rhs: 'h} | Numb & 'result | Var & 'p & 'lhs //│ 'p <: Var & 'q //│ 'm <: Abs[?] & {body: 'h} | App[?] & {lhs: 'h, rhs: 'h} | Var & 'q //│ 'j <: {body: 'h, name: string} @@ -497,9 +497,9 @@ rec def eval4 subst = eval_lexpr' eval4 subst //│ 'rhs :> 'i //│ = //│ eval_lexpr', eval_var, list_assoc and eq are not implemented -//│ constrain calls : 10599 -//│ annoying calls : 2300 -//│ subtyping calls : 319664 +//│ constrain calls : 10623 +//│ annoying calls : 2768 +//│ subtyping calls : 320018 :ResetFuel diff --git a/shared/src/test/diff/mlscript/PreservationFail.mls b/shared/src/test/diff/mlscript/PreservationFail.mls index 21b335efaa..891be20561 100644 --- a/shared/src/test/diff/mlscript/PreservationFail.mls +++ b/shared/src/test/diff/mlscript/PreservationFail.mls @@ -88,7 +88,7 @@ rec def getNegT1 x = case x of { //│ = [Function: getNegT1] nt1 = getNegT1 {} -//│ nt1: ~#T1 +//│ nt1: 'a | ~(#T1 & (#T1 | 'a & ~#T1)) //│ = {} T1 @@ -96,7 +96,7 @@ T1 //│ = [Function: build] t1nt1 = T1 nt1 -//│ t1nt1: nothing +//│ t1nt1: #T1 & ('a | ~#T1 & ~('a & ~#T1)) //│ = {} :re diff --git a/shared/src/test/diff/mlscript/RecursiveTypes.mls b/shared/src/test/diff/mlscript/RecursiveTypes.mls index 5fbbd12f81..9eac9fb529 100644 --- a/shared/src/test/diff/mlscript/RecursiveTypes.mls +++ b/shared/src/test/diff/mlscript/RecursiveTypes.mls @@ -704,12 +704,12 @@ f "a" //│ res: int rec def f x = case x of {int -> f "ok" | string -> f (impossible x) | _ -> x} -//│ f: (int | string & (int | string | ~int) | 'a & ~int & ~string) -> 'a +//│ f: (int | string & (int | string | ~int) | 'a & ~int & ~string) -> ("ok" & ~int & ~string & int | 'a) f 1 f "a" f false -//│ res: nothing -//│ res: nothing -//│ res: false +//│ res: "ok" & ~int & ~string & int +//│ res: ~int & ~string & int & ("a" | "ok") +//│ res: "ok" & ~int & ~string & int | false diff --git a/shared/src/test/diff/mlscript/References.mls b/shared/src/test/diff/mlscript/References.mls index 1dd8a5625c..5c775ab7d6 100644 --- a/shared/src/test/diff/mlscript/References.mls +++ b/shared/src/test/diff/mlscript/References.mls @@ -177,17 +177,17 @@ move ri rn def swap a b = let tmp = a.Get in (a.Set b.Get, b.Set tmp) -//│ swap: Ref[in 'A & 'A0 out 'A | 'A0] -> Ref[in 'A1 & 'A0 out 'A | 'A1] -> (unit, unit,) +//│ swap: Ref[in 'A & 'A0 out 'A | 'A0] -> Ref[in 'A1 & ('A | 'A2) out 'A0 & 'A1 | 'A2] -> (unit, unit,) //│ = [Function: swap] swap r swap ri swap rn -//│ res: Ref[in 'A out 1 | 'A] -> (unit, unit,) +//│ res: Ref[in 'A & (1 | 'A0) out 'A | 'A0] -> (unit, unit,) //│ = [Function (anonymous)] -//│ res: Ref[int] -> (unit, unit,) +//│ res: Ref[out 'A] -> (unit, unit,) //│ = [Function (anonymous)] -//│ res: Ref[number] -> (unit, unit,) +//│ res: Ref[out 'A] -> (unit, unit,) //│ = [Function (anonymous)] swap r ri @@ -269,7 +269,7 @@ res.Swap //│ res: ('A & ((int | string) & 'b | 'd & (int | string))) -> ('b & 'd | 'A) refin: Ref['a..'b] | Ref['c..'d] -//│ res: Ref[in 'd & (int | string | ~'d) out 'd] +//│ res: Ref[in 'd | 'b & (int | string | ~'d) out 'b & 'd] //│ = //│ refin is not implemented @@ -337,7 +337,7 @@ consrefin (RefImpl { mut value = error }) def refun: Ref[int] | Ref[string] -//│ refun: Ref[out int | string] +//│ refun: Ref[in int | string out nothing] //│ = // * Errors happen because we constrain `Ref[int] | Ref[string] <: Ref['A]` diff --git a/shared/src/test/diff/mlscript/Scratch.mls b/shared/src/test/diff/mlscript/Scratch.mls index e69de29bb2..72784a52f1 100644 --- a/shared/src/test/diff/mlscript/Scratch.mls +++ b/shared/src/test/diff/mlscript/Scratch.mls @@ -0,0 +1,6 @@ + +class Foo +//│ Defined class Foo + + + diff --git a/shared/src/test/diff/mlscript/SimpleErrors.mls b/shared/src/test/diff/mlscript/SimpleErrors.mls index f55e93bf5b..a8e7f59f58 100644 --- a/shared/src/test/diff/mlscript/SimpleErrors.mls +++ b/shared/src/test/diff/mlscript/SimpleErrors.mls @@ -44,11 +44,13 @@ test1 1 //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.43: test1 1 //│ ║ ^^^^^^^ -//│ ╟── expression of type `1 & ~?a | 1 & #MyTrait` does not have field 'value' +//│ ╟── integer literal of type `1 & #MyTrait` does not have field 'value' +//│ ║ l.43: test1 1 +//│ ║ ^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.39: def test1 x = case x of { MyTrait -> x.value | _ -> 0 } //│ ║ ^^^^^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.39: def test1 x = case x of { MyTrait -> x.value | _ -> 0 } //│ ╙── ^ //│ res: 0 | error @@ -61,16 +63,16 @@ def map f = f map (fun x -> map) //│ <: map: //│ 'a -> 'a //│ ╔══[ERROR] Type mismatch in def definition: -//│ ║ l.58: def map f = f map (fun x -> map) +//│ ║ l.60: def map f = f map (fun x -> map) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type `'a` is not a function -//│ ║ l.57: def map: 'a -> 'a +//│ ║ l.59: def map: 'a -> 'a //│ ║ ^^ //│ ╟── Note: constraint arises from application: -//│ ║ l.58: def map f = f map (fun x -> map) +//│ ║ l.60: def map f = f map (fun x -> map) //│ ║ ^^^^^ //│ ╟── from reference: -//│ ║ l.58: def map f = f map (fun x -> map) +//│ ║ l.60: def map f = f map (fun x -> map) //│ ╙── ^ @@ -78,16 +80,16 @@ class Bar method Map[B]: B -> B rec method Map f = f 1 //│ ╔══[ERROR] Type mismatch in method definition: -//│ ║ l.79: rec method Map f = f 1 +//│ ║ l.81: rec method Map f = f 1 //│ ║ ^^^^^^^^^^^ //│ ╟── type `B` is not a function -//│ ║ l.78: method Map[B]: B -> B +//│ ║ l.80: method Map[B]: B -> B //│ ║ ^ //│ ╟── Note: constraint arises from application: -//│ ║ l.79: rec method Map f = f 1 +//│ ║ l.81: rec method Map f = f 1 //│ ║ ^^^ //│ ╟── from reference: -//│ ║ l.79: rec method Map f = f 1 +//│ ║ l.81: rec method Map f = f 1 //│ ╙── ^ //│ Defined class Bar //│ Declared Bar.Map: Bar -> 'B -> 'B @@ -101,13 +103,13 @@ def boom: anything :e add boom 1 //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.102: add boom 1 +//│ ║ l.104: add boom 1 //│ ║ ^^^^^^^^ //│ ╟── type `anything` is not an instance of type `int` -//│ ║ l.97: def boom: anything +//│ ║ l.99: def boom: anything //│ ║ ^^^^^^^^ //│ ╟── but it flows into reference with expected type `int` -//│ ║ l.102: add boom 1 +//│ ║ l.104: add boom 1 //│ ╙── ^^^^ //│ res: error | int diff --git a/shared/src/test/diff/mlscript/Splice.mls b/shared/src/test/diff/mlscript/Splice.mls index 6972e21485..16b2043725 100644 --- a/shared/src/test/diff/mlscript/Splice.mls +++ b/shared/src/test/diff/mlscript/Splice.mls @@ -92,4 +92,4 @@ a2 = (1,2, ...a1, 4,5) // TODO a2 : Array[int] -//│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing +//│ /!!!\ Uncaught error: java.lang.Exception: Internal Error: Program reached and unexpected state. diff --git a/shared/src/test/diff/mlscript/Stress.mls b/shared/src/test/diff/mlscript/Stress.mls index e9627da558..2bf15d226d 100644 --- a/shared/src/test/diff/mlscript/Stress.mls +++ b/shared/src/test/diff/mlscript/Stress.mls @@ -63,7 +63,7 @@ foo arg //│ arg: A[int] | B[int] //│ res: int //│ constrain calls : 36 -//│ annoying calls : 20 +//│ annoying calls : 22 //│ subtyping calls : 276 @@ -81,7 +81,7 @@ foo arg //│ arg: A[int] | B[int] | C[int] //│ res: int //│ constrain calls : 48 -//│ annoying calls : 30 +//│ annoying calls : 33 //│ subtyping calls : 522 @@ -100,21 +100,21 @@ foo arg //│ arg: A[int] | B[int] | C[int] | D[int] //│ res: int //│ constrain calls : 60 -//│ annoying calls : 40 +//│ annoying calls : 44 //│ subtyping calls : 852 :stats foo (arg with { x = 1} with { y = 2 }) //│ res: int //│ constrain calls : 35 -//│ annoying calls : 37 +//│ annoying calls : 41 //│ subtyping calls : 369 :stats foo (arg with { x = 1; y = 2; z = 3 }) //│ res: int //│ constrain calls : 35 -//│ annoying calls : 37 +//│ annoying calls : 41 //│ subtyping calls : 345 @@ -134,7 +134,7 @@ foo arg //│ arg: A[int] | B[int] | C[int] | D[int] | E[int] //│ res: int //│ constrain calls : 72 -//│ annoying calls : 50 +//│ annoying calls : 55 //│ subtyping calls : 1274 @@ -155,7 +155,7 @@ foo arg //│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] //│ res: int //│ constrain calls : 84 -//│ annoying calls : 60 +//│ annoying calls : 66 //│ subtyping calls : 1796 @@ -177,7 +177,7 @@ foo arg //│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] //│ res: int //│ constrain calls : 96 -//│ annoying calls : 70 +//│ annoying calls : 77 //│ subtyping calls : 2426 @@ -200,7 +200,7 @@ foo arg //│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] | H[int] //│ res: int //│ constrain calls : 108 -//│ annoying calls : 80 +//│ annoying calls : 88 //│ subtyping calls : 3172 diff --git a/shared/src/test/diff/mlscript/StressDNF.mls b/shared/src/test/diff/mlscript/StressDNF.mls index a190878d59..7a8505c76d 100644 --- a/shared/src/test/diff/mlscript/StressDNF.mls +++ b/shared/src/test/diff/mlscript/StressDNF.mls @@ -32,7 +32,7 @@ ty0 = ty1 //│ <: ty0: //│ (E & 'e & 'f | 'd & (C & 'c | D & 'e) | 'b & (A & 'a | B & 'c)) -> ('a, 'b, 'c, 'd, 'e, 'f,) //│ constrain calls : 45 -//│ annoying calls : 25 +//│ annoying calls : 30 //│ subtyping calls : 1035 :stats @@ -51,7 +51,7 @@ ty1 = ty0 //│ ║ l.26: def ty1: ('a & A | 'b & B | 'c & C | 'd & D | 'e & E) -> ('a, 'b, 'c, 'd, 'e, 'f) //│ ╙── ^^ //│ constrain calls : 70 -//│ annoying calls : 51 +//│ annoying calls : 61 //│ subtyping calls : 1048 diff --git a/shared/src/test/diff/mlscript/StressTraits.mls b/shared/src/test/diff/mlscript/StressTraits.mls index df63bffef4..b4f9b4b403 100644 --- a/shared/src/test/diff/mlscript/StressTraits.mls +++ b/shared/src/test/diff/mlscript/StressTraits.mls @@ -42,7 +42,7 @@ foo arg //│ arg: A[int] //│ res: int //│ constrain calls : 19 -//│ annoying calls : 9 +//│ annoying calls : 10 //│ subtyping calls : 248 :stats @@ -53,17 +53,22 @@ foo arg //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.51: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.50: def arg: A[int] | B[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.51: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.22: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.21: def foo x = case x of { //│ ╙── ^ //│ res: error | int -//│ constrain calls : 36 -//│ annoying calls : 31 -//│ subtyping calls : 698 +//│ constrain calls : 41 +//│ annoying calls : 41 +//│ subtyping calls : 597 :stats :e @@ -71,19 +76,24 @@ def arg: A[int] | B[int] | C[int] foo arg //│ arg: A[int] | B[int] | C[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.71: foo arg +//│ ║ l.76: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.75: def arg: A[int] | B[int] | C[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.76: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.22: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.21: def foo x = case x of { //│ ╙── ^ -//│ res: error | int -//│ constrain calls : 65 -//│ annoying calls : 90 -//│ subtyping calls : 3208 +//│ res: error +//│ constrain calls : 118 +//│ annoying calls : 168 +//│ subtyping calls : 1664 :stats :e @@ -91,19 +101,24 @@ def arg: A[int] | B[int] | D[int] foo arg //│ arg: A[int] | B[int] | D[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.91: foo arg -//│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ║ l.101: foo arg +//│ ║ ^^^^^^^ +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.100: def arg: A[int] | B[int] | D[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.101: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.22: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.21: def foo x = case x of { //│ ╙── ^ //│ res: error -//│ constrain calls : 82 -//│ annoying calls : 209 -//│ subtyping calls : 16245 +//│ constrain calls : 135 +//│ annoying calls : 226 +//│ subtyping calls : 2257 // ====== 2 ====== // @@ -119,19 +134,24 @@ foo arg //│ foo: ({fB: 'fA} & #B & ~#A | {fA: 'fA} & #A) -> 'fA //│ arg: A[int] | B[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.118: foo arg +//│ ║ l.133: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.132: def arg: A[int] | B[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.133: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.114: | A -> x.fA +//│ ║ l.129: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.113: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.128: def foo x = case x of { //│ ╙── ^ //│ res: error | int -//│ constrain calls : 44 -//│ annoying calls : 31 -//│ subtyping calls : 494 +//│ constrain calls : 49 +//│ annoying calls : 41 +//│ subtyping calls : 393 // ====== 3 ====== // @@ -148,19 +168,24 @@ foo arg //│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | {fC: 'fA} & #C & ~#B)) -> 'fA //│ arg: A[int] | B[int] | C[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.147: foo arg +//│ ║ l.167: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.166: def arg: A[int] | B[int] | C[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.167: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.142: | A -> x.fA +//│ ║ l.162: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.141: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.161: def foo x = case x of { //│ ╙── ^ -//│ res: error | int -//│ constrain calls : 76 -//│ annoying calls : 90 -//│ subtyping calls : 2989 +//│ res: error +//│ constrain calls : 129 +//│ annoying calls : 168 +//│ subtyping calls : 1445 // ====== 4 ====== // @@ -178,55 +203,64 @@ foo arg //│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | {fD: 'fA} & #D & ~#C))) -> 'fA //│ arg: A[int] | B[int] | C[int] | D[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.177: foo arg +//│ ║ l.202: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.201: def arg: A[int] | B[int] | C[int] | D[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.202: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.171: | A -> x.fA +//│ ║ l.196: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.170: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.195: def foo x = case x of { //│ ╙── ^ //│ res: error -//│ constrain calls : 94 -//│ annoying calls : 131 -//│ subtyping calls : 3984 +//│ constrain calls : 133 +//│ annoying calls : 168 +//│ subtyping calls : 1664 :stats :e foo (arg with { x = 1} with { y = 2 }) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.197: foo (arg with { x = 1} with { y = 2 }) +//│ ║ l.227: foo (arg with { x = 1} with { y = 2 }) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int, x: 1, y: 2} & ~#B | {fB: int, x: 1, y: 2} & ~?a | {fB: int, x: 1, y: 2} & #A)` does not have field 'fA' +//│ ╟── `with` extension of type `{fB: int, x: 1, y: 2} & #A & #B` does not have field 'fA' +//│ ║ l.227: foo (arg with { x = 1} with { y = 2 }) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.171: | A -> x.fA +//│ ║ l.196: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.170: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.195: def foo x = case x of { //│ ╙── ^ //│ res: error -//│ constrain calls : 69 -//│ annoying calls : 128 -//│ subtyping calls : 3450 +//│ constrain calls : 110 +//│ annoying calls : 166 +//│ subtyping calls : 1185 :stats :e foo (arg with { x = 1; y = 2; z = 3 }) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.215: foo (arg with { x = 1; y = 2; z = 3 }) +//│ ║ l.247: foo (arg with { x = 1; y = 2; z = 3 }) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int, x: 1, y: 2, z: 3} & ~#B | {fB: int, x: 1, y: 2, z: 3} & ~?a | {fB: int, x: 1, y: 2, z: 3} & #A)` does not have field 'fA' +//│ ╟── `with` extension of type `{fB: int, x: 1, y: 2, z: 3} & #A & #B` does not have field 'fA' +//│ ║ l.247: foo (arg with { x = 1; y = 2; z = 3 }) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.171: | A -> x.fA +//│ ║ l.196: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.170: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.195: def foo x = case x of { //│ ╙── ^ //│ res: error -//│ constrain calls : 69 -//│ annoying calls : 128 -//│ subtyping calls : 3450 +//│ constrain calls : 110 +//│ annoying calls : 166 +//│ subtyping calls : 1185 // ====== 5 ====== // @@ -245,19 +279,24 @@ foo arg //│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | {fE: 'fA} & #E & ~#D)))) -> 'fA //│ arg: A[int] | B[int] | C[int] | D[int] | E[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.244: foo arg +//│ ║ l.278: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.277: def arg: A[int] | B[int] | C[int] | D[int] | E[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.278: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.237: | A -> x.fA +//│ ║ l.271: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.236: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.270: def foo x = case x of { //│ ╙── ^ //│ res: error -//│ constrain calls : 98 -//│ annoying calls : 131 -//│ subtyping calls : 4272 +//│ constrain calls : 137 +//│ annoying calls : 168 +//│ subtyping calls : 1936 // ====== 6 ====== // @@ -277,19 +316,24 @@ foo arg //│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | ~#D & ({fE: 'fA} & #E | {fF: 'fA} & #F & ~#E))))) -> 'fA //│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.276: foo arg +//│ ║ l.315: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.314: def arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.315: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.268: | A -> x.fA +//│ ║ l.307: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.267: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.306: def foo x = case x of { //│ ╙── ^ //│ res: error -//│ constrain calls : 102 -//│ annoying calls : 131 -//│ subtyping calls : 4618 +//│ constrain calls : 141 +//│ annoying calls : 168 +//│ subtyping calls : 2266 // ====== 7 ====== // @@ -310,19 +354,24 @@ foo arg //│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | ~#D & ({fE: 'fA} & #E | ~#E & ({fF: 'fA} & #F | {fG: 'fA} & #G & ~#F)))))) -> 'fA //│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.309: foo arg +//│ ║ l.353: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.352: def arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.353: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.300: | A -> x.fA +//│ ║ l.344: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.299: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.343: def foo x = case x of { //│ ╙── ^ //│ res: error -//│ constrain calls : 106 -//│ annoying calls : 131 -//│ subtyping calls : 5027 +//│ constrain calls : 145 +//│ annoying calls : 168 +//│ subtyping calls : 2659 def foo_manual: ({fA: 'a} & a | {fB: 'a} & b & ~a | {fC: 'a} & c & ~a & ~b | {fD: 'a} & d & ~a & ~b & ~c | {fE: 'a} & e & ~a & ~b & ~c & ~d | {fF: 'a} & f & ~a & ~b & ~c & ~d & ~e | {fG: 'a} & g & ~a & ~b & ~c & ~d & ~e & ~f) -> 'a //│ foo_manual: ({fA: 'a} & #A | ~#A & ({fB: 'a} & #B | ~#B & ({fC: 'a} & #C | ~#C & ({fD: 'a} & #D | ~#D & ({fE: 'a} & #E | ~#E & ({fF: 'a} & #F | {fG: 'a} & #G & ~#F)))))) -> 'a @@ -331,16 +380,16 @@ def foo_manual: ({fA: 'a} & a | {fB: 'a} & b & ~a | {fC: 'a} & c & ~a & ~b | {fD :e foo_manual arg //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.332: foo_manual arg +//│ ║ l.381: foo_manual arg //│ ║ ^^^^^^^^^^^^^^ //│ ╟── type `{fB: int} & #B` does not match type `{fA: 'a} & #A | ~#A & ({fB: 'a} & #B | ~#B & ({fC: 'a} & #C | ~#C & ({fD: 'a} & #D | ~#D & ({fE: 'a} & #E | ~#E & ({fF: 'a} & #F | {fG: 'a} & #G & ~#F)))))` -//│ ║ l.308: def arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] +//│ ║ l.352: def arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] //│ ║ ^^^^^^ //│ ╟── but it flows into reference with expected type `{fA: 'a0} & #A | ~#A & ({fB: 'a0} & #B | ~#B & ({fC: 'a0} & #C | ~#C & ({fD: 'a0} & #D | ~#D & ({fE: 'a0} & #E | ~#E & ({fF: 'a0} & #F | {fG: 'a0} & #G & ~#F)))))` -//│ ║ l.332: foo_manual arg +//│ ║ l.381: foo_manual arg //│ ║ ^^^ //│ ╟── Note: constraint arises from union type: -//│ ║ l.327: def foo_manual: ({fA: 'a} & a | {fB: 'a} & b & ~a | {fC: 'a} & c & ~a & ~b | {fD: 'a} & d & ~a & ~b & ~c | {fE: 'a} & e & ~a & ~b & ~c & ~d | {fF: 'a} & f & ~a & ~b & ~c & ~d & ~e | {fG: 'a} & g & ~a & ~b & ~c & ~d & ~e & ~f) -> 'a +//│ ║ l.376: def foo_manual: ({fA: 'a} & a | {fB: 'a} & b & ~a | {fC: 'a} & c & ~a & ~b | {fD: 'a} & d & ~a & ~b & ~c | {fE: 'a} & e & ~a & ~b & ~c & ~d | {fF: 'a} & f & ~a & ~b & ~c & ~d & ~e | {fG: 'a} & g & ~a & ~b & ~c & ~d & ~e & ~f) -> 'a //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ res: error //│ constrain calls : 24 @@ -353,7 +402,7 @@ foo_manual = foo //│ <: foo_manual: //│ ({fA: 'a} & #A | ~#A & ({fB: 'a} & #B | ~#B & ({fC: 'a} & #C | ~#C & ({fD: 'a} & #D | ~#D & ({fE: 'a} & #E | ~#E & ({fF: 'a} & #F | {fG: 'a} & #G & ~#F)))))) -> 'a //│ constrain calls : 91 -//│ annoying calls : 183 +//│ annoying calls : 190 //│ subtyping calls : 3611 @@ -376,18 +425,23 @@ foo arg //│ foo: ({fA: 'fA} & #A | ~#A & ({fB: 'fA} & #B | ~#B & ({fC: 'fA} & #C | ~#C & ({fD: 'fA} & #D | ~#D & ({fE: 'fA} & #E | ~#E & ({fF: 'fA} & #F | ~#F & ({fG: 'fA} & #G | {fH: 'fA} & #H & ~#G))))))) -> 'fA //│ arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] | H[int] //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.375: foo arg +//│ ║ l.424: foo arg //│ ║ ^^^^^^^ -//│ ╟── expression of type `#B & ({fB: int} & ~#B | {fB: int} & ~?a | {fB: int} & #A)` does not have field 'fA' +//│ ╟── type `{fB: int} & #A & #B` does not have field 'fA' +//│ ║ l.423: def arg: A[int] | B[int] | C[int] | D[int] | E[int] | F[int] | G[int] | H[int] +//│ ║ ^^^^^^ +//│ ╟── but it flows into reference with expected type `{fA: ?fA}` +//│ ║ l.424: foo arg +//│ ║ ^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.365: | A -> x.fA +//│ ║ l.414: | A -> x.fA //│ ║ ^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.364: def foo x = case x of { +//│ ╟── from reference: +//│ ║ l.413: def foo x = case x of { //│ ╙── ^ //│ res: error -//│ constrain calls : 110 -//│ annoying calls : 131 -//│ subtyping calls : 5504 +//│ constrain calls : 149 +//│ annoying calls : 168 +//│ subtyping calls : 3120 diff --git a/shared/src/test/diff/mlscript/StressUgly.mls b/shared/src/test/diff/mlscript/StressUgly.mls index e5d4c5688c..ce9c8c9b06 100644 --- a/shared/src/test/diff/mlscript/StressUgly.mls +++ b/shared/src/test/diff/mlscript/StressUgly.mls @@ -44,7 +44,7 @@ eval1_ty = eval1_ty_ugly //│ ╙── ^^^ //│ = //│ eval1_ty_ugly is not implemented -//│ constrain calls : 49 -//│ annoying calls : 42 -//│ subtyping calls : 397 +//│ constrain calls : 46 +//│ annoying calls : 50 +//│ subtyping calls : 312 diff --git a/shared/src/test/diff/mlscript/Tony.mls b/shared/src/test/diff/mlscript/Tony.mls index b46f597427..f6a36854da 100644 --- a/shared/src/test/diff/mlscript/Tony.mls +++ b/shared/src/test/diff/mlscript/Tony.mls @@ -20,8 +20,8 @@ flatMap3 (fun x -> add x.value x.payload) arg //│ res: None | int //│ = 65 //│ constrain calls : 82 -//│ annoying calls : 23 -//│ subtyping calls : 350 +//│ annoying calls : 27 +//│ subtyping calls : 324 arg = if true then Some{value = 42} else None {} diff --git a/shared/src/test/diff/mlscript/TraitMatching.mls b/shared/src/test/diff/mlscript/TraitMatching.mls index 9604faa444..9ae5cb58bf 100644 --- a/shared/src/test/diff/mlscript/TraitMatching.mls +++ b/shared/src/test/diff/mlscript/TraitMatching.mls @@ -12,11 +12,13 @@ test1 1 //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.11: test1 1 //│ ║ ^^^^^^^ -//│ ╟── expression of type `1 & ~?a | 1 & #MyTrait` does not have field 'value' +//│ ╟── integer literal of type `1 & #MyTrait` does not have field 'value' +//│ ║ l.11: test1 1 +//│ ║ ^ //│ ╟── Note: constraint arises from field selection: //│ ║ l.6: def test1 x = case x of { MyTrait -> x.value | _ -> 0 } //│ ║ ^^^^^^^ -//│ ╟── from refined scrutinee: +//│ ╟── from reference: //│ ║ l.6: def test1 x = case x of { MyTrait -> x.value | _ -> 0 } //│ ╙── ^ //│ res: 0 | error @@ -49,11 +51,11 @@ def test2 x = case x of { MyTrait -> x.value | _ -> x.default } :e test2 1 //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.50: test2 1 +//│ ║ l.52: test2 1 //│ ║ ^^^^^^^ //│ ╟── expression of type `1 & ~#MyTrait` does not have field 'default' //│ ╟── Note: constraint arises from field selection: -//│ ║ l.45: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } +//│ ║ l.47: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } //│ ╙── ^^^^^^^^^ //│ res: error //│ = undefined @@ -61,11 +63,11 @@ test2 1 :e test2 { value = 1 } //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.62: test2 { value = 1 } +//│ ║ l.64: test2 { value = 1 } //│ ║ ^^^^^^^^^^^^^^^^^^^ //│ ╟── expression of type `{value: 1} & ~#MyTrait` does not have field 'default' //│ ╟── Note: constraint arises from field selection: -//│ ║ l.45: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } +//│ ║ l.47: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } //│ ╙── ^^^^^^^^^ //│ res: 1 | error //│ = undefined @@ -90,14 +92,16 @@ class C2: { default: string } :e test2 (C2 { default = "oops" }) //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.91: test2 (C2 { default = "oops" }) +//│ ║ l.93: test2 (C2 { default = "oops" }) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── expression of type `C2 & {default: ?default} & ~?a | C2 & {default: ?default} & #MyTrait` does not have field 'value' +//│ ╟── application of type `C2 & {default: ?default} & #MyTrait` does not have field 'value' +//│ ║ l.93: test2 (C2 { default = "oops" }) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.45: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } +//│ ║ l.47: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } //│ ║ ^^^^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.45: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } +//│ ╟── from reference: +//│ ║ l.47: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } //│ ╙── ^ //│ res: "oops" | error //│ = 'oops' @@ -110,14 +114,19 @@ c2 = C2 { value = 1; default = "oops" } :e test2 c2 //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.111: test2 c2 +//│ ║ l.115: test2 c2 //│ ║ ^^^^^^^^ -//│ ╟── expression of type `C2 & {default: ?default} & ~?a | C2 & {default: ?default} & #MyTrait` does not have field 'value' +//│ ╟── application of type `C2 & {default: ?default} & #MyTrait` does not have field 'value' +//│ ║ l.110: c2 = C2 { value = 1; default = "oops" } +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── but it flows into reference with expected type `{value: ?value}` +//│ ║ l.115: test2 c2 +//│ ║ ^^ //│ ╟── Note: constraint arises from field selection: -//│ ║ l.45: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } +//│ ║ l.47: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } //│ ║ ^^^^^^^ -//│ ╟── from refined scrutinee: -//│ ║ l.45: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } +//│ ╟── from reference: +//│ ║ l.47: def test2 x = case x of { MyTrait -> x.value | _ -> x.default } //│ ╙── ^ //│ res: "oops" | error //│ = 'oops' @@ -131,13 +140,13 @@ test2 (c2 with { value = 1 }) :e class C3: { default: string } & ~myTrait //│ ╔══[ERROR] cannot inherit from a type negation -//│ ║ l.132: class C3: { default: string } & ~myTrait +//│ ║ l.141: class C3: { default: string } & ~myTrait //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :e class C3: { default: string } & ~MyTrait[anything] //│ ╔══[ERROR] cannot inherit from a type negation -//│ ║ l.138: class C3: { default: string } & ~MyTrait[anything] +//│ ║ l.147: class C3: { default: string } & ~MyTrait[anything] //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ def strawman: C2 & ~MyTrait[anything] @@ -157,16 +166,16 @@ strawman: C2 :e strawman: ~{ value: anything } //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.158: strawman: ~{ value: anything } +//│ ║ l.167: strawman: ~{ value: anything } //│ ║ ^^^^^^^^ //│ ╟── type `C2 & ~MyTrait[?]` does not match type `~{value: anything}` -//│ ║ l.143: def strawman: C2 & ~MyTrait[anything] +//│ ║ l.152: def strawman: C2 & ~MyTrait[anything] //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── but it flows into reference with expected type `~{value: anything}` -//│ ║ l.158: strawman: ~{ value: anything } +//│ ║ l.167: strawman: ~{ value: anything } //│ ║ ^^^^^^^^ //│ ╟── Note: constraint arises from type negation: -//│ ║ l.158: strawman: ~{ value: anything } +//│ ║ l.167: strawman: ~{ value: anything } //│ ╙── ^^^^^^^^^^^^^^^^^^^^ //│ res: nothing //│ = diff --git a/shared/src/test/diff/mlscript/Trio.mls b/shared/src/test/diff/mlscript/Trio.mls index 4b6a9057c5..44bc2215e2 100644 --- a/shared/src/test/diff/mlscript/Trio.mls +++ b/shared/src/test/diff/mlscript/Trio.mls @@ -24,7 +24,7 @@ foo b //│ res: "test" //│ = 'test' //│ constrain calls : 22 -//│ annoying calls : 10 +//│ annoying calls : 11 //│ subtyping calls : 156 @@ -38,7 +38,7 @@ foo arg //│ = //│ arg is not implemented //│ constrain calls : 37 -//│ annoying calls : 30 +//│ annoying calls : 33 //│ subtyping calls : 342 :stats @@ -47,7 +47,7 @@ foo (arg with { fC = true }) //│ = //│ arg is not implemented //│ constrain calls : 30 -//│ annoying calls : 28 +//│ annoying calls : 31 //│ subtyping calls : 274 def foo x = case x of { @@ -80,7 +80,7 @@ foo arg //│ = //│ arg is not implemented //│ constrain calls : 48 -//│ annoying calls : 40 +//│ annoying calls : 43 //│ subtyping calls : 427 :stats @@ -89,6 +89,6 @@ foo (arg with { payload = 1 }) //│ = //│ arg is not implemented //│ constrain calls : 42 -//│ annoying calls : 38 +//│ annoying calls : 41 //│ subtyping calls : 330 diff --git a/shared/src/test/diff/mlscript/Variant-sub-ad-hoc.mls b/shared/src/test/diff/mlscript/Variant-sub-ad-hoc.mls index c010607a1c..5c99cebff8 100644 --- a/shared/src/test/diff/mlscript/Variant-sub-ad-hoc.mls +++ b/shared/src/test/diff/mlscript/Variant-sub-ad-hoc.mls @@ -51,15 +51,15 @@ rec def evalOpt = fun x -> case x of { //│ where //│ 'a <: Lit & {v: int} | Neg & {sub: 'a} | Plus & {lhs: 'a, rhs: 'a} | Var & {nme: string} //│ = [Function: evalOpt] -//│ constrain calls : 533 -//│ annoying calls : 156 -//│ subtyping calls : 3001 +//│ constrain calls : 563 +//│ annoying calls : 195 +//│ subtyping calls : 3442 :stats evalOpt (Plus{} with {lhs = Lit{} with {v=2}; rhs = Lit{} with {v=2}}) //│ res: None & {err: string} | Some & {v: int} //│ = Some { v: 4 } //│ constrain calls : 88 -//│ annoying calls : 34 -//│ subtyping calls : 653 +//│ annoying calls : 42 +//│ subtyping calls : 631 diff --git a/shared/src/test/diff/mlscript/Variant-sub.mls b/shared/src/test/diff/mlscript/Variant-sub.mls index f4275397f0..b1b5c6615f 100644 --- a/shared/src/test/diff/mlscript/Variant-sub.mls +++ b/shared/src/test/diff/mlscript/Variant-sub.mls @@ -79,7 +79,7 @@ rec def evalOpt x = case x of { //│ 'a <: Lit & {v: int} | (Neg with {sub: 'a}) | (Plus with {lhs: 'a, rhs: 'a}) | Var //│ = [Function: evalOpt] //│ constrain calls : 537 -//│ annoying calls : 105 +//│ annoying calls : 117 //│ subtyping calls : 3721 :stats @@ -87,5 +87,5 @@ evalOpt (Plus{lhs = Lit{v=2}; rhs = Lit{v=3}}) //│ res: NoneBecause | Some[int] //│ = Some { v: 5 } //│ constrain calls : 127 -//│ annoying calls : 37 +//│ annoying calls : 40 //│ subtyping calls : 959 diff --git a/shared/src/test/diff/mlscript/Yicong.mls b/shared/src/test/diff/mlscript/Yicong.mls index cde8120e9e..6bd2047b69 100644 --- a/shared/src/test/diff/mlscript/Yicong.mls +++ b/shared/src/test/diff/mlscript/Yicong.mls @@ -14,7 +14,7 @@ case r of { T1 -> r | _ -> 0 } // TODO also factor ClassTag-s like `2`: case r of { T1 -> r | T2 -> r } -//│ res: 1 & #T1 | 'a | #T2 & (2 & ~#T1 | 2 & ~#T2 | 2 & ~'a | 2 & #T1) +//│ res: 1 & #T1 | 'a | #T2 & (2 & ~#T1 | 2 & ~'a | 2 & #T1) //│ = [Number: 1] r = if true then T1 ((1,2,3)) else T2 ((3,4,5,4)) diff --git a/shared/src/test/diff/mlscript/Yuheng.mls b/shared/src/test/diff/mlscript/Yuheng.mls index 08e798b313..d1f2bb2ee3 100644 --- a/shared/src/test/diff/mlscript/Yuheng.mls +++ b/shared/src/test/diff/mlscript/Yuheng.mls @@ -327,7 +327,7 @@ rec def eval(e) = case e of //│ ║ ^^^^^^^^^^^^^^ //│ ║ l.+5: } //│ ║ ^^^ -//│ ╟── expression of type `Expr[?] & ~#IntLit & ~?a | Pair[?, ?]` does not have field 'rhs' +//│ ╟── expression of type `Pair[?, ?]` does not have field 'rhs' //│ ╟── Note: constraint arises from field selection: //│ ║ l.+3: | Pair -> (eval e.lhs, eval e.rhs) //│ ║ ^^^^^ diff --git a/shared/src/test/diff/nu/Andong.mls b/shared/src/test/diff/nu/Andong.mls index e2f1e77efc..f4ca165c64 100644 --- a/shared/src/test/diff/nu/Andong.mls +++ b/shared/src/test/diff/nu/Andong.mls @@ -6,10 +6,10 @@ class Union(a: Region, b: Region) fun hmm(x) = if x is Union(x, y) then x -//│ fun hmm: forall 'a. Union['a] -> 'a +//│ fun hmm: forall 'Region. Union['Region] -> (??Region & 'Region) fun hmm(x) = if x is Union(z, y) then x -//│ fun hmm: forall 'Region. Union['Region] -> Union['Region] +//│ fun hmm: forall 'Region. Union['Region] -> Union[??Region & 'Region] diff --git a/shared/src/test/diff/nu/ArrayProg.mls b/shared/src/test/diff/nu/ArrayProg.mls index 857ee4e3ac..2ec748b0dc 100644 --- a/shared/src/test/diff/nu/ArrayProg.mls +++ b/shared/src/test/diff/nu/ArrayProg.mls @@ -69,7 +69,7 @@ fun add(e) = Vectr of map of xs, x => add of Pair of x, Numbr(n) Pair(Numbr(n), Vectr(xs)) then Vectr of map of xs, x => add of Pair of Numbr(n), x -//│ fun add: Pair[Numbr | Vectr, Numbr | Vectr] -> (Numbr | Vectr) +//│ fun add: Pair[Numbr | Vectr | ~??A, Numbr | Vectr | ~??B] -> (Numbr | Vectr) add(Pair(Numbr(0), Numbr(1))) @@ -112,7 +112,7 @@ fun add2(e) = if e is Pair(Numbr(n), Numbr(m)) then Numbr(m + m) Pair(Numbr(n), Vectr(n)) then n -//│ fun add2: Pair[Numbr, Numbr | Vectr] -> (Numbr | Array[Numbr | Vectr]) +//│ fun add2: Pair[Numbr | ~??A, Numbr | Vectr | ~??B] -> (Numbr | Array[Numbr | Vectr]) add2(Pair(Numbr(0), Numbr(1))) //│ Numbr | Array[Numbr | Vectr] @@ -232,7 +232,7 @@ add2(Pair(Vectr(0), Numbr(1))) //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.+1: add2(Pair(Vectr(0), Numbr(1))) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── application of type `Vectr` is not an instance of type `Numbr` +//│ ╟── application of type `Vectr` does not match type `Numbr | ~??A` //│ ║ l.+1: add2(Pair(Vectr(0), Numbr(1))) //│ ║ ^^^^^^^^ //│ ╟── Note: constraint arises from class pattern: diff --git a/shared/src/test/diff/nu/AsOp.mls b/shared/src/test/diff/nu/AsOp.mls new file mode 100644 index 0000000000..da6f26644a --- /dev/null +++ b/shared/src/test/diff/nu/AsOp.mls @@ -0,0 +1,53 @@ +:NewDefs + +abstract class Foo[type T]: Bar | Baz +class Bar extends Foo[Int] +class Baz[T](val x: Foo[T]) extends Foo[[T]] +//│ abstract class Foo[T]: Bar | Baz[?] +//│ class Bar extends Foo { +//│ constructor() +//│ } +//│ class Baz[T](x: Foo[T]) extends Foo + +fun foo: Foo['T] -> Int +fun foo[T](f: Foo[T]): Int = if f is + Bar then 0 + Baz(x) then foo(x as Foo[x.T]) +//│ fun foo: forall 'T. (f: Foo['T]) -> Int +//│ fun foo: forall 'T0. Foo['T0] -> Int + +1 as Int +"hi" as Str +//│ Str +//│ res +//│ = 1 +//│ res +//│ = 'hi' + +:e +1 as 2 +"hello" as Int +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.28: 1 as 2 +//│ ║ ^ +//│ ╟── integer literal of type `1` does not match type `2` +//│ ╟── Note: constraint arises from literal type: +//│ ║ l.28: 1 as 2 +//│ ╙── ^ +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.29: "hello" as Int +//│ ║ ^^^^^^^ +//│ ╟── string literal of type `"hello"` is not an instance of type `Int` +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.29: "hello" as Int +//│ ╙── ^^^ +//│ Int +//│ res +//│ = 1 +//│ res +//│ = 'hello' + +0as Int +//│ Int +//│ res +//│ = 0 diff --git a/shared/src/test/diff/nu/BadClasses.mls b/shared/src/test/diff/nu/BadClasses.mls index 74ac645b04..78342e8c41 100644 --- a/shared/src/test/diff/nu/BadClasses.mls +++ b/shared/src/test/diff/nu/BadClasses.mls @@ -74,14 +74,13 @@ module Bar { type I = Int } //│ module Bar { -//│ type I = Int //│ fun hello: 0 //│ } :e hello //│ ╔══[ERROR] identifier not found: hello -//│ ║ l.82: hello +//│ ║ l.81: hello //│ ╙── ^^^^^ //│ error //│ Code generation encountered an error: @@ -90,7 +89,7 @@ hello :e 1 : I //│ ╔══[ERROR] type identifier not found: I -//│ ║ l.91: 1 : I +//│ ║ l.90: 1 : I //│ ╙── ^ //│ error //│ res @@ -101,20 +100,20 @@ hello :w class Foo[A] { 42: A } //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.102: class Foo[A] { 42: A } +//│ ║ l.101: class Foo[A] { 42: A } //│ ║ ^^ //│ ╟── integer literal of type `42` does not match type `A` //│ ╟── Note: constraint arises from type parameter: -//│ ║ l.102: class Foo[A] { 42: A } +//│ ║ l.101: class Foo[A] { 42: A } //│ ╙── ^ //│ ╔══[WARNING] Expression in statement position should have type `()`. //│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer. //│ ╟── Type mismatch in type ascription: -//│ ║ l.102: class Foo[A] { 42: A } +//│ ║ l.101: class Foo[A] { 42: A } //│ ║ ^^ //│ ╟── expression in statement position of type `A` does not match type `()` //│ ╟── Note: type parameter A is defined at: -//│ ║ l.102: class Foo[A] { 42: A } +//│ ║ l.101: class Foo[A] { 42: A } //│ ╙── ^ //│ class Foo[A] { //│ constructor() @@ -124,7 +123,7 @@ class Foo[A] { 42: A } :e class C1 { fun oops = this.x } //│ ╔══[ERROR] Type `#C1` does not contain member `x` -//│ ║ l.125: class C1 { fun oops = this.x } +//│ ║ l.124: class C1 { fun oops = this.x } //│ ╙── ^^ //│ class C1 { //│ constructor() @@ -135,10 +134,10 @@ class C1 { fun oops = this.x } :e class C { fun x: Int } //│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C` -//│ ║ l.136: class C { fun x: Int } +//│ ║ l.135: class C { fun x: Int } //│ ║ ^ //│ ╟── Declared here: -//│ ║ l.136: class C { fun x: Int } +//│ ║ l.135: class C { fun x: Int } //│ ╙── ^^^^^^^^^^ //│ class C { //│ constructor() @@ -148,10 +147,10 @@ class C { fun x: Int } :e class C { val x: Int } //│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `C` -//│ ║ l.149: class C { val x: Int } +//│ ║ l.148: class C { val x: Int } //│ ║ ^ //│ ╟── Declared here: -//│ ║ l.149: class C { val x: Int } +//│ ║ l.148: class C { val x: Int } //│ ╙── ^^^^^^^^^^ //│ class C { //│ constructor() diff --git a/shared/src/test/diff/nu/BasicClasses.mls b/shared/src/test/diff/nu/BasicClasses.mls index 7d85a1150f..2c5c836683 100644 --- a/shared/src/test/diff/nu/BasicClasses.mls +++ b/shared/src/test/diff/nu/BasicClasses.mls @@ -204,7 +204,74 @@ r.n //│ res //│ = 0 +:d r.go.n +//│ 0. Typing TypingUnit(List(Sel(Sel(Var(r),Var(go)),Var(n)))) +//│ | Typing unit statements +//│ | | 0. Typing term ((r).go).n +//│ | | | 0. Typing term (r).go +//│ | | | | 0. Typing term r +//│ | | | | 0. : α183 +//│ | | | | CONSTRAIN α183 Rec <: {n: n185} & r184 +//│ r184 :> Rec +//│ n185 :> Int +//│ | | | | 0. C α183 {}) {} <: DNF(0, {go: go188}) +//│ | | | | | | | | | Possible: List({go: go188}) +//│ | | | | | | | | | 0. A #Rec{} % List() {} % List() {} % List() Rec <: go181'' +//│ go181'' :> Rec +//│ | | | | | | | | | | | | | Fresh[0] Rec.go : Some(‹∀ 1. α180''›) where Some( +//│ α180'' :> Rec <: go181'' +//│ go181'' :> Rec) +//│ | | | | | | | | | | | | | & None (from refinement) +//│ | | | | | | | | | | | | 0. C ‹∀ 1. α180''› Rec <: go181'' +//│ go181'' :> Rec +//│ go188 :> ‹∀ 1. α180''› +//│ | | | 0. C go188 {}) {} <: DNF(0, {n: n189}) +//│ | | | | | | | | | | Possible: List({n: n189}) +//│ | | | | | | | | | | 0. A #Rec{} % List() {} % List() {} % List() Int //│ Int //│ res //│ = 1 @@ -220,13 +287,13 @@ class Annots(base: 0 | 1) { //│ ╔══[WARNING] Expression in statement position should have type `()`. //│ ╟── Use a comma expression `... , ()` to explicitly discard non-unit values, making your intent clearer. //│ ╟── Type mismatch in type ascription: -//│ ║ l.217: a: Int +//│ ║ l.284: a: Int //│ ║ ^ //│ ╟── type `Int` does not match type `()` -//│ ║ l.217: a: Int +//│ ║ l.284: a: Int //│ ║ ^^^ //│ ╟── but it flows into expression in statement position with expected type `()` -//│ ║ l.217: a: Int +//│ ║ l.284: a: Int //│ ╙── ^ //│ class Annots(base: 0 | 1) { //│ fun a: 0 | 1 diff --git a/shared/src/test/diff/nu/CaseExpr.mls b/shared/src/test/diff/nu/CaseExpr.mls index 5b317fe937..d067c073ac 100644 --- a/shared/src/test/diff/nu/CaseExpr.mls +++ b/shared/src/test/diff/nu/CaseExpr.mls @@ -46,7 +46,7 @@ module None extends Option[nothing] fun map(f) = case Some(x) then Some(f(x)) None then None -//│ fun map: forall 'a 'A. ('a -> 'A) -> (None | Some['a]) -> (None | Some['A]) +//│ fun map: forall 'A 'a. ((??A & 'A) -> 'a) -> (None | Some['A]) -> (None | Some['a]) map(succ) of Some of 123 //│ None | Some[Int] @@ -59,13 +59,20 @@ map(succ) of None //│ = None { class: [class None extends Option] } -:e // TODO support +// :pe // TODO support +// :e +// :w + +// TODO :: here `as` is used as @ fun map(f) = case Some(x) then Some(f(x)) None as n then n -//│ ╔══[ERROR] Illegal pattern `as` -//│ ║ l.65: None as n then n -//│ ╙── ^^ +//│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead +//│ ║ l.69: None as n then n +//│ ╙── ^^^^^^^^ +//│ ╔══[ERROR] Illegal interleaved statement Asc(Var(None),Literal(UnitLit(true))) +//│ ║ l.69: None as n then n +//│ ╙── ^^^^ //│ fun map: anything -> anything -> error //│ Code generation encountered an error: //│ if expression was not desugared @@ -74,10 +81,10 @@ fun map(f) = case :pe case 1 //│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'case'; found integer literal instead -//│ ║ l.75: case 1 +//│ ║ l.82: case 1 //│ ║ ^ //│ ╟── Note: 'case' expression starts here: -//│ ║ l.75: case 1 +//│ ║ l.82: case 1 //│ ╙── ^^^^ //│ anything -> 1 //│ res @@ -86,13 +93,13 @@ case 1 :pe case (1 then true) //│ ╔══[PARSE ERROR] Unexpected 'then' keyword here -//│ ║ l.87: case (1 then true) +//│ ║ l.94: case (1 then true) //│ ╙── ^^^^ //│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'case'; found integer literal instead -//│ ║ l.87: case (1 then true) +//│ ║ l.94: case (1 then true) //│ ║ ^^^^^^^^^^^^^ //│ ╟── Note: 'case' expression starts here: -//│ ║ l.87: case (1 then true) +//│ ║ l.94: case (1 then true) //│ ╙── ^^^^ //│ anything -> 1 //│ res @@ -106,16 +113,16 @@ case else 0 :pe case then 1 else 0 //│ ╔══[PARSE ERROR] Unexpected 'then' keyword in expression position -//│ ║ l.107: case then 1 else 0 +//│ ║ l.114: case then 1 else 0 //│ ╙── ^^^^ //│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'case'; found integer literal instead -//│ ║ l.107: case then 1 else 0 +//│ ║ l.114: case then 1 else 0 //│ ║ ^ //│ ╟── Note: 'case' expression starts here: -//│ ║ l.107: case then 1 else 0 +//│ ║ l.114: case then 1 else 0 //│ ╙── ^^^^ //│ ╔══[PARSE ERROR] Expected end of input; found 'else' keyword instead -//│ ║ l.107: case then 1 else 0 +//│ ║ l.114: case then 1 else 0 //│ ╙── ^^^^ //│ anything -> 1 //│ res @@ -129,16 +136,16 @@ case then 1 else 0 :e case x, y then x + y //│ ╔══[PARSE ERROR] Expected an expression; found a 'then'/'else' clause instead -//│ ║ l.130: case x, y then x + y +//│ ║ l.137: case x, y then x + y //│ ╙── ^^^^^^^^^^^^ //│ ╔══[PARSE ERROR] Expected 'then'/'else' clause after 'case'; found operator application instead -//│ ║ l.130: case x, y then x + y +//│ ║ l.137: case x, y then x + y //│ ║ ^^^^^^^^^^^^^^^ //│ ╟── Note: 'case' expression starts here: -//│ ║ l.130: case x, y then x + y +//│ ║ l.137: case x, y then x + y //│ ╙── ^^^^ //│ ╔══[ERROR] identifier not found: x -//│ ║ l.130: case x, y then x + y +//│ ║ l.137: case x, y then x + y //│ ╙── ^ //│ anything -> () //│ Code generation encountered an error: @@ -147,7 +154,7 @@ case x, y then x + y :e case (x, y) then x + y //│ ╔══[ERROR] Illegal pattern `,` -//│ ║ l.148: case (x, y) then x + y +//│ ║ l.155: case (x, y) then x + y //│ ╙── ^^^^ //│ anything -> error //│ Code generation encountered an error: diff --git a/shared/src/test/diff/nu/ClassesInMixins.mls b/shared/src/test/diff/nu/ClassesInMixins.mls index ca2f3c647f..99644eff94 100644 --- a/shared/src/test/diff/nu/ClassesInMixins.mls +++ b/shared/src/test/diff/nu/ClassesInMixins.mls @@ -29,7 +29,7 @@ M.f.n :e M.Foo -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member Foo not yet supported //│ ║ l.31: M.Foo //│ ╙── ^^^^ //│ error @@ -82,19 +82,14 @@ mixin Test { fun size(x) = if x is Add(l, r) then this.size(l) + this.size(r) } -//│ ╔══[ERROR] Type error in application -//│ ║ l.80: fun cached = size(this) -//│ ║ ^^^^^^^^^^ -//│ ╟── type variable `A` leaks out of its scope -//│ ║ l.78: class Add(lhs: A, rhs: A) { -//│ ╙── ^ //│ mixin Test() { -//│ this: {size: anything -> Int} +//│ this: {size: ??A -> Int} //│ class Add[A](lhs: A, rhs: A) { -//│ fun cached: Int | error +//│ fun cached: Int //│ } //│ class Lit(n: Int) -//│ fun size: Add[??A & 'a] -> Int +//│ fun size: Add['A] -> Int //│ } +//│ TEST CASE FAILURE: There was an unexpected lack of type error diff --git a/shared/src/test/diff/nu/CommaOperator.mls b/shared/src/test/diff/nu/CommaOperator.mls index 6d7e46db0b..8647f9d57b 100644 --- a/shared/src/test/diff/nu/CommaOperator.mls +++ b/shared/src/test/diff/nu/CommaOperator.mls @@ -382,7 +382,7 @@ foo(if true then 1 else 2, 3) //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.381: foo(if true then 1 else 2, 3) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── argument of type `[1 | ?a]` does not match type `[?b, ?c]` +//│ ╟── argument of type `[?a | ?b]` does not match type `[?c, ?d]` //│ ║ l.381: foo(if true then 1 else 2, 3) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from tuple literal: diff --git a/shared/src/test/diff/nu/Eval.mls b/shared/src/test/diff/nu/Eval.mls index 7f3886971e..c4b58e223a 100644 --- a/shared/src/test/diff/nu/Eval.mls +++ b/shared/src/test/diff/nu/Eval.mls @@ -113,7 +113,7 @@ fun (:::) concatList(xs, ys) = if xs is Nil then ys Cons(x, xs) then x :: xs ::: ys //│ fun (::) cons: forall 'A. ('A, List['A]) -> Cons['A] -//│ fun (:::) concatList: forall 'A0 'a. (Cons['A0] | Nil, List['A0] & 'a) -> (Cons['A0] | 'a) +//│ fun (:::) concatList: forall 'A0 'A1 'a. (Cons['A0] | Nil, List['A1] & 'a) -> (Cons[??A & 'A0 | 'A1] | 'a) module Lists { // TODO use name List when module overloading is supported: @@ -136,9 +136,9 @@ module Lists { // TODO use name List when module overloading is supported: } //│ module Lists { -//│ fun assoc: forall 'a 'A. 'a -> (Cons[{key: Eql['a], value: 'A}] | Nil) -> (None | Some['A]) -//│ fun map: forall 'b 'A0. ('b -> 'A0) -> (Cons['b] | Nil) -> (Cons['A0] | Nil) -//│ fun zip: forall 'c 'd. (Cons['c] | Nil, Cons['d] | Nil) -> (Cons[['c, 'd]] | Nil) +//│ fun assoc: forall 'a 'value. 'a -> (Cons[{key: Eql['a], value: 'value} | ~??A] | Nil) -> (None | Some['value]) +//│ fun map: forall 'A 'A0. ((??A0 & 'A) -> 'A0) -> (Cons['A] | Nil) -> (Cons['A0] | Nil) +//│ fun zip: forall 'A1 'A2. (Cons['A1] | Nil, Cons['A2] | Nil) -> (Cons[[??A1 & 'A1, ??A2 & 'A2]] | Nil) //│ } let xs = 1 :: 2 :: 3 :: Nil @@ -260,12 +260,14 @@ fun eval(t, env) = if t is else err(String(pree) ++ " does not have field " ++ nme) Rcd(fs) then Rcd of fs |> Lists.map of {key, value} => {key, value: eval(value, env)} -//│ fun eval: forall 'a 'b 'c. ('a, Cons[{key: Eql[Str], value: 'b}] & {List#A <: {key: Eql[Str], value: 'b}} & List[{key: Eql[Str], value: 'b}] | Nil & {List#A <: {key: Eql[Str], value: 'b}} & List[{key: Eql[Str], value: 'b}]) -> 'c +//│ fun eval: forall 'Sub 'value 'a 'Sub0. (App | Lam | Lit[anything] | Rcd['Sub] | Sel | Var, Cons[{key: Eql[Str], value: 'value} | ~??A] & {List#A <: {key: Eql[Str], value: 'value} | ~??A} & List[{key: Eql[Str], value: 'value} | ~??A] | Nil & {List#A <: {key: Eql[Str], value: 'value} | ~??A} & List[{key: Eql[Str], value: 'value} | ~??A]) -> 'a //│ where -//│ 'b :> 'c -//│ <: Object & ~#Rcd | Rcd['b] -//│ 'c :> Lam | Lit[??A] | Rcd[Lam | Lit[??A] | 'c] | 'b -//│ 'a <: App | Lam | Lit[anything] | Rcd['a] | Sel | Var +//│ 'value :> ??A0 & 'a +//│ <: Lam | Object & ~#Lam & ~#Rcd | Rcd['Sub0] | ~??A1 +//│ 'a :> Lam | Lit[??A2] | Rcd[Lam | Lit[??A2] | 'a] | ??A1 & 'value | ??Sub & ??A3 & 'Sub0 +//│ 'Sub0 :> Lam | Lit[??A2] | 'a +//│ <: Lam | Object & ~#Lam & ~#Rcd | Rcd['Sub0] | ~(??Sub & ??A3) +//│ 'Sub <: App | Lam | Lit[anything] | Rcd['Sub] | Sel | Var | ~??Sub0 eval : (Term, List[{key: Str, value: Value}]) -> Value //│ (Term, List[{key: Str, value: Value}]) -> Value @@ -278,23 +280,23 @@ let rcd = Rcd({key: "a", value: IntLit(0)} :: Nil) //│ = Rcd {} eval of rcd, Nil -//│ 'a +//│ Lam | Lit[??A] | 'a //│ where -//│ 'a :> Lam | Lit[anything] | Rcd[Lam | Lit[anything] | 'a] +//│ 'a :> Lam | Lit[??A] | Rcd[Lam | Lit[??A] | 'a] | ??A0 & ??A1 & (Lam | Lit[??A]) //│ res //│ = Rcd {} eval of Sel(rcd, "a"), Nil -//│ 'a +//│ Lam | Lit[??A & ??A0] | 'a //│ where -//│ 'a :> Lam | Lit[??A] | Rcd[Lam | Lit[??A] | 'a] +//│ 'a :> Lam | Lit[??A & ??A0] | Rcd[Lam | Lit[??A & ??A0] | 'a] | ??A1 & ??A2 & (Lam | Lit[??A & ??A0]) //│ res //│ = IntLit {} eval of App(Lam("x" :: Nil, Sel(Var("x"), "a")), rcd :: Nil), Nil -//│ 'a +//│ Lam | Lit[??A & ??A0] | 'a //│ where -//│ 'a :> Lam | Lit[??A] | Rcd[Lam | Lit[??A] | 'a] +//│ 'a :> Lam | Lit[??A & ??A0] | Rcd[Lam | Lit[??A & ??A0] | 'a] | ??A1 & ??A2 & (Lam | Lit[??A & ??A0]) //│ res //│ = IntLit {} diff --git a/shared/src/test/diff/nu/EvalNegNeg.mls b/shared/src/test/diff/nu/EvalNegNeg.mls index b97bdb2ae6..18ddd7b046 100644 --- a/shared/src/test/diff/nu/EvalNegNeg.mls +++ b/shared/src/test/diff/nu/EvalNegNeg.mls @@ -14,8 +14,8 @@ mixin EvalBase { Add(l, r) then this.eval(l) + this.eval(r) } //│ mixin EvalBase() { -//│ this: {eval: 'a -> Int} -//│ fun eval: (Add['a] | Lit) -> Int +//│ this: {eval: (??E & 'E) -> Int} +//│ fun eval: (Add['E] | Lit) -> Int //│ } @@ -30,8 +30,8 @@ mixin EvalNeg { } //│ mixin EvalNeg() { //│ super: {eval: 'a -> 'b} -//│ this: {eval: 'c -> Int} -//│ fun eval: (Neg['c] | Object & 'a & ~#Neg) -> (Int | 'b) +//│ this: {eval: (??A & 'A) -> Int} +//│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> (Int | 'b) //│ } @@ -41,9 +41,9 @@ mixin EvalNegNeg { else super.eval(e) } //│ mixin EvalNegNeg() { -//│ super: {eval: (Neg[nothing] | 'a) -> 'b} -//│ this: {eval: 'c -> 'b} -//│ fun eval: (Neg[Neg['c] | Object & ~#Neg] | Object & 'a & ~#Neg) -> 'b +//│ super: {eval: (Neg[??A & 'A] | 'a) -> 'b} +//│ this: {eval: (??A0 & 'A0) -> 'b} +//│ fun eval: (Neg['A & (Neg['A0] | Object & ~#Neg | ~??A)] | Object & 'a & ~#Neg) -> 'b //│ } @@ -52,9 +52,8 @@ module TestLang extends EvalBase, EvalNeg, EvalNegNeg //│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int //│ } //│ where -//│ 'A <: 'b & (Neg['b] | Object & ~#Neg) -//│ 'b <: Neg['A] | Object & 'a & ~#Neg -//│ 'a <: Add['b] | Lit | Neg['b] +//│ 'A <: Neg['A] & ~#Neg | Neg['A & (Neg['A] | Object & 'a & ~#Neg | ~??A)] | Object & 'a & ~#Neg | ~??A0 +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit | Neg[Neg['A] | Object & 'a & ~#Neg | ~??A1] fun mk(n) = if n is diff --git a/shared/src/test/diff/nu/ExpressionProblem_repro.mls b/shared/src/test/diff/nu/ExpressionProblem_repro.mls index 70a8a32ed0..80c513f964 100644 --- a/shared/src/test/diff/nu/ExpressionProblem_repro.mls +++ b/shared/src/test/diff/nu/ExpressionProblem_repro.mls @@ -6,9 +6,9 @@ class Add0(lhs: E) //│ class Add0[E](lhs: E) fun eval(e) = if e is Add0(l) then eval(l) -//│ fun eval: forall 'a. 'a -> nothing +//│ fun eval: forall 'E. Add0['E] -> nothing //│ where -//│ 'a <: Add0['a] +//│ 'E <: Add0['E] | ~??E class Add(lhs: E, rhs: E) @@ -23,9 +23,9 @@ fun eval(e) = if e is Lit(n) then n: Int Add(l, r) then eval(l) + eval(r) -//│ fun eval: forall 'a. 'a -> Int +//│ fun eval: forall 'E. (Add['E] | Lit) -> Int //│ where -//│ 'a <: Add['a] | Lit +//│ 'E <: Add['E] | Lit | ~??E mixin EvalLit { @@ -51,21 +51,21 @@ mixin EvalAdd { Add(l, r) then this.eval(l) } //│ mixin EvalAdd() { -//│ this: {eval: 'a -> 'b} -//│ fun eval: Add['a] -> 'b +//│ this: {eval: (??E & 'E) -> 'a} +//│ fun eval: Add['E] -> 'a //│ } module TestLang extends EvalAdd //│ module TestLang { -//│ fun eval: 'a -> nothing +//│ fun eval: Add['E] -> nothing //│ } //│ where -//│ 'a <: Add['a] +//│ 'E <: Add['E] | ~??E TestLang.eval -//│ 'a -> nothing +//│ Add['E] -> nothing //│ where -//│ 'a <: Add['a] +//│ 'E <: Add['E] | ~??E @@ -76,22 +76,22 @@ mixin EvalBase { Add(l, r) then this.eval(l) + this.eval(r) } //│ mixin EvalBase() { -//│ this: {eval: 'a -> Int} -//│ fun eval: (Add['a] | Lit) -> Int +//│ this: {eval: (??E & 'E) -> Int} +//│ fun eval: (Add['E] | Lit) -> Int //│ } module TestLang extends EvalBase //│ module TestLang { -//│ fun eval: 'a -> Int +//│ fun eval: (Add['E] | Lit) -> Int //│ } //│ where -//│ 'a <: Add['a] | Lit +//│ 'E <: Add['E] | Lit | ~??E TestLang.eval -//│ 'a -> Int +//│ (Add['E] | Lit) -> Int //│ where -//│ 'a <: Add['a] | Lit +//│ 'E <: Add['E] | Lit | ~??E @@ -126,22 +126,24 @@ mixin EvalNeg { } //│ mixin EvalNeg() { //│ super: {eval: 'a -> 'b} -//│ this: {eval: 'c -> Int} -//│ fun eval: (Neg['c] | Object & 'a & ~#Neg) -> (Int | 'b) +//│ this: {eval: (??A & 'A) -> Int} +//│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> (Int | 'b) //│ } module TestLang extends EvalBase, EvalNeg //│ module TestLang { -//│ fun eval: 'a -> Int +//│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int //│ } //│ where -//│ 'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg +//│ 'A <: Neg['A] | Object & 'a & ~#Neg | ~??A +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit TestLang.eval -//│ 'a -> Int +//│ (Neg['A] | Object & 'a & ~#Neg) -> Int //│ where -//│ 'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg +//│ 'A <: Neg['A] | Object & 'a & ~#Neg | ~??A +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit TestLang.eval(add11) diff --git a/shared/src/test/diff/nu/ExpressionProblem_small.mls b/shared/src/test/diff/nu/ExpressionProblem_small.mls index 128c1eee71..3823d82525 100644 --- a/shared/src/test/diff/nu/ExpressionProblem_small.mls +++ b/shared/src/test/diff/nu/ExpressionProblem_small.mls @@ -34,25 +34,27 @@ mixin EvalNeg { //│ } //│ mixin EvalAddLit() { //│ super: {eval: 'a -> 'b} -//│ this: {eval: 'c -> Int} -//│ fun eval: (Add['c] | Lit | Object & 'a & ~#Add & ~#Lit) -> (Int | 'b) +//│ this: {eval: (??E & 'E) -> Int} +//│ fun eval: (Add['E] | Lit | Object & 'a & ~#Add & ~#Lit) -> (Int | 'b) //│ } //│ mixin EvalNeg() { -//│ super: {eval: 'd -> 'e} -//│ this: {eval: 'f -> Int} -//│ fun eval: (Neg['f] | Object & 'd & ~#Neg) -> (Int | 'e) +//│ super: {eval: 'c -> 'd} +//│ this: {eval: (??A & 'A) -> Int} +//│ fun eval: (Neg['A] | Object & 'c & ~#Neg) -> (Int | 'd) //│ } module TestLang extends EvalNothing, EvalAddLit, EvalNeg //│ module TestLang { -//│ fun eval: 'a -> Int +//│ fun eval: (Neg['A] | Object & 'a & ~#Neg) -> Int //│ } //│ where -//│ 'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg +//│ 'A <: Neg['A] | Object & 'a & ~#Neg | ~??A +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit TestLang.eval -//│ 'a -> Int +//│ (Neg['A] | Object & 'a & ~#Neg) -> Int //│ where -//│ 'a <: Neg['a] | Object & (Add['a] | Lit) & ~#Neg +//│ 'A <: Neg['A] | Object & 'a & ~#Neg | ~??A +//│ 'a <: Add[Neg['A] | Object & 'a & ~#Neg | ~??E] | Lit diff --git a/shared/src/test/diff/nu/FilterMap.mls b/shared/src/test/diff/nu/FilterMap.mls index 421fe34c4a..045af68f91 100644 --- a/shared/src/test/diff/nu/FilterMap.mls +++ b/shared/src/test/diff/nu/FilterMap.mls @@ -30,7 +30,7 @@ fun filtermap(f, xs) = if xs is [true, z] then Cons(y, filtermap(f, ys)) //│ ╔══[ERROR] type identifier not found: Tuple#2 //│ ╙── -//│ fun filtermap: ((Cons[nothing] | Nil) -> nothing, Cons[anything] | Nil) -> (Cons[nothing] | Nil | error) +//│ fun filtermap: forall 'A. ((Cons[??A & 'A] | Nil) -> nothing, Cons['A] | Nil) -> (Cons[??A & 'A] | Nil | error) //│ Code generation encountered an error: //│ unknown match case: Tuple#2 @@ -49,7 +49,7 @@ fun filtermap(f, xs) = if xs is Tru then filtermap(f, ys) Fals then Cons(y, filtermap(f, ys)) Pair(Tru, z) then Cons(z, filtermap(f, ys)) -//│ fun filtermap: forall 'a 'A. ('a -> (Fals | Pair[Tru, 'A] | Tru), Cons['a & 'A] | Nil) -> (Cons['A] | Nil) +//│ fun filtermap: forall 'A 'B. ((??A & 'A) -> (Fals | Pair[Tru | ~??A0, 'B] | Tru), Cons['A] | Nil) -> (Cons[??B & 'B | ??A & 'A] | Nil) fun mkString(xs) = if xs is diff --git a/shared/src/test/diff/nu/FunnyPoly.mls b/shared/src/test/diff/nu/FunnyPoly.mls index 21d6cbe464..fc66880d0b 100644 --- a/shared/src/test/diff/nu/FunnyPoly.mls +++ b/shared/src/test/diff/nu/FunnyPoly.mls @@ -26,7 +26,7 @@ fun test(x: Id & 'b) = fun test(x: Int | 'b) = let foo(y) = (if true then x else y) : (Int | 'c) foo -//│ fun test: forall 'c. (x: Int | 'c) -> (forall 'c0. (Int | 'c0) -> (Int | 'c | 'c0)) +//│ fun test: forall 'b. (x: Int | 'b) -> (forall 'c. (Int | 'c) -> (Int | 'b & ~Int | 'c)) @@ -77,27 +77,25 @@ fun test(x, y) = let tmp = mk(x, y) let foo(z) = mk(z, tmp) : MyClass['x] foo -//│ fun test: forall 'a 'b 'b0 'a0 'a1 'a2 'x. (Ref['a], Ref['b]) -> (forall 'a3 'x0. Ref['a3] -> MyClass['x0]) +//│ fun test: forall 'a 'b 'b0 'x 'x0 'a0 'a1. (Ref['a], Ref['b]) -> (forall 'a2 'x1. Ref['a2] -> MyClass['x1]) //│ where -//│ 'x0 <: 'x -//│ 'a3 :> 'a2 | 'a1 -//│ <: 'a0 -//│ 'b <: Ref[?] | Ref[?] & ~{MyClass#A = 'a} | Ref[in 'b0 out 'b0 & (MyClass[?] & ~{MyClass#A :> 'a0 & 'a1} | MyClass[in 'x out nothing] | {MyClass#A :> 'x <: nothing} & ~{MyClass#A :> 'a2 <: 'a2 | 'a0} | ~#MyClass | ~{MyClass#A :> 'a2 & 'a0 & 'a1})] & { -//│ Ref#T :> 'b0 <: 'b0 & (MyClass[?] & ~{MyClass#A :> 'a0 & 'a1 <: 'a2 | 'a1} | MyClass[in 'x out nothing] | {MyClass#A = 'x} & ~{MyClass#A :> 'a2 <: 'a2 | 'a0} | ~#MyClass | ~{MyClass#A :> 'a2 & 'a0 & 'a1 <: 'a2 | 'a0 | 'a1}) -//│ } | ~MyClass['a] +//│ 'x1 :> 'x0 +//│ <: 'x +//│ 'a2 :> 'a0 +//│ <: 'a1 +//│ 'b <: Ref[?] | Ref[?] & ~{MyClass#A = 'a} | Ref[in 'b0 out 'b0 & (MyClass[in 'x out 'x & 'x0] | ~{MyClass#A :> 'a0 <: 'a0 | 'a1} | ~#MyClass)] | ~MyClass['a] fun test(x, y) = let tmp = mk(x, y) let foo(z) = mk(z, tmp) : MyClass['x] [tmp, foo] -//│ fun test: forall 'a 'b 'b0 'a0 'a1 'a2 'x. (Ref['a], Ref['b]) -> [MyClass['a] & 'b, forall 'a3 'x0. Ref['a3] -> MyClass['x0]] +//│ fun test: forall 'a 'b 'b0 'x 'x0 'a0 'a1. (Ref['a], Ref['b]) -> [MyClass['a] & 'b, forall 'a2 'x1. Ref['a2] -> MyClass['x1]] //│ where -//│ 'x0 <: 'x -//│ 'a3 :> 'a2 | 'a1 -//│ <: 'a0 -//│ 'b <: Ref[?] | Ref[?] & ~{MyClass#A = 'a} | Ref[in 'b0 out 'b0 & (MyClass[?] & ~{MyClass#A :> 'a0 & 'a1} | MyClass[in 'x out nothing] | {MyClass#A :> 'x <: nothing} & ~{MyClass#A :> 'a2 <: 'a2 | 'a0} | ~#MyClass | ~{MyClass#A :> 'a2 & 'a0 & 'a1})] & { -//│ Ref#T :> 'b0 <: 'b0 & (MyClass[?] & ~{MyClass#A :> 'a0 & 'a1 <: 'a2 | 'a1} | MyClass[in 'x out nothing] | {MyClass#A = 'x} & ~{MyClass#A :> 'a2 <: 'a2 | 'a0} | ~#MyClass | ~{MyClass#A :> 'a2 & 'a0 & 'a1 <: 'a2 | 'a0 | 'a1}) -//│ } | ~MyClass['a] +//│ 'x1 :> 'x0 +//│ <: 'x +//│ 'a2 :> 'a0 +//│ <: 'a1 +//│ 'b <: Ref[?] | Ref[?] & ~{MyClass#A = 'a} | Ref[in 'b0 out 'b0 & (MyClass[in 'x out 'x & 'x0] | ~{MyClass#A :> 'a0 <: 'a0 | 'a1} | ~#MyClass)] | ~MyClass['a] @@ -114,13 +112,13 @@ fun test(x, y) = let tmp = ref(mk(x, y)) let foo(z) = mk(z, tmp) : MyClass['x] foo -//│ fun test: forall 'a 'b 'a0 'a1 'a2 'a3 'x 'x0. (Ref['a], Ref['b]) -> (forall 'a4 'x1. Ref['a4] -> MyClass['x1]) +//│ fun test: forall 'a 'b 'x 'x0 'a0 'a1. (Ref['a], Ref['b]) -> (forall 'a2 'x1. Ref['a2] -> MyClass['x1]) //│ where //│ 'x1 :> 'x0 //│ <: 'x -//│ 'a4 :> 'a2 | 'a1 -//│ <: 'a0 & 'a3 -//│ 'b <: MyClass[?] & ~{MyClass#A :> 'a0 & 'a1 | 'a <: 'a & ('a2 | 'a1 | 'a3)} | MyClass[in 'x out 'x & 'x0] | {MyClass#A :> 'x <: 'x & 'x0} & ~{MyClass#A :> 'a2 | 'a <: 'a & ('a2 | 'a0)} | ~MyClass[in 'a | 'a2 & ('a0 & 'a1 | 'a) out 'a & ('a2 | 'a0 | 'a1 | 'a3)] +//│ 'a2 :> 'a0 +//│ <: 'a1 +//│ 'b <: MyClass[in 'x out 'x & 'x0] | ~MyClass[in 'a0 | 'a out 'a & ('a0 | 'a1)] @@ -144,9 +142,7 @@ fun test(x: 'x) = fun test(x: 'x) = let foo(y) = refined(x, y) : Ref['r] foo -//│ fun test: forall 'B 'r. (x: Ref[?] & ~'B | Ref[in 'r out nothing] | ~'B) -> (forall 'r0. 'B -> Ref['r0]) -//│ where -//│ 'r0 <: 'r +//│ fun test: forall 'x. (x: 'x) -> (forall 'r. (Ref['r] | ~'x) -> Ref['r]) diff --git a/shared/src/test/diff/nu/GADTMono.mls b/shared/src/test/diff/nu/GADTMono.mls index 0d8323d5fb..de912acdf0 100644 --- a/shared/src/test/diff/nu/GADTMono.mls +++ b/shared/src/test/diff/nu/GADTMono.mls @@ -1,124 +1,39 @@ :NewDefs -trait Expr[A]: LitInt | LitBool | Add | Cond | Pair | Fst | Snd -class LitInt(n: Int) extends Expr[Int] -class LitBool(b: Bool) extends Expr[Bool] -class Add(x: Expr[Int], y: Expr[Int]) extends Expr[Int] -class Cond[T](p: Expr[Bool], t: Expr[T], e: Expr[T]) extends Expr[T] -class Pair[S, T](a: Expr[S], b: Expr[T]) extends Expr[[S, T]] -class Fst[S, T](p: Expr[[S, T]]) extends Expr[S] -class Snd[S, T](p: Expr[[S, T]]) extends Expr[T] -//│ trait Expr[A]: Add | Cond[?] | Fst[?, ?] | LitBool | LitInt | Pair[?, ?] | Snd[?, ?] -//│ class LitInt(n: Int) extends Expr -//│ class LitBool(b: Bool) extends Expr -//│ class Add(x: Expr[Int], y: Expr[Int]) extends Expr -//│ class Cond[T](p: Expr[Bool], t: Expr[T], e: Expr[T]) extends Expr -//│ class Pair[S, T](a: Expr[S], b: Expr[T]) extends Expr -//│ class Fst[S, T](p: Expr[[S, T]]) extends Expr -//│ class Snd[S, T](p: Expr[[S, T]]) extends Expr +abstract class Option[type T]: None | Some[T] +module None extends Option[nothing] +class Some[T](get: T) extends Option[T] +//│ abstract class Option[T]: None | Some[T] +//│ module None extends Option +//│ class Some[T](get: T) extends Option -let l1 = LitInt(1) -//│ let l1: LitInt -//│ l1 -//│ = LitInt {} +fun map(f, x) = if x is + None then None + Some(g) then Some(f(g)) +//│ fun map: forall 'T 'T0. ((??T & 'T) -> 'T0, None | Some['T]) -> (None | Some['T0]) -// TODO -class Exp[type A] -//│ ╔══[PARSE ERROR] Unexpected 'type' keyword here -//│ ║ l.26: class Exp[type A] -//│ ╙── ^^^^ -//│ class Exp { -//│ constructor() -//│ } +fun map[A, B](f: A -> B, x: Option[A]) = if x is + None then None + Some(g) then Some(f(g)) +//│ fun map: forall 'A 'B. (f: 'A -> 'B, x: Option['A]) -> (None | Some['B]) -l1: Expr[Int] -//│ Expr[Int] -//│ res -//│ = LitInt {} +fun getOr(x, d) = if x is + None then d + Some(g) then g +//│ fun getOr: forall 'T 'a. (None | Some['T], 'a) -> (??T & 'T | 'a) -:e -l1: Expr[Bool] -//│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.40: l1: Expr[Bool] -//│ ║ ^^ -//│ ╟── type `Int` is not an instance of type `Bool` -//│ ║ l.4: class LitInt(n: Int) extends Expr[Int] -//│ ║ ^^^ -//│ ╟── Note: constraint arises from type reference: -//│ ║ l.40: l1: Expr[Bool] -//│ ╙── ^^^^ -//│ Expr[Bool] -//│ res -//│ = LitInt {} +fun getOr(x: Option['a], d) = if x is + None then d + Some(g) then g +//│ fun getOr: forall 'a 'b. (x: Option['a], 'b) -> (??T & 'a | 'b) -// FIXME -fun eval[A](e: Expr[A]): A = - if - e is LitInt(n) then n - e is LitBool(b) then b - e is Add(x, y) then eval(x) + eval(y) -//│ ╔══[ERROR] Type mismatch in `case` expression: -//│ ║ l.57: e is LitInt(n) then n -//│ ║ ^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.58: e is LitBool(b) then b -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.59: e is Add(x, y) then eval(x) + eval(y) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── type `#Expr & (Add & {Expr#A = A} | Cond[?] & {Expr#A = A} | Fst[?, ?] & {Expr#A = A} | LitBool & {Expr#A = A} | LitInt & {Expr#A = A} | Pair[?, ?] & {Expr#A = A} | Snd[?, ?] & {Expr#A = A})` does not match type `Add | LitBool | LitInt` -//│ ║ l.55: fun eval[A](e: Expr[A]): A = -//│ ║ ^^^^^^^ -//│ ╟── but it flows into reference with expected type `Add | LitBool | LitInt` -//│ ║ l.57: e is LitInt(n) then n -//│ ╙── ^ -//│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.57: e is LitInt(n) then n -//│ ║ ^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.58: e is LitBool(b) then b -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.59: e is Add(x, y) then eval(x) + eval(y) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── type `Int` does not match type `A` -//│ ║ l.4: class LitInt(n: Int) extends Expr[Int] -//│ ║ ^^^ -//│ ╟── but it flows into reference with expected type `A` -//│ ║ l.57: e is LitInt(n) then n -//│ ║ ^ -//│ ╟── Note: constraint arises from method type parameter: -//│ ║ l.55: fun eval[A](e: Expr[A]): A = -//│ ╙── ^ -//│ ╔══[ERROR] Type mismatch in definition: -//│ ║ l.55: fun eval[A](e: Expr[A]): A = -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.56: if -//│ ║ ^^^^^^^ -//│ ║ l.57: e is LitInt(n) then n -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.58: e is LitBool(b) then b -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.59: e is Add(x, y) then eval(x) + eval(y) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── type `Int` does not match type `A` -//│ ║ l.6: class Add(x: Expr[Int], y: Expr[Int]) extends Expr[Int] -//│ ║ ^^^ -//│ ╟── Note: constraint arises from method type parameter: -//│ ║ l.55: fun eval[A](e: Expr[A]): A = -//│ ╙── ^ -//│ ╔══[ERROR] Type mismatch in definition: -//│ ║ l.55: fun eval[A](e: Expr[A]): A = -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.56: if -//│ ║ ^^^^^^^ -//│ ║ l.57: e is LitInt(n) then n -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.58: e is LitBool(b) then b -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.59: e is Add(x, y) then eval(x) + eval(y) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── type `A` is not an instance of type `Int` -//│ ║ l.55: fun eval[A](e: Expr[A]): A = -//│ ║ ^ -//│ ╟── Note: constraint arises from type reference: -//│ ║ l.6: class Add(x: Expr[Int], y: Expr[Int]) extends Expr[Int] -//│ ╙── ^^^ -//│ fun eval: forall 'A. (e: Expr['A]) -> 'A +fun getOr[T](x: Option[T], d: T): T = if x is + None then d + Some(g) then g +//│ fun getOr: forall 'T. (x: Option['T], d: 'T) -> 'T +fun get(x) = if x is Some(r) then r else error +//│ fun get: forall 'T. (Object & ~#Some | Some['T]) -> (??T & 'T) + +fun get(x: Option['a]): x.T = if x is Some(r) then r else error +//│ fun get: forall 'a. (x: Option['a]) -> nothing diff --git a/shared/src/test/diff/nu/GenericClasses.mls b/shared/src/test/diff/nu/GenericClasses.mls index 8ce63d9db9..44cbabedba 100644 --- a/shared/src/test/diff/nu/GenericClasses.mls +++ b/shared/src/test/diff/nu/GenericClasses.mls @@ -7,7 +7,7 @@ class C //│ } fun f(x) = if x is C then x -//│ fun f: forall 'A. C['A] -> C['A] +//│ fun f: forall 'A 'A0. C[in 'A out 'A0] -> C[in 'A & 'A0 out ??A & 'A0] // * TODO parse class tags? // f(C : #C) @@ -27,10 +27,10 @@ c.a //│ = 1 fun f(x) = if x is C(a) then a -//│ fun f: forall 'a. C['a] -> 'a +//│ fun f: forall 'A. C['A] -> (??A & 'A) f(c) -//│ 1 +//│ 1 & ??A //│ res //│ = 1 @@ -158,12 +158,12 @@ opt.map(x => x > 0) if opt is Some then opt.value else 0 -//│ 0 | 123 +//│ 0 | 123 & ??A //│ res //│ = 123 if opt is Some(v) then v else 0 -//│ 0 | 123 +//│ 0 | 123 & ??A //│ res //│ = 123 @@ -171,7 +171,7 @@ if opt is Some(v) then v else 0 fun map(x, f) = if x is None then None Some(v) then Some(f(v)) -//│ fun map: forall 'a 'A. (None | Some['a], 'a -> 'A) -> (None | Some['A]) +//│ fun map: forall 'A 'a. (None | Some['A], (??A & 'A) -> 'a) -> (None | Some['a]) let mo = map(opt, succ) //│ let mo: None | Some[Int] diff --git a/shared/src/test/diff/nu/GenericModules.mls b/shared/src/test/diff/nu/GenericModules.mls index 778511bb83..2a19b54ab6 100644 --- a/shared/src/test/diff/nu/GenericModules.mls +++ b/shared/src/test/diff/nu/GenericModules.mls @@ -142,10 +142,10 @@ Test : Test<'a> fun test(x) = if x is Test then x.foo -//│ fun test: forall 'A. Test['A] -> 'A -> 'A +//│ fun test: forall 'A 'A0. Test[in 'A out 'A0] -> ('A & 'A0) -> (??A & 'A0) test(Test) -//│ 'A -> 'A +//│ 'A -> (??A & 'A) //│ res //│ = [Function: id] diff --git a/shared/src/test/diff/nu/Huawei1.mls b/shared/src/test/diff/nu/Huawei1.mls index 7b939fe6a1..5c12260288 100644 --- a/shared/src/test/diff/nu/Huawei1.mls +++ b/shared/src/test/diff/nu/Huawei1.mls @@ -21,10 +21,10 @@ class B fun bar(c) = if c is C(y) then y B then 0 -//│ fun bar: forall 'a. (B | C['a]) -> (0 | 'a) +//│ fun bar: forall 'A. (B | C['A]) -> (0 | ??A & 'A) bar(c) -//│ 0 | 123 +//│ 0 | 123 & ??A //│ res //│ = 123 @@ -32,7 +32,7 @@ fun bar(c) = if c is C(y) then y + 1 B then 0 else 1 -//│ fun bar: (C[Int] | Object & ~#C) -> Int +//│ fun bar: (C[Int | ~??A] | Object & ~#C) -> Int bar(c) //│ Int @@ -44,7 +44,7 @@ bar(C(true)) //│ ╔══[ERROR] Type mismatch in application: //│ ║ l.43: bar(C(true)) //│ ║ ^^^^^^^^^^^^ -//│ ╟── reference of type `true` is not an instance of `Int` +//│ ╟── reference of type `true` does not match type `Int | ~??A` //│ ║ l.43: bar(C(true)) //│ ║ ^^^^ //│ ╟── Note: constraint arises from reference: diff --git a/shared/src/test/diff/nu/InferredInheritanceTypeArgs.mls b/shared/src/test/diff/nu/InferredInheritanceTypeArgs.mls index b89c16cbd3..47a5c80d56 100644 --- a/shared/src/test/diff/nu/InferredInheritanceTypeArgs.mls +++ b/shared/src/test/diff/nu/InferredInheritanceTypeArgs.mls @@ -172,14 +172,8 @@ B.foo //│ res //│ = [Function: foo] - -// * TODO: when -:pe trait Foo[type A] { fun foo(x: A): A } -//│ ╔══[PARSE ERROR] Unexpected 'type' keyword here -//│ ║ l.178: trait Foo[type A] { fun foo(x: A): A } -//│ ╙── ^^^^ -//│ trait Foo { +//│ trait Foo[A] { //│ fun foo: (x: A) -> A //│ } @@ -228,22 +222,22 @@ class B extends Foo { fun foo(x) = x } :e class B extends Foo { fun foo(x) = x + 1 } //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.229: class B extends Foo { fun foo(x) = x + 1 } +//│ ║ l.223: class B extends Foo { fun foo(x) = x + 1 } //│ ║ ^^^^^^^^^^^^^^ //│ ╟── type `A` is not an instance of type `Int` -//│ ║ l.217: trait Foo[A] { fun foo[A](x: A): A } +//│ ║ l.211: trait Foo[A] { fun foo[A](x: A): A } //│ ║ ^ //│ ╟── Note: constraint arises from reference: -//│ ║ l.229: class B extends Foo { fun foo(x) = x + 1 } +//│ ║ l.223: class B extends Foo { fun foo(x) = x + 1 } //│ ╙── ^ //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.229: class B extends Foo { fun foo(x) = x + 1 } +//│ ║ l.223: class B extends Foo { fun foo(x) = x + 1 } //│ ║ ^^^^^^^^^^^^^^ //│ ╟── operator application of type `Int` does not match type `A` -//│ ║ l.229: class B extends Foo { fun foo(x) = x + 1 } +//│ ║ l.223: class B extends Foo { fun foo(x) = x + 1 } //│ ║ ^^^^^ //│ ╟── Note: constraint arises from method type parameter: -//│ ║ l.217: trait Foo[A] { fun foo[A](x: A): A } +//│ ║ l.211: trait Foo[A] { fun foo[A](x: A): A } //│ ╙── ^ //│ class B extends Foo { //│ constructor() diff --git a/shared/src/test/diff/nu/Interfaces.mls b/shared/src/test/diff/nu/Interfaces.mls index 99c46392a3..c4c5f91d89 100644 --- a/shared/src/test/diff/nu/Interfaces.mls +++ b/shared/src/test/diff/nu/Interfaces.mls @@ -495,44 +495,30 @@ val b: Base = f //│ = Foo {} if b is Foo(a) then a else 0 -//│ 0 | [??A, ??A] +//│ 0 | [??A & ??A0, ??A & ??A0] //│ res //│ = [ 1, 2 ] :e // * Note: an error is raised in this case and not above because B is invariant so it can't be widened if b is Bar(f) then f else 0 -//│ ╔══[ERROR] Type error in `case` expression -//│ ║ l.503: if b is Bar(f) then f else 0 -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── type variable `B` leaks out of its scope -//│ ║ l.477: class Bar[B](f: B => B) extends Base -//│ ╙── ^ -//│ 0 | ??B -> anything +//│ 0 | ??B -> ??B0 //│ res //│ = 0 +//│ TEST CASE FAILURE: There was an unexpected lack of type error :e if b is Foo(a) then a Bar(f) then f -//│ ╔══[ERROR] Type error in `case` expression -//│ ║ l.515: if b is -//│ ║ ^^^^ -//│ ║ l.516: Foo(a) then a -//│ ║ ^^^^^^^^^^^^^^^ -//│ ║ l.517: Bar(f) then f -//│ ║ ^^^^^^^^^^^^^^^ -//│ ╟── type variable `B` leaks out of its scope -//│ ║ l.477: class Bar[B](f: B => B) extends Base -//│ ╙── ^ //│ anything //│ res //│ = [ 1, 2 ] +//│ TEST CASE FAILURE: There was an unexpected lack of type error :e val tt1 = Test //│ ╔══[ERROR] trait Test cannot be used in term position -//│ ║ l.533: val tt1 = Test +//│ ║ l.519: val tt1 = Test //│ ╙── ^^^^ //│ val tt1: error //│ Code generation encountered an error: @@ -541,7 +527,7 @@ val tt1 = Test :e fun mt(x) = if x is Test then 1 else 0 //│ ╔══[ERROR] Cannot match on trait `Test` -//│ ║ l.542: fun mt(x) = if x is Test then 1 else 0 +//│ ║ l.528: fun mt(x) = if x is Test then 1 else 0 //│ ╙── ^^^^ //│ fun mt: anything -> error //│ Code generation encountered an error: @@ -607,40 +593,40 @@ z: WP g: ZL e: ZL & WP //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.605: fun fto(w: WP): EM = w +//│ ║ l.591: fun fto(w: WP): EM = w //│ ║ ^ //│ ╟── type `#WP` is not an instance of type `EM` -//│ ║ l.605: fun fto(w: WP): EM = w +//│ ║ l.591: fun fto(w: WP): EM = w //│ ║ ^^ //│ ╟── but it flows into reference with expected type `#EM` -//│ ║ l.605: fun fto(w: WP): EM = w +//│ ║ l.591: fun fto(w: WP): EM = w //│ ║ ^ //│ ╟── Note: constraint arises from type reference: -//│ ║ l.605: fun fto(w: WP): EM = w +//│ ║ l.591: fun fto(w: WP): EM = w //│ ╙── ^^ //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.606: z: WP +//│ ║ l.592: z: WP //│ ║ ^ //│ ╟── type `#ZL` is not an instance of type `WP` -//│ ║ l.562: val z: ZL +//│ ║ l.548: val z: ZL //│ ║ ^^ //│ ╟── but it flows into reference with expected type `#WP` -//│ ║ l.606: z: WP +//│ ║ l.592: z: WP //│ ║ ^ //│ ╟── Note: constraint arises from type reference: -//│ ║ l.606: z: WP +//│ ║ l.592: z: WP //│ ╙── ^^ //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.607: g: ZL +//│ ║ l.593: g: ZL //│ ║ ^ //│ ╟── type `#Geo` is not an instance of type `ZL` -//│ ║ l.561: val g: Geo +//│ ║ l.547: val g: Geo //│ ║ ^^^ //│ ╟── but it flows into reference with expected type `#ZL` -//│ ║ l.607: g: ZL +//│ ║ l.593: g: ZL //│ ║ ^ //│ ╟── Note: constraint arises from type reference: -//│ ║ l.607: g: ZL +//│ ║ l.593: g: ZL //│ ╙── ^^ //│ fun fto: (w: WP) -> EM //│ WP & ZL @@ -696,36 +682,36 @@ class Eh2 extends Bs(true), Ele { fun ce(x) = x } //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.695: fun foo(x) = x && false +//│ ║ l.681: fun foo(x) = x && false //│ ║ ^^^^^^^^^^^^^^^^^^^ //│ ╟── expression of type `Int & ?a` is not an instance of type `Bool` //│ ╟── Note: constraint arises from reference: -//│ ║ l.695: fun foo(x) = x && false +//│ ║ l.681: fun foo(x) = x && false //│ ╙── ^ //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.695: fun foo(x) = x && false +//│ ║ l.681: fun foo(x) = x && false //│ ║ ^^^^^^^^^^^^^^^^^^^ //│ ╟── expression of type `Int & ?a` does not match type `Bool` //│ ╟── Note: constraint arises from reference: -//│ ║ l.695: fun foo(x) = x && false +//│ ║ l.681: fun foo(x) = x && false //│ ╙── ^ //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.695: fun foo(x) = x && false +//│ ║ l.681: fun foo(x) = x && false //│ ║ ^^^^^^^^^^^^^^^^^^^ //│ ╟── operator application of type `Bool` does not match type `Int | ?a` -//│ ║ l.695: fun foo(x) = x && false +//│ ║ l.681: fun foo(x) = x && false //│ ║ ^^^^^^^^^^ //│ ╟── Note: constraint arises from operator application: -//│ ║ l.658: virtual fun foo(x) = x + 1 +//│ ║ l.644: virtual fun foo(x) = x + 1 //│ ╙── ^^^^^ //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.695: fun foo(x) = x && false +//│ ║ l.681: fun foo(x) = x && false //│ ║ ^^^^^^^^^^^^^^^^^^^ //│ ╟── operator application of type `Bool` does not match type `Int | ?a` -//│ ║ l.695: fun foo(x) = x && false +//│ ║ l.681: fun foo(x) = x && false //│ ║ ^^^^^^^^^^ //│ ╟── Note: constraint arises from operator application: -//│ ║ l.658: virtual fun foo(x) = x + 1 +//│ ║ l.644: virtual fun foo(x) = x + 1 //│ ╙── ^^^^^ //│ class Eh2 extends Bs, Ele { //│ constructor() @@ -738,34 +724,34 @@ class Eh extends Bs(1) class Eh1 extends Bs class Eh3 extends Bs(false), Test //│ ╔══[ERROR] Type mismatch in type declaration: -//│ ║ l.737: class Eh extends Bs(1) +//│ ║ l.723: class Eh extends Bs(1) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── integer literal of type `1` is not an instance of type `Bool` -//│ ║ l.737: class Eh extends Bs(1) +//│ ║ l.723: class Eh extends Bs(1) //│ ║ ^ //│ ╟── Note: constraint arises from type reference: -//│ ║ l.657: class Bs(val a: Bool) { +//│ ║ l.643: class Bs(val a: Bool) { //│ ╙── ^^^^ //│ ╔══[ERROR] Type mismatch in type declaration: -//│ ║ l.737: class Eh extends Bs(1) +//│ ║ l.723: class Eh extends Bs(1) //│ ║ ^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── integer literal of type `1` does not match type `Bool` -//│ ║ l.737: class Eh extends Bs(1) +//│ ║ l.723: class Eh extends Bs(1) //│ ║ ^ //│ ╟── Note: constraint arises from type reference: -//│ ║ l.657: class Bs(val a: Bool) { +//│ ║ l.643: class Bs(val a: Bool) { //│ ╙── ^^^^ //│ ╔══[ERROR] class Bs expects 1 parameter(s); got 0 -//│ ║ l.738: class Eh1 extends Bs +//│ ║ l.724: class Eh1 extends Bs //│ ╙── ^^ //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.658: virtual fun foo(x) = x + 1 +//│ ║ l.644: virtual fun foo(x) = x + 1 //│ ║ ^^^^^^^^^^^^^^ //│ ╟── function of type `?a -> (forall ?b. ?b)` is not an instance of type `Int` -//│ ║ l.658: virtual fun foo(x) = x + 1 +//│ ║ l.644: virtual fun foo(x) = x + 1 //│ ║ ^^^^^^^^^^^ //│ ╟── but it flows into definition of method foo with expected type `Int` -//│ ║ l.658: virtual fun foo(x) = x + 1 +//│ ║ l.644: virtual fun foo(x) = x + 1 //│ ║ ^^^^^^^^^^^^^^ //│ ╟── Note: constraint arises from type reference: //│ ║ l.5: fun foo: Int @@ -774,7 +760,7 @@ class Eh3 extends Bs(false), Test //│ ║ l.5: fun foo: Int //│ ╙── ^^^^^^^^ //│ ╔══[ERROR] Member `bar` is declared (or its declaration is inherited) but is not implemented in `Eh3` -//│ ║ l.739: class Eh3 extends Bs(false), Test +//│ ║ l.725: class Eh3 extends Bs(false), Test //│ ║ ^^^ //│ ╟── Declared here: //│ ║ l.6: fun bar: Bool -> Bool @@ -855,7 +841,7 @@ abstract class Bc3 { :e class Bc12() extends Bc1(1), Bc2(true) //│ ╔══[ERROR] Cannot inherit from more than one base class: Bc1 and Bc2 -//│ ║ l.856: class Bc12() extends Bc1(1), Bc2(true) +//│ ║ l.842: class Bc12() extends Bc1(1), Bc2(true) //│ ╙── ^^^^^^^^^ //│ class Bc12() extends Bc1, Bc2 //│ Code generation encountered an error: @@ -876,24 +862,24 @@ Bc02().foo :e class Bc31(val baz: Bool) extends Bc3 //│ ╔══[ERROR] Type mismatch in type reference: -//│ ║ l.877: class Bc31(val baz: Bool) extends Bc3 +//│ ║ l.863: class Bc31(val baz: Bool) extends Bc3 //│ ║ ^^^^ //│ ╟── type `Bool` is not an instance of type `Int` //│ ╟── Note: constraint arises from type reference: -//│ ║ l.847: val baz : Int +//│ ║ l.833: val baz : Int //│ ║ ^^^ //│ ╟── from signature of member `baz`: -//│ ║ l.847: val baz : Int +//│ ║ l.833: val baz : Int //│ ╙── ^^^^^^^^^ //│ ╔══[ERROR] Type mismatch in type reference: -//│ ║ l.877: class Bc31(val baz: Bool) extends Bc3 +//│ ║ l.863: class Bc31(val baz: Bool) extends Bc3 //│ ║ ^^^^ //│ ╟── type `Bool` is not an instance of type `Int` //│ ╟── Note: constraint arises from type reference: -//│ ║ l.847: val baz : Int +//│ ║ l.833: val baz : Int //│ ║ ^^^ //│ ╟── from signature of member `baz`: -//│ ║ l.847: val baz : Int +//│ ║ l.833: val baz : Int //│ ╙── ^^^^^^^^^ //│ class Bc31(baz: Bool) extends Bc3 @@ -928,7 +914,7 @@ trait BInt extends Base[Int] { fun f = error } //│ ╔══[ERROR] Method implementations in traits are not yet supported -//│ ║ l.928: fun f = error +//│ ║ l.914: fun f = error //│ ╙── ^^^^^^^^^^^^^ //│ trait BInt extends Base { //│ fun f: nothing @@ -959,7 +945,7 @@ bp: Base[[Int, Bool]] :e bp: Base[[Int, Int]] //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.960: bp: Base[[Int, Int]] +//│ ║ l.946: bp: Base[[Int, Int]] //│ ║ ^^ //│ ╙── expression of type `true` is not an instance of type `Int` //│ Base[[Int, Int]] @@ -1020,13 +1006,13 @@ trait BInfer2 extends Base { :e class DerBad1 extends Base[Int, Int] //│ ╔══[ERROR] trait Base expects 1 type parameter(s); got 2 -//│ ║ l.1021: class DerBad1 extends Base[Int, Int] +//│ ║ l.1007: class DerBad1 extends Base[Int, Int] //│ ╙── ^^^^^^^^^^^^^ //│ ╔══[ERROR] Member `f` is declared (or its declaration is inherited) but is not implemented in `DerBad1` -//│ ║ l.1021: class DerBad1 extends Base[Int, Int] +//│ ║ l.1007: class DerBad1 extends Base[Int, Int] //│ ║ ^^^^^^^ //│ ╟── Declared here: -//│ ║ l.909: trait Base[A] { fun f: A -> A } +//│ ║ l.895: trait Base[A] { fun f: A -> A } //│ ╙── ^^^^^^^^^^^^^ //│ class DerBad1 extends Base { //│ constructor() @@ -1038,28 +1024,28 @@ class DerBad1 extends Base[Int, Int] :e class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ╔══[ERROR] Type mismatch in definition of method f: -//│ ║ l.1039: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } +//│ ║ l.1025: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── reference of type `B` does not match type `A` -//│ ║ l.1039: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } +//│ ║ l.1025: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ║ ^ //│ ╟── Note: constraint arises from type parameter: -//│ ║ l.1039: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } +//│ ║ l.1025: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ║ ^ //│ ╟── Note: type parameter B is defined at: -//│ ║ l.1039: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } +//│ ║ l.1025: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ╙── ^ //│ ╔══[ERROR] Type mismatch in definition of method f: -//│ ║ l.1039: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } +//│ ║ l.1025: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── reference of type `A` does not match type `B` -//│ ║ l.1039: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } +//│ ║ l.1025: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ║ ^ //│ ╟── Note: constraint arises from type parameter: -//│ ║ l.1039: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } +//│ ║ l.1025: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ║ ^ //│ ╟── Note: type parameter A is defined at: -//│ ║ l.1039: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } +//│ ║ l.1025: class Der2[A, B] extends Base[[A, B]] { fun f([x, y]) = [y, x] } //│ ╙── ^ //│ class Der2[A, B] extends Base { //│ constructor() @@ -1111,7 +1097,7 @@ trait Tb extends Ta[Int] { virtual val p = false } //│ ╔══[ERROR] Method implementations in traits are not yet supported -//│ ║ l.1111: virtual val p = false +//│ ║ l.1097: virtual val p = false //│ ╙── ^^^^^^^^^^^^^ //│ trait Tb extends Ta { //│ val g: 'T @@ -1146,24 +1132,24 @@ trait Oz { :e class Fischl(val age: Bool) extends Oz //│ ╔══[ERROR] Type mismatch in type reference: -//│ ║ l.1147: class Fischl(val age: Bool) extends Oz +//│ ║ l.1133: class Fischl(val age: Bool) extends Oz //│ ║ ^^^^ //│ ╟── type `Bool` is not an instance of type `Int` //│ ╟── Note: constraint arises from type reference: -//│ ║ l.1140: val age: Int +//│ ║ l.1126: val age: Int //│ ║ ^^^ //│ ╟── from signature of member `age`: -//│ ║ l.1140: val age: Int +//│ ║ l.1126: val age: Int //│ ╙── ^^^^^^^^ //│ ╔══[ERROR] Type mismatch in type reference: -//│ ║ l.1147: class Fischl(val age: Bool) extends Oz +//│ ║ l.1133: class Fischl(val age: Bool) extends Oz //│ ║ ^^^^ //│ ╟── type `Bool` is not an instance of type `Int` //│ ╟── Note: constraint arises from type reference: -//│ ║ l.1140: val age: Int +//│ ║ l.1126: val age: Int //│ ║ ^^^ //│ ╟── from signature of member `age`: -//│ ║ l.1140: val age: Int +//│ ║ l.1126: val age: Int //│ ╙── ^^^^^^^^ //│ class Fischl(age: Bool) extends Oz @@ -1183,36 +1169,36 @@ class Go extends Fate { fun foo(x) = x && true } //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.1183: fun foo(x) = x && true +//│ ║ l.1169: fun foo(x) = x && true //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── expression of type `Int & ?a` is not an instance of type `Bool` //│ ╟── Note: constraint arises from reference: -//│ ║ l.1183: fun foo(x) = x && true +//│ ║ l.1169: fun foo(x) = x && true //│ ╙── ^ //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.1183: fun foo(x) = x && true +//│ ║ l.1169: fun foo(x) = x && true //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── expression of type `Int & ?a` does not match type `Bool` //│ ╟── Note: constraint arises from reference: -//│ ║ l.1183: fun foo(x) = x && true +//│ ║ l.1169: fun foo(x) = x && true //│ ╙── ^ //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.1183: fun foo(x) = x && true +//│ ║ l.1169: fun foo(x) = x && true //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── operator application of type `Bool` does not match type `Int | ?a` -//│ ║ l.1183: fun foo(x) = x && true +//│ ║ l.1169: fun foo(x) = x && true //│ ║ ^^^^^^^^^ //│ ╟── Note: constraint arises from operator application: -//│ ║ l.1174: virtual fun foo(x) = x + 1 +//│ ║ l.1160: virtual fun foo(x) = x + 1 //│ ╙── ^^^^^ //│ ╔══[ERROR] Type mismatch in definition of method foo: -//│ ║ l.1183: fun foo(x) = x && true +//│ ║ l.1169: fun foo(x) = x && true //│ ║ ^^^^^^^^^^^^^^^^^^ //│ ╟── operator application of type `Bool` does not match type `Int | ?a` -//│ ║ l.1183: fun foo(x) = x && true +//│ ║ l.1169: fun foo(x) = x && true //│ ║ ^^^^^^^^^ //│ ╟── Note: constraint arises from operator application: -//│ ║ l.1174: virtual fun foo(x) = x + 1 +//│ ║ l.1160: virtual fun foo(x) = x + 1 //│ ╙── ^^^^^ //│ class Go extends Fate { //│ constructor() @@ -1231,24 +1217,24 @@ class Haha(x: 1 | 2) extends Ha :e class Ohhh(x: Bool) extends Ha //│ ╔══[ERROR] Type mismatch in type reference: -//│ ║ l.1232: class Ohhh(x: Bool) extends Ha +//│ ║ l.1218: class Ohhh(x: Bool) extends Ha //│ ║ ^^^^ //│ ╟── type `Bool` is not an instance of type `Int` //│ ╟── Note: constraint arises from type reference: -//│ ║ l.1222: class Ha { virtual val x: Int = 1 } +//│ ║ l.1208: class Ha { virtual val x: Int = 1 } //│ ║ ^^^ //│ ╟── from definition of value x: -//│ ║ l.1222: class Ha { virtual val x: Int = 1 } +//│ ║ l.1208: class Ha { virtual val x: Int = 1 } //│ ╙── ^^^^^^^^^^ //│ ╔══[ERROR] Type mismatch in type reference: -//│ ║ l.1232: class Ohhh(x: Bool) extends Ha +//│ ║ l.1218: class Ohhh(x: Bool) extends Ha //│ ║ ^^^^ //│ ╟── type `Bool` is not an instance of type `Int` //│ ╟── Note: constraint arises from type reference: -//│ ║ l.1222: class Ha { virtual val x: Int = 1 } +//│ ║ l.1208: class Ha { virtual val x: Int = 1 } //│ ║ ^^^ //│ ╟── from definition of value x: -//│ ║ l.1222: class Ha { virtual val x: Int = 1 } +//│ ║ l.1208: class Ha { virtual val x: Int = 1 } //│ ╙── ^^^^^^^^^^ //│ class Ohhh(x: Bool) extends Ha diff --git a/shared/src/test/diff/nu/Lifted.mls b/shared/src/test/diff/nu/Lifted.mls new file mode 100644 index 0000000000..bf313531ea --- /dev/null +++ b/shared/src/test/diff/nu/Lifted.mls @@ -0,0 +1,83 @@ +:NewDefs + +let y = 1 +//│ let y: 1 +//│ y +//│ = 1 + +1 : y +//│ 1 +//│ res +//│ = 1 + +let x: y = y +//│ let x: 1 +//│ x +//│ = 1 + +:e +let x: (1, 2) = (1, 2) +//│ ╔══[ERROR] cannot lift variable , to type +//│ ║ l.19: let x: (1, 2) = (1, 2) +//│ ╙── ^^^^^^ +//│ let x: error +//│ x +//│ = 2 + +:e +let x: (1, 2,) = (1, 2,) +//│ ╔══[ERROR] cannot lift variable , to type +//│ ║ l.28: let x: (1, 2,) = (1, 2,) +//│ ╙── ^^^^^^^ +//│ let x: error +//│ x +//│ = 2 + +class Foo[A, B] +//│ class Foo[A, B] { +//│ constructor() +//│ } + +let x: Foo[1, 2] = new Foo +//│ let x: Foo[1, 2] +//│ x +//│ = Foo {} + +let y: Foo = new Foo +//│ let y: Foo[?, ?] +//│ y +//│ = Foo {} + +y: y +//│ Foo[?, ?] +//│ res +//│ = Foo {} + +:e +let z: y[1, 2] +//│ ╔══[ERROR] `let` bindings must have a right-hand side +//│ ║ l.57: let z: y[1, 2] +//│ ╙── ^^^^^^^^^^^^^^ +//│ ╔══[ERROR] cannot lift expression y to type +//│ ║ l.57: let z: y[1, 2] +//│ ║ ^^^^^^^ +//│ ╟── as defined in +//│ ║ l.46: let y: Foo = new Foo +//│ ╙── ^^^^^^^^^^^^^^^^ +//│ let z: error +//│ z +//│ = + +:e +2 : (1, 2) +//│ ╔══[ERROR] cannot lift variable , to type +//│ ║ l.72: 2 : (1, 2) +//│ ╙── ^^^^^^ +//│ error +//│ res +//│ = 2 + +1 : Int +//│ Int +//│ res +//│ = 1 diff --git a/shared/src/test/diff/nu/ListConsNil.mls b/shared/src/test/diff/nu/ListConsNil.mls index d1f1c147fe..511353c25e 100644 --- a/shared/src/test/diff/nu/ListConsNil.mls +++ b/shared/src/test/diff/nu/ListConsNil.mls @@ -106,15 +106,15 @@ fun list_assoc(s, l) = if eq(s)(h._1) then Cons(h._2, Nil) else list_assoc(s, t) Nil then Nil -//│ fun list_assoc: forall 'A. (anything, Cons[{_1: anything, _2: 'A}] | Nil) -> (Cons['A] | Nil) +//│ fun list_assoc: forall 'a. (anything, Cons[{_1: anything, _2: 'a} | ~??A] | Nil) -> (Cons['a] | Nil) fun test(x, l) = list_assoc(42, Cons(x, l)) -//│ fun test: forall 'A. ({_1: anything, _2: 'A}, List[{_1: anything, _2: 'A}]) -> (Cons['A] | Nil) +//│ fun test: forall 'a. ({_1: anything, _2: 'a} | ~??A, List[{_1: anything, _2: 'a} | ~??A]) -> (Cons['a] | Nil) fun test(x, l) = if l is Nil then list_assoc(42, Cons(x, l)) Cons(h, t) then list_assoc(42, Cons(h, t)) -//│ fun test: forall 'A 'A0. ({_1: anything, _2: 'A}, Cons[{_1: anything, _2: 'A0}] | Nil) -> (Cons['A] | Nil | Cons['A0]) +//│ fun test: forall 'a 'b. ({_1: anything, _2: 'a} | ~??A, Cons[{_1: anything, _2: 'b} | ~(??A & ??A0)] | Nil) -> (Cons['a & 'b] | Nil) diff --git a/shared/src/test/diff/nu/Metaprog.mls b/shared/src/test/diff/nu/Metaprog.mls index fda3779361..2ebfefbd3e 100644 --- a/shared/src/test/diff/nu/Metaprog.mls +++ b/shared/src/test/diff/nu/Metaprog.mls @@ -28,7 +28,7 @@ abstract class Test[C] { // * Represents what happens in "... ${input} ..." when a binding of C is in scope fun unquote: (input: Code['a, C | 'c]) -> Code[Int, 'c] fun getVar: Code[Int, C] - fun test0 = this.unquote of IntLit(1) + fun test0 = this.unquote of (IntLit(1) : Code['ia, 'ic]) // ? why ascription works here fun test1 = this.unquote of Add(this.getVar, IntLit(1)) } //│ abstract class Test[C] { diff --git a/shared/src/test/diff/nu/MethodSignatures.mls b/shared/src/test/diff/nu/MethodSignatures.mls index 583ddefb4a..25f496b3e0 100644 --- a/shared/src/test/diff/nu/MethodSignatures.mls +++ b/shared/src/test/diff/nu/MethodSignatures.mls @@ -164,7 +164,27 @@ module M { //│ ╔══[ERROR] undeclared `this` //│ ║ l.161: fun a: this.A //│ ╙── ^^^^ -//│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing +//│ ╔══[ERROR] Type mismatch in definition of method a: +//│ ║ l.162: fun a = 1 +//│ ║ ^^^^^ +//│ ╟── integer literal of type `1` does not match type `A` +//│ ║ l.162: fun a = 1 +//│ ║ ^ +//│ ╟── but it flows into definition of method a with expected type `A` +//│ ║ l.162: fun a = 1 +//│ ║ ^^^^^ +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.161: fun a: this.A +//│ ║ ^^ +//│ ╟── from signature of member `a`: +//│ ║ l.161: fun a: this.A +//│ ╙── ^^^^^^^^^ +//│ module M { +//│ class A { +//│ constructor() +//│ } +//│ fun a: error +//│ } // FIXME similar module M { @@ -188,7 +208,7 @@ fun f(Int): Int :e fun f(x): Int //│ ╔══[ERROR] type identifier not found: x -//│ ║ l.189: fun f(x): Int +//│ ║ l.209: fun f(x): Int //│ ╙── ^ //│ fun f: error -> Int diff --git a/shared/src/test/diff/nu/MissingTypeArg.mls b/shared/src/test/diff/nu/MissingTypeArg.mls index 688e797ce1..806859c249 100644 --- a/shared/src/test/diff/nu/MissingTypeArg.mls +++ b/shared/src/test/diff/nu/MissingTypeArg.mls @@ -72,7 +72,7 @@ fun test(pt1, pt2) = pt1.color === pt1.color and else test(p1, p2) //│ fun test: forall 'a 'b 'c. ('a, 'c) -> Bool //│ where -//│ 'c <: {parent: Object & 'c} +//│ 'c <: {parent: 'c & (Object & ~() | ())} //│ 'a <: {color: Eql['b] & 'b, parent: Object & 'a & ~() | ()} :e // TODO support diff --git a/shared/src/test/diff/nu/MutLet.mls b/shared/src/test/diff/nu/MutLet.mls index 1c86ee34a2..1d8c9e38d0 100644 --- a/shared/src/test/diff/nu/MutLet.mls +++ b/shared/src/test/diff/nu/MutLet.mls @@ -58,7 +58,7 @@ funny(1) if oops is None then 0 Some(v) then v -//│ 0 | 1 +//│ 0 | 1 & ??A //│ res //│ = 1 @@ -68,7 +68,9 @@ set oops = Some(123) //│ = undefined oops -//│ None | Some[in 'A out 1 | 123 | 'A] +//│ None | Some['A & (1 | 'A0)] +//│ where +//│ 'A :> 123 //│ res //│ = Some {} @@ -86,14 +88,14 @@ fun funny(x) = //│ fun funny: 'A -> (None | Some['A]) funny(123) -//│ None | Some[in 'A out 123 | 'A] +//│ None | Some[123 | 'A] //│ res //│ = None { class: [class None] } if funny("hi") is Some(v) then v else 0 -//│ "hi" | 0 | 123 +//│ 0 | ??A & ("hi" | 123) //│ res //│ = 123 @@ -119,19 +121,19 @@ let x = 1 set x = 2 x //│ ╔══[ERROR] definition `x` is not mutable and cannot be reassigned -//│ ║ l.119: set x = 2 +//│ ║ l.121: set x = 2 //│ ╙── ^^^^^^^^^ //│ ╔══[ERROR] Type mismatch in assignment: -//│ ║ l.119: set x = 2 +//│ ║ l.121: set x = 2 //│ ║ ^^^^^^^^^ //│ ╟── integer literal of type `2` does not match type `1` -//│ ║ l.119: set x = 2 +//│ ║ l.121: set x = 2 //│ ║ ^ //│ ╟── Note: constraint arises from integer literal: -//│ ║ l.118: let x = 1 +//│ ║ l.120: let x = 1 //│ ║ ^ //│ ╟── from definition of let binding x: -//│ ║ l.118: let x = 1 +//│ ║ l.120: let x = 1 //│ ╙── ^^^^^ //│ let x: 1 //│ 1 @@ -176,20 +178,20 @@ fun repmin(t) = Leaf(n) then set min = n go(t) min -//│ fun repmin: forall 'min. Leaf['min] -> (123 | 'min) +//│ fun repmin: forall 'min. Leaf['min | ~??A] -> (123 | 'min) fun repmin = mut let min = 123 let go(t) = if t is Leaf(n) then set min = n [min, go] -//│ fun repmin: forall 'min. [123 | 'min, Leaf['min] -> ()] +//│ fun repmin: forall 'min. [123 | 'min, Leaf['min | ~??A] -> ()] :e mut val lol[A] = (x: A) => x //│ ╔══[ERROR] Type parameters are not yet supported in this position -//│ ║ l.190: mut val lol[A] = (x: A) => x +//│ ║ l.192: mut val lol[A] = (x: A) => x //│ ╙── ^ //│ mut val lol: (x: 'A) -> 'A //│ lol diff --git a/shared/src/test/diff/nu/NamedArgs.mls b/shared/src/test/diff/nu/NamedArgs.mls index 3642761fb3..adee5cb773 100644 --- a/shared/src/test/diff/nu/NamedArgs.mls +++ b/shared/src/test/diff/nu/NamedArgs.mls @@ -369,7 +369,7 @@ fun foo(f: ((x: Int) => Int) | 'a) = f(x: 123) // * the result of the if-then-else is a TV with two LBs: the type of x and the function type :e fun foo(x) = (if true then (x: Int) => x + 1 else x)(x: 123) -//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `(x: Int) -> ?a | ?b` for applying named arguments +//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `?a | ?b` for applying named arguments //│ ║ l.371: fun foo(x) = (if true then (x: Int) => x + 1 else x)(x: 123) //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ fun foo: anything -> error @@ -382,7 +382,7 @@ foo((y: Int) => y) :e // TODO later: this could be made to work... fun foo(x) = (if true then (x: Int) => x + 1 else (x: Int) => x + 1)(x: 123) -//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `(x: Int) -> (?a | ?b)` for applying named arguments +//│ ╔══[ERROR] Cannot retrieve appropriate function signature from type `(x: Int) -> ?a | ?b` for applying named arguments //│ ║ l.384: fun foo(x) = (if true then (x: Int) => x + 1 else (x: Int) => x + 1)(x: 123) //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ fun foo: anything -> error diff --git a/shared/src/test/diff/nu/NestedClasses.mls b/shared/src/test/diff/nu/NestedClasses.mls index d712fc8db9..65eac7c881 100644 --- a/shared/src/test/diff/nu/NestedClasses.mls +++ b/shared/src/test/diff/nu/NestedClasses.mls @@ -15,7 +15,7 @@ let c = C0() :e c.NC0 -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member NC0 not yet supported //│ ║ l.17: c.NC0 //│ ╙── ^^^^ //│ error @@ -37,7 +37,7 @@ module M0 { :e M0.NC0 -//│ ╔══[ERROR] Access to class member not yet supported +//│ ╔══[ERROR] Access to class member NC0 not yet supported //│ ║ l.39: M0.NC0 //│ ╙── ^^^^ //│ error @@ -54,7 +54,7 @@ module M1 { :e M1.NM1 -//│ ╔══[ERROR] Access to module member not yet supported +//│ ╔══[ERROR] Access to module member NM1 not yet supported //│ ║ l.56: M1.NM1 //│ ╙── ^^^^ //│ error diff --git a/shared/src/test/diff/nu/NewNew.mls b/shared/src/test/diff/nu/NewNew.mls index a2e039d7c3..c9826a0cf7 100644 --- a/shared/src/test/diff/nu/NewNew.mls +++ b/shared/src/test/diff/nu/NewNew.mls @@ -259,7 +259,7 @@ fun f(x) = {x} :e new f(1) -//│ ╔══[ERROR] type identifier not found: f +//│ ╔══[ERROR] Unexpected type `forall ?a. ?a -> {x: ?a}` after `new` keyword //│ ║ l.261: new f(1) //│ ╙── ^ //│ error diff --git a/shared/src/test/diff/nu/NuPolymorphicTypeAliases.mls b/shared/src/test/diff/nu/NuPolymorphicTypeAliases.mls index 999389e9c8..1ae06ddc8f 100644 --- a/shared/src/test/diff/nu/NuPolymorphicTypeAliases.mls +++ b/shared/src/test/diff/nu/NuPolymorphicTypeAliases.mls @@ -17,15 +17,13 @@ fun f = forall 'B: module A { type F[A] = forall 'a: (A, 'a) -> [A, 'a] } -//│ module A { -//│ type F[A] = forall 'a. (A, 'a) -> [A, 'a] -//│ } +//│ module A :pe // TODO fun f[B] = ((x: B, y) => [x, y]) : A.F[B] //│ ╔══[PARSE ERROR] Not a recognized type -//│ ║ l.26: ((x: B, y) => [x, y]) : A.F[B] +//│ ║ l.24: ((x: B, y) => [x, y]) : A.F[B] //│ ╙── ^^^^^^ //│ fun f: anything diff --git a/shared/src/test/diff/nu/NuScratch.mls b/shared/src/test/diff/nu/NuScratch.mls index 539c23787c..63533d4401 100644 --- a/shared/src/test/diff/nu/NuScratch.mls +++ b/shared/src/test/diff/nu/NuScratch.mls @@ -1,3 +1,305 @@ :NewDefs +// ?A' :> `S <: `S +// ?A :> ??S <: ??S and ?A' :> `S | ?A <: `S & ?A' +// the bounds of ??A are now eqt to ?A :> Top <: Bot +// which fails + + +class Box[type A](val get: A) +abstract class F[type A]: MkF +class MkF[T](t: T) extends F[Box[T]] +//│ class Box[A](get: A) +//│ abstract class F[A]: MkF[anything] +//│ class MkF[T](t: T) extends F + +// :d +fun f[T](x: F[T]): T = if x is MkF(t) then Box(t) as x.A +//│ fun f: forall 'T. (x: F['T]) -> 'T + + + +fun f: Box[?] +//│ fun f: Box[anything] + +// :ds +f +//│ Box[anything] +//│ res +//│ = +//│ f is not implemented + + +fun foo(b: Box['X]) = b.get + 1 +//│ fun foo: forall 'X. (b: Box['X]) -> Int +//│ where +//│ 'X <: Int + +fun foo(b: Box['X] & Box[Int]) = [b, b.get + 1] +//│ fun foo: forall 'X. (b: Box[Int | 'X]) -> [Box[Int & 'X], Int] + + +type List[out A] = Cons[A] +module Nil +class Cons[A](head: A, tail: List[A]) +//│ type List[A] = Cons[A] +//│ module Nil +//│ class Cons[A](head: A, tail: List[A]) + +fun listConcat(xs) = + if xs is + Cons(x, xs2) then Cons(x, listConcat(xs2)) +//│ fun listConcat: forall 'A 'A0. Cons['A] -> Cons['A0] +//│ where +//│ 'A0 :> ??A & 'A + + + + + +module T { + fun unapply(x) = [x] +} +//│ module T { +//│ fun unapply: forall 'a. 'a -> ['a] +//│ } + +:e +fun foo(a) = if a is T(x) then x else 0 +//│ ╔══[ERROR] module T expects 0 parameter but found 1 parameter +//│ ║ l.69: fun foo(a) = if a is T(x) then x else 0 +//│ ╙── ^^^^ +//│ fun foo: anything -> error +//│ Code generation encountered an error: +//│ if expression was not desugared + + + +class C(x: Int, y: Str) +//│ class C(x: Int, y: Str) + + +:d +fun foo(c) = if c is C(a, b) then [a, b] +//│ 0. Typing TypingUnit(List(NuFunDef(None,Var(foo),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(c))))),If(IfThen(App(Var(is),Tup(List((None,Fld(_,Var(c))), (None,Fld(_,App(Var(C),Tup(List((None,Fld(_,Var(a))), (None,Fld(_,Var(b))))))))))),Tup(List((None,Fld(_,Var(a))), (None,Fld(_,Var(b)))))),None)))))) +//│ | 0. Created lazy type info for NuFunDef(None,Var(foo),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(c))))),If(IfThen(App(Var(is),Tup(List((None,Fld(_,Var(c))), (None,Fld(_,App(Var(C),Tup(List((None,Fld(_,Var(a))), (None,Fld(_,Var(b))))))))))),Tup(List((None,Fld(_,Var(a))), (None,Fld(_,Var(b)))))),None)))) +//│ | Completing fun foo = (c,) => if (is(c, C(a, b,),)) then [a, b,] +//│ | | Type params +//│ | | Params +//│ | | Type foo polymorphically? true && (0 === 0 || false || false +//│ | | 1. Typing term (c,) => if (is(c, C(a, b,),)) then [a, b,] +//│ | | | 1. Typing pattern [c,] +//│ | | | | 1. Typing pattern c +//│ | | | | 1. : c179' +//│ | | | 1. : (c179',) +//│ | | | 1. Typing term if (is(c, C(a, b,),)) then [a, b,] +//│ | | | | [Desugarer.destructPattern] scrutinee = Var(c); pattern = App(Var(C),Tup(List((None,Fld(_,Var(a))), (None,Fld(_,Var(b)))))) +//│ | | | | [Desugarer.destructPattern] Result: «c is Var(C)» +//│ | | | | Desugared term: case c of { C => let $unapp = (C).unapply(c,) in let a = ($unapp).0 in let b = ($unapp).1 in [a, b,] } +//│ | | | | 1. Typing term case c of { C => let $unapp = (C).unapply(c,) in let a = ($unapp).0 in let b = ($unapp).1 in [a, b,] } +//│ | | | | | 1. Typing term c +//│ | | | | | 1. : c179' +//│ | | | | | CONSTRAIN c179' & ⊤ intl ⊤ +//│ | | | | | var rfn: c :: ⊤ & #C & ⊤ +//│ | | | | | 2. Typing term let $unapp = (C).unapply(c,) in let a = ($unapp).0 in let b = ($unapp).1 in [a, b,] +//│ | | | | | | 2. Typing term (C).unapply(c,) +//│ | | | | | | | 2. Typing term (C).unapply +//│ | | | | | | | | 2. Typing term (x,) => let _ = x : C in [(x).#x, (x).#y,] +//│ | | | | | | | | | TYPING POLY LAM +//│ | | | | | | | | | 3. Typing pattern [x,] +//│ | | | | | | | | | | 3. Typing pattern x +//│ | | | | | | | | | | 3. : x181''' +//│ | | | | | | | | | 3. : (x181''',) +//│ | | | | | | | | | 3. Typing term let _ = x : C in [(x).#x, (x).#y,] +//│ | | | | | | | | | | 3. Typing term x : C +//│ | | | | | | | | | | | 3. Typing term x +//│ | | | | | | | | | | | 3. : x181''' +//│ | | | | | | | | | | | Typing type TypeName(C) +//│ | | | | | | | | | | | | vars=Map() newDefsInfo=Map() +//│ | | | | | | | | | | | | 3. type TypeName(C) +//│ | | | | | | | | | | | | => C +//│ | | | | | | | | | | | => C ——— +//│ | | | | | | | | | | | CONSTRAIN x181''' (#x182''', #y183''',)) —— where +//│ x181''' <: {#y: #y183'''} & {#x: #x182'''} & C +//│ | | | | | | | | 2. : ‹∀ 2. (x181''' -> (#x182''', #y183''',))› +//│ | | | | | | | 2. : ‹∀ 2. (x181''' -> (#x182''', #y183''',))› +//│ | | | | | | | 2. Typing term c +//│ | | | | | | | 2. : #C +//│ | | | | | | | CONSTRAIN ‹∀ 2. (x181''' -> (#x182''', #y183''',))› -> α184'') +//│ | | | | | | | where +//│ x181''' <: {#y: #y183'''} & {#x: #x182'''} & C +//│ | | | | | | | 2. C ‹∀ 2. (x181''' -> (#x182''', #y183''',))› -> α184'') (0) +//│ | | | | | | | | could be distribbed: Set(#x182''', #y183''') +//│ | | | | | | | | cannot be distribbed: Set(x181''', #x182''', #y183''') +//│ | | | | | | | | INST [2] ‹∀ 2. (x181''' -> (#x182''', #y183''',))› +//│ | | | | | | | | where +//│ x181''' <: {#y: #y183'''} & {#x: #x182'''} & C +//│ | | | | | | | | TO [2] ~> (x181_185'' -> (#x182_187'', #y183_186'',)) +//│ | | | | | | | | where +//│ x181_185'' <: {#y: #y183_186''} & {#x: #x182_187''} & C +//│ | | | | | | | | 2. C (x181_185'' -> (#x182_187'', #y183_186'',)) -> α184'') (2) +//│ | | | | | | | | | 2. C (#C,) (8) +//│ | | | | | | | | | | | | | Already a subtype by <:< +//│ | | | | | | | | | 2. C (#x182_187'', #y183_186'',) (#x182_187'', #y183_186'',) +//│ #y183_186'' :> Str +//│ #x182_187'' :> Int +//│ | | | | | | | | 2. C α184'' (#x182_187'', #y183_186'',) <: {0: α188''} +//│ #y183_186'' :> Str +//│ #x182_187'' :> Int <: α188'' +//│ α188'' :> Int +//│ | | | | | | | | | 2. C α184'' Int +//│ α189'' :> Str +//│ | | | | | 2. C (α188'', α189'',) Int +//│ | | | | | | | => α188_190' +//│ | | | | | | | EXTR[+] α189'' || 1 .. 1024 2 false +//│ | | | | | | | | EXTR[+] Str || 1 .. 1024 0 true +//│ | | | | | | | | => Str +//│ | | | | | | | => α189_191' +//│ | | | | | | => (α188_190', α189_191',) +//│ | | | | | | RECONSTRAINING TVs +//│ | | | | | | | Reconstraining α188_190' +//│ | | | | | | | Reconstraining α189_191' +//│ | | | | | | EXTR LHS ~> (α188_190', α189_191',) to 1 +//│ | | | | | | where +//│ α188_190' :> Int +//│ α189_191' :> Str +//│ | | | | | | 2. C (α188_190', α189_191',) ,⊤)] + List() and [α180'] | ⊥ +//│ | | | | | finishing case c179' <: #C +//│ | | | | | CONSTRAIN c179' +//│ | | | | | where +//│ c179' <: Object +//│ | | | | | 1. C c179' (0) +//│ | | | | | | NEW c179' UB (0) +//│ | | | | 1. : α180' +//│ | | | 1. : α180' +//│ | | 1. : (c179' -> α180') +//│ | | CONSTRAIN (c179' -> α180') & Object +//│ α180' :> (α188_190', α189_191',) +//│ α188_190' :> Int +//│ α189_191' :> Str +//│ | | 1. C (c179' -> α180') α180')) where +//│ c179' <: #C & Object +//│ α180' :> (α188_190', α189_191',) +//│ α188_190' :> Int +//│ α189_191' :> Str +//│ | Typing unit statements +//│ | : None +//│ ======== TYPED ======== +//│ fun foo: ‹∀ 0. (c179' -> α180')› where +//│ | c179' <: #C & Object +//│ | α180' :> (α188_190', α189_191',) +//│ | α188_190' :> Int +//│ | α189_191' :> Str +//│ fun foo: C -> [Int, Str] + + + + + + + + diff --git a/shared/src/test/diff/nu/NuScratch2.mls b/shared/src/test/diff/nu/NuScratch2.mls new file mode 100644 index 0000000000..a16dd2cfa3 --- /dev/null +++ b/shared/src/test/diff/nu/NuScratch2.mls @@ -0,0 +1,213 @@ +:NewDefs + +abstract class Foo0[type T] { + fun x: T +} +abstract class Bar0 extends Foo0[Int] +//│ abstract class Foo0[T] { +//│ fun x: T +//│ } +//│ abstract class Bar0 extends Foo0 { +//│ fun x: 'T +//│ } +//│ where +//│ 'T := Int + +abstract class Foo[type T]: (Bar | Baz) { + fun x: T + fun f: T -> Int +} +abstract class Bar extends Foo[Int] +abstract class Baz extends Foo[Str] +//│ abstract class Foo[T]: Bar | Baz { +//│ fun f: T -> Int +//│ fun x: T +//│ } +//│ abstract class Bar: Bar | Baz extends Foo { +//│ fun f: 'T -> Int +//│ fun x: 'T +//│ } +//│ abstract class Baz: Bar | Baz extends Foo { +//│ fun f: 'T0 -> Int +//│ fun x: 'T0 +//│ } +//│ where +//│ 'T0 := Str +//│ 'T := Int + +:e // Expected +fun test(f: Foo) = f.f(f.x) +//│ ╔══[ERROR] Type error in application +//│ ║ l.39: fun test(f: Foo) = f.f(f.x) +//│ ║ ^^^^^^^^ +//│ ╟── type variable `T` leaks out of its scope +//│ ║ l.17: fun x: T +//│ ║ ^^^^ +//│ ╟── back into type variable `T` +//│ ║ l.16: abstract class Foo[type T]: (Bar | Baz) { +//│ ╙── ^ +//│ fun test: (f: Foo[?]) -> (Int | error) + +fun test(f: Foo) = if f is + Foo then f.f(f.x) +//│ fun test: (f: Foo[?]) -> Int + +fun test(f: Foo) = if f is + Foo then f.x : f.T +//│ fun test: (f: Foo[?]) -> (??T & ??T0) + +// FIXME +fun test(f: Foo['a]) = if f is + Foo then f.x : f.T +//│ /!!!\ Uncaught error: java.lang.StackOverflowError + +fun test(f: Foo0['a]) = if f is + Foo0 then f.x : f.T // here, locally we have f.T =:= `T & 'a where `T is the local skolem for x.T +//│ fun test: forall 'a. (f: Foo0['a]) -> (??T & 'a) + +// * NOTE: refined f.T =:= `T & 'a +fun test(f: Foo0['a]) = if f is + Foo0 then f.x : f.T + _ then error +//│ fun test: forall 'a. (f: Foo0['a]) -> (??T & 'a) + +// * TODO: why don't we get 'a in the result whereas we do in the Foo0 case above? +fun test(f: Foo0['a]) = if f is + Bar0 then 123 : f.T + _ then error +//│ fun test: forall 'a. (f: Foo0['a]) -> (Int & 'a) + +// ^ What's haoppening: +// Bar & {} <: { T: 'l..'u } +// ^ What SHOULD be haoppening: +// Bar & Foo0['a] <: { T: 'l..'u } +// Notice that field T in `Bar & Foo0['a]` should yield `'a | Int .. 'a & Int` +// Alternative (not great; not clear how to do it generally/in a principled way): +// Bar & {T: 'a .. 'a } <: { T: 'l..'u } + + +fun test(x: 'a, g: Foo0[x], f: Foo0[x]) = if f is + Bar0 then 123 : g.T + _ then error +//│ fun test: forall 'a. (x: 'a, g: Foo0['a], f: Foo0['a]) -> 'a +//│ where +//│ 'a :> 123 + + +fun test(f: Foo) = if f is + Foo then f.f(f.x : f.T) +//│ fun test: (f: Foo[?]) -> Int + +fun test(f: Foo) = if f is + Bar then f.x + else error +//│ fun test: (f: Foo[?]) -> Int + +fun test(f: Foo) = if f is + Bar then f.x : f.T + else error +//│ fun test: (f: Foo[?]) -> Int + +// FIXME +fun test(f: Foo) = if f is + Bar then 123 : f.T + Baz then error +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.112: fun test(f: Foo) = if f is +//│ ║ ^^^^ +//│ ║ l.113: Bar then 123 : f.T +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.114: Baz then error +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Foo[?]` does not match type `Bar | Baz` +//│ ║ l.112: fun test(f: Foo) = if f is +//│ ║ ^^^ +//│ ╟── but it flows into reference with expected type `Bar | Baz` +//│ ║ l.112: fun test(f: Foo) = if f is +//│ ╙── ^ +//│ fun test: (f: Foo[?]) -> Int + +fun test(f: Foo) = if f is + Bar then 123 : f.T + Baz then "hello" : f.T + _ then error +//│ fun test: (f: Foo[?]) -> (Int | Str) + +// FIXME +fun test(f: Foo['a]) = if f is + Bar then 123 : f.T + Baz then "hello" : f.T + _ then error +//│ /!!!\ Uncaught error: java.lang.StackOverflowError + +fun test(f: Foo, x) = x : f.T +//│ fun test: (f: Foo[?], ??T) -> ??T0 + +// FIXME +fun test[A](f: Foo[A]): A = if f is + Bar then 123 : f.T + Baz then "hello" : f.T +//│ /!!!\ Uncaught error: java.lang.StackOverflowError + +// FIXME +fun test(f: Foo['a]): f.T = if f is + Bar then 123 : f.T + Baz then "hello" : f.T +//│ /!!!\ Uncaught error: java.lang.StackOverflowError + +// FIXME +:e // expected +test(error, 1) +//│ /!!!\ Uncaught error: java.lang.StackOverflowError + +// FIXME +fun test[T](f: Foo[T]): T = if f is + Bar then 123 : f.T + Baz then error +//│ /!!!\ Uncaught error: java.lang.StackOverflowError + +// FIXME +fun test(f: Foo['a]) = if f is + Foo then f.x +//│ /!!!\ Uncaught error: java.lang.StackOverflowError + +// * infinite loop in expand(Bar) (making Bar non abstract fixes the problem) +// * abstract Bar expands to `#Bar & (Bar | Baz)` +// * non abstract Bar expands to `#Bar` + +abstract class Foo[type T]: (Bar | Baz) { + fun x: T + fun f: T -> Int +} +class Bar(val x: Int) extends Foo[Int] { fun f(y) = this.x + y } +class Baz(val x: Str) extends Foo[Str] { fun f(y) = 0 } +//│ abstract class Foo[T]: Bar | Baz { +//│ fun f: T -> Int +//│ fun x: T +//│ } +//│ class Bar(x: Int) extends Foo { +//│ fun f: Int -> Int +//│ } +//│ class Baz(x: Str) extends Foo { +//│ fun f: anything -> 0 +//│ } + +fun test(f: Foo['a]) = if f is + Foo then f.x +//│ fun test: forall 'a. (f: Foo['a]) -> (Int | Str) + +abstract class Foo[T]: Bar { fun x: T } +abstract class Bar extends Foo[Int] +//│ abstract class Foo[T]: Bar { +//│ fun x: T +//│ } +//│ abstract class Bar: Bar extends Foo { +//│ fun x: 'T +//│ } +//│ where +//│ 'T := Int + +// FIXME +fun test(f: Foo['a]) = if f is + Foo then f.x +//│ /!!!\ Uncaught error: java.lang.StackOverflowError diff --git a/shared/src/test/diff/nu/NuScratch3.mls b/shared/src/test/diff/nu/NuScratch3.mls new file mode 100644 index 0000000000..f84992ce4a --- /dev/null +++ b/shared/src/test/diff/nu/NuScratch3.mls @@ -0,0 +1,19 @@ +:NewDefs + + + +class Arr[A](xs: A -> A) +//│ class Arr[A](xs: A -> A) + +module N extends Arr[nothing](id) +//│ module N extends Arr + +fun test(k) = id(x => k(if true then N else Arr(x))) +//│ fun test: forall 'A 'A0 'a. ((Arr[in 'A out 'A | 'A0] | N) -> 'a) -> (forall 'A1. (('A | 'A1) -> ('A0 & 'A1)) -> 'a) + +test(x => x)(id) +//│ Arr['A] | N +//│ res +//│ = N { class: [class N extends Arr] } + + diff --git a/shared/src/test/diff/nu/NuScratch4.mls b/shared/src/test/diff/nu/NuScratch4.mls new file mode 100644 index 0000000000..1303ab6f62 --- /dev/null +++ b/shared/src/test/diff/nu/NuScratch4.mls @@ -0,0 +1,157 @@ +:NewDefs +:NoJS + + +class Ref[T](x: T -> T) +//│ class Ref[T](x: T -> T) + + +// fun refined[A](r: Ref[A]) +// fun refined[A, B](r: A): A & Ref[B] +fun refined: forall 'A, 'B: (r: 'A) -> ('A & Ref['B]) +//│ fun refined: forall 'A 'B. (r: 'A) -> (Ref['B] & 'A) + +fun test(x: 'x) = + let foo() = refined(x) + foo +//│ fun test: forall 'x. (x: 'x) -> (forall 'B. () -> (Ref['B] & 'x)) + +// fun refined: forall 'A, 'B, 'C: (r: 'A, s: 'B) -> ('A & 'B & Ref['C]) +fun refined: forall 'A, 'B, 'C: (r: 'A, s: 'B) -> ('A & 'B) +//│ fun refined: forall 'A 'B. (r: 'A, s: 'B) -> ('A & 'B) + +// fun test(x: 'x) = +// let foo(y: Ref['r] & 'y) = y +// foo(x) + +:d +fun test(x: 'x) = + let foo(y) = refined(x, y) : Ref['r] + foo +//│ 0. Typing TypingUnit(List(NuFunDef(None,Var(test),None,List(),Left(Lam(Tup(List((Some(Var(x)),Fld(_,Var('x))))),Blk(List(NuFunDef(Some(false),Var(foo),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(y))))),Asc(App(Var(refined),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))),AppliedType(TypeName(Ref),List('r)))))), Var(foo)))))))) +//│ | 0. Created lazy type info for NuFunDef(None,Var(test),None,List(),Left(Lam(Tup(List((Some(Var(x)),Fld(_,Var('x))))),Blk(List(NuFunDef(Some(false),Var(foo),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(y))))),Asc(App(Var(refined),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))),AppliedType(TypeName(Ref),List('r)))))), Var(foo)))))) +//│ | Completing fun test = (x: 'x,) => {let foo = (y,) => refined(x, y,) : Ref['r]; foo} +//│ | | Type params +//│ | | Params +//│ | | Type test polymorphically? true && (0 === 0 || false || false +//│ | | 1. Typing term (x: 'x,) => {let foo = (y,) => refined(x, y,) : Ref['r]; foo} +//│ | | | 1. Typing pattern [x: 'x,] +//│ | | | | 1. Typing pattern x : 'x +//│ | | | | | Typing type 'x +//│ | | | | | | vars=Map() newDefsInfo=Map() +//│ | | | | | | 1. type 'x +//│ | | | | | | => 'x93' +//│ | | | | | => 'x93' ——— 'x93' +//│ | | | | 1. : 'x93' +//│ | | | 1. : (x: 'x93',) +//│ | | | 1. Typing term {let foo = (y,) => refined(x, y,) : Ref['r]; foo} +//│ | | | | 1. Typing TypingUnit(List(NuFunDef(Some(false),Var(foo),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(y))))),Asc(App(Var(refined),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))),AppliedType(TypeName(Ref),List('r)))))), Var(foo))) +//│ | | | | | 1. Created lazy type info for NuFunDef(Some(false),Var(foo),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(y))))),Asc(App(Var(refined),Tup(List((None,Fld(_,Var(x))), (None,Fld(_,Var(y)))))),AppliedType(TypeName(Ref),List('r)))))) +//│ | | | | | Completing let foo = (y,) => refined(x, y,) : Ref['r] +//│ | | | | | | Type params +//│ | | | | | | Params +//│ | | | | | | Type foo polymorphically? true && (1 === 0 || false || true +//│ | | | | | | 2. Typing term (y,) => refined(x, y,) : Ref['r] +//│ | | | | | | | 2. Typing pattern [y,] +//│ | | | | | | | | 2. Typing pattern y +//│ | | | | | | | | 2. : y94'' +//│ | | | | | | | 2. : (y94'',) +//│ | | | | | | | 2. Typing term refined(x, y,) : Ref['r] +//│ | | | | | | | | 2. Typing term refined(x, y,) +//│ | | | | | | | | | 2. Typing term refined +//│ | | | | | | | | | 2. : ‹∀ 0. ‹∀ 1. ((r: 'A81'', s: 'B82'',) -> ('A81'' & 'B82''))›› +//│ | | | | | | | | | 2. Typing term x +//│ | | | | | | | | | 2. : 'x93' +//│ | | | | | | | | | 2. Typing term y +//│ | | | | | | | | | 2. : y94'' +//│ | | | | | | | | | CONSTRAIN ‹∀ 0. ‹∀ 1. ((r: 'A81'', s: 'B82'',) -> ('A81'' & 'B82''))›› α95'') +//│ | | | | | | | | | where +//│ | | | | | | | | | 2. C ‹∀ 0. ‹∀ 1. ((r: 'A81'', s: 'B82'',) -> ('A81'' & 'B82''))›› α95'') (0) +//│ | | | | | | | | | | 2. C ‹∀ 1. ((r: 'A81'', s: 'B82'',) -> ('A81'' & 'B82''))› α95'') (2) +//│ | | | | | | | | | | | could be distribbed: Set('A81'', 'B82'') +//│ | | | | | | | | | | | cannot be distribbed: Set('A81'', 'B82'') +//│ | | | | | | | | | | | INST [1] ‹∀ 1. ((r: 'A81'', s: 'B82'',) -> ('A81'' & 'B82''))› +//│ | | | | | | | | | | | where +//│ | | | | | | | | | | | TO [2] ~> ((r: 'A81_96'', s: 'B82_97'',) -> ('A81_96'' & 'B82_97'')) +//│ | | | | | | | | | | | where +//│ | | | | | | | | | | | 2. C ((r: 'A81_96'', s: 'B82_97'',) -> ('A81_96'' & 'B82_97'')) α95'') (4) +//│ | | | | | | | | | | | | 2. C ('x93', y94'',) 'r98'' +//│ | | | | | | | | | => Ref['r98''] +//│ | | | | | | | | => Ref['r98''] ——— 'r98'' +//│ | | | | | | | | CONSTRAIN α95'' ('A81_96'' & 'B82_97'') +//│ 'A81_96'' :> 'x93' +//│ | | | | | | | | 2. C α95'' & {Ref#T: mut 'r98''..'r98''}) (4) +//│ | | | | | | | | | | | 2. C ('A81_96'' & 'B82_97'') (6) +//│ | | | | | | | | | | | | 2. ARGH DNF(2, 'A81_96''∧'B82_97'') {}) +//│ | | | | | | | | | | | | | DNF DISCHARGE CONSTRAINTS +//│ | | | | | | | | | | | | | 2. C 'A81_96'' | ~('B82_97'')) (8) +//│ | | | | | | | | | | | | | | NEW 'A81_96'' UB (2) +//│ | | | | | | | | | | | | | | 2. C 'x93' | ~('B82_97'')) (10) +//│ | | | | | | | | | | | | | | | 2. C 'B82_97'' ) (10) +//│ | | | | | | | | | | | | | | | | NEW 'B82_97'' UB (1) +//│ | | | | | | | | | | | 2. C ('A81_96'' & 'B82_97'') Ref['r98'']) +//│ | | | | | | CONSTRAIN (y94'' -> Ref['r98'']) ) +//│ | | | | | | 2. C (y94'' -> Ref['r98'']) Ref['r98''])) where +//│ y94'' <: 'B82_97'' +//│ 'B82_97'' <: (~('x93') | {Ref#T: mut 'r98''..'r98''}) & (~('x93') | #Ref) +//│ | | | | | Typing unit statements +//│ | | | | | | 1. Typing term foo +//│ | | | | | | 1. : ‹∀ 1. (y94'' -> Ref['r98''])› +//│ | | | | | : Some(‹∀ 1. (y94'' -> Ref['r98''])›) +//│ | | | 1. : ‹∀ 1. (y94'' -> Ref['r98''])› +//│ | | 1. : ((x: 'x93',) -> ‹∀ 1. (y94'' -> Ref['r98''])›) +//│ | | CONSTRAIN ((x: 'x93',) -> ‹∀ 1. (y94'' -> Ref['r98''])›) ) +//│ | | 1. C ((x: 'x93',) -> ‹∀ 1. (y94'' -> Ref['r98''])›) ‹∀ 1. (y94'' -> Ref['r98''])›)) where +//│ y94'' <: 'B82_97'' +//│ 'B82_97'' <: (~('x93') | {Ref#T: mut 'r98''..'r98''}) & (~('x93') | #Ref) +//│ | Typing unit statements +//│ | : None +//│ ======== TYPED ======== +//│ fun test: ‹∀ 0. ((x: 'x93',) -> ‹∀ 1. (y94'' -> Ref['r98''])›)› where +//│ | y94'' <: 'B82_97'' +//│ | 'B82_97'' <: (~('x93') | {Ref#T: mut 'r98''..'r98''}) & (~('x93') | #Ref) +//│ fun test: forall 'x. (x: 'x) -> (forall 'r. (Ref['r] | ~'x) -> Ref['r]) + + + + + diff --git a/shared/src/test/diff/nu/Object.mls b/shared/src/test/diff/nu/Object.mls index 9e93dec27b..dbb080aff9 100644 --- a/shared/src/test/diff/nu/Object.mls +++ b/shared/src/test/diff/nu/Object.mls @@ -53,7 +53,7 @@ fun foo(x: anything) = if x is A then true //│ ╟── Note: constraint arises from class pattern: //│ ║ l.34: fun foo(x: anything) = if x is A then true //│ ╙── ^ -//│ fun foo: (x: anything) -> true +//│ fun foo: (x: anything) -> (error | true) :e fun foo(x: anything) = if x is A then true else false diff --git a/shared/src/test/diff/nu/Parens.mls b/shared/src/test/diff/nu/Parens.mls index 12a9306ee0..b89ca91c6f 100644 --- a/shared/src/test/diff/nu/Parens.mls +++ b/shared/src/test/diff/nu/Parens.mls @@ -68,7 +68,7 @@ val x: (1,) :e val x: (1, 2) -//│ ╔══[ERROR] type identifier not found: , +//│ ╔══[ERROR] cannot lift variable , to type //│ ║ l.70: val x: (1, 2) //│ ╙── ^^^^^^ //│ val x: error @@ -77,7 +77,7 @@ val x: (1, 2) :e val x: (1, 2,) -//│ ╔══[ERROR] type identifier not found: , +//│ ╔══[ERROR] cannot lift variable , to type //│ ║ l.79: val x: (1, 2,) //│ ╙── ^^^^^^^ //│ val x: error diff --git a/shared/src/test/diff/nu/PolymorphicVariants_Alt.mls b/shared/src/test/diff/nu/PolymorphicVariants_Alt.mls index e127c1b673..f2b7e7b25f 100644 --- a/shared/src/test/diff/nu/PolymorphicVariants_Alt.mls +++ b/shared/src/test/diff/nu/PolymorphicVariants_Alt.mls @@ -60,7 +60,7 @@ mixin EvalVar { Success(r) then r } //│ mixin EvalVar() { -//│ fun eval: (List[{0: Str, 1: 'a}], Var) -> (Var | 'a) +//│ fun eval: (List[{0: Str, 1: 'b}], Var) -> (Var | ??A & 'b) //│ } class Abs(x: Str, t: A) @@ -96,18 +96,20 @@ mixin EvalLambda { //│ mixin EvalLambda() { //│ super: {eval: ('b, 'c) -> 'd} //│ this: { -//│ eval: ('b, 'e) -> 'A & (List[[Str, 'A]], 'f) -> 'd & (List[[Str, Var] | 'a], 'g) -> 'A0 +//│ eval: ('b, ??A & 'A) -> 'e & (List[[Str, 'e]], ??A0 & 'A0) -> 'd & (List[[Str, Var] | 'a], ??A1 & 'A1) -> 'f //│ } -//│ fun eval: (List['a] & 'b, Abs['g] | App['e & (Abs['f] | Object & ~#Abs)] | Object & 'c & ~#Abs & ~#App) -> (Abs['A0] | App['A] | 'd) +//│ fun eval: (List['a] & 'b, Abs['A1] | App['A & (Abs['A0] | Object & ~#Abs | ~??A)] | Object & 'c & ~#Abs & ~#App) -> (Abs['f] | App['e] | 'd) //│ } module Test1 extends EvalVar, EvalLambda //│ module Test1 { -//│ fun eval: (List[{0: Str, 1: 'a}], 'b) -> 'a +//│ fun eval: (List[{0: Str, 1: 'b}], Abs['A] | App['A0] | Var) -> 'a //│ } //│ where -//│ 'b <: Abs['b] | App['b & (Abs['b] | Object & ~#Abs)] | Var -//│ 'a :> Abs['a] | App['a] | Var +//│ 'A <: Abs['A] | App['A0] | Var | ~??A +//│ 'A0 <: Abs['A] & ~#Abs | Abs['A & (Abs['A] | App['A0] | Var | ~??A0)] | App['A0] | Var | ~??A1 +//│ 'b :> 'a +//│ 'a :> Abs['a] | App['a] | Var | ??A2 & 'b Test1.eval(Nil(), Var("a")) //│ 'a @@ -125,9 +127,9 @@ Test1.eval(Cons(["c", Var("d")], Nil()), App(Abs("b", Var("b")), Var("c"))) //│ 'a :> Abs['a] | App['a] | Var Test1.eval(Cons(["c", Abs("d", Var("d"))], Nil()), App(Abs("b", Var("b")), Var("c"))) -//│ Abs['a] | 'a +//│ 'a //│ where -//│ 'a :> Abs['a] | App['a] | Var +//│ 'a :> Abs['a] | Abs[Var] & ??A | App['a] | Var class Numb(n: Int) class Add(l: A, r: A) @@ -142,7 +144,7 @@ fun map_expr(f, v) = Numb then v Add(l, r) then Add(f(l), f(r)) Mul(l, r) then Mul(f(l), f(r)) -//│ fun map_expr: forall 'a 'A 'b 'A0. ('a -> 'A & 'b -> 'A0, Add['a] | Mul['b] | Numb | Var) -> (Add['A] | Mul['A0] | Numb | Var) +//│ fun map_expr: forall 'A 'a 'A0 'b. ((??A & 'A) -> 'a & (??A0 & 'A0) -> 'b, Add['A] | Mul['A0] | Numb | Var) -> (Add['a] | Mul['b] | Numb | Var) mixin EvalExpr { fun eval(sub, v) = @@ -156,57 +158,60 @@ mixin EvalExpr { } //│ mixin EvalExpr() { //│ super: {eval: ('a, Var) -> 'b} -//│ this: {eval: ('a, 'c) -> Object} -//│ fun eval: ('a, 'b & (Add['c] | Mul['c] | Numb | Var)) -> (Numb | 'b) +//│ this: {eval: ('a, ??A & 'A | ??A0 & 'A0) -> (Numb | Object & ~#Numb)} +//│ fun eval: ('a, 'b & (Add['A0] | Mul['A] | Numb | Var)) -> (Numb | 'b) //│ } module Test2 extends EvalVar, EvalExpr //│ module Test2 { -//│ fun eval: forall 'a. (List[{0: Str, 1: Object & 'b}], 'a & (Add['c] | Mul['c] | Numb | Var)) -> (Numb | Var | 'b | 'c | 'a) +//│ fun eval: forall 'a. (List[{0: Str, 1: 'b & (Numb | Object & ~#Numb | ~??A)}], 'a & (Add['A] | Mul['A0] | Numb | Var)) -> (Numb | Var | ??A & 'b | ??A0 & 'A | ??A1 & 'A0 | 'a) //│ } //│ where -//│ 'c <: Add['c] | Mul['c] | Numb | Var +//│ 'A <: Add['A] | Mul['A0] | Numb | Var | ~??A0 +//│ 'A0 <: Add['A] | Mul['A0] | Numb | Var | ~??A1 Test2.eval(Nil(), Var("a")) //│ Numb | Var Test2.eval(Cons(["c", Abs("d", Var("d"))], Nil()), Var("a")) -//│ Abs[Var] | Numb | Var +//│ Abs[Var] & ??A | Numb | Var Test2.eval(Cons(["a", Numb(1)], Nil()), Var("a")) //│ Numb | Var Test2.eval(Cons(["a", Abs("d", Var("d"))], Nil()), Add(Numb(1), Var("a"))) -//│ Abs[Var] | Add[Numb | Var] | Numb | Var +//│ Abs[Var] & ??A | Add[Numb | Var] | Numb & ??A0 | Var module Test3 extends EvalVar, EvalExpr, EvalLambda //│ module Test3 { -//│ fun eval: (List[{0: Str, 1: 'a}], 'b) -> (Abs['c] | App['c] | 'c) +//│ fun eval: (List[{0: Str, 1: 'b}], Abs['A] | App['A0] | Object & 'a & ~#Abs & ~#App) -> 'c //│ } //│ where -//│ 'a :> 'c -//│ <: Object -//│ 'c :> 'a | 'd -//│ 'd <: Add['b] | Mul['b] | Numb | Var -//│ 'b <: Abs['b] | App['b & (Abs['b] | Object & ~#Abs)] | Object & 'd & ~#Abs & ~#App +//│ 'b :> 'c +//│ <: Numb | Object & ~#Numb | ~??A +//│ 'c :> Abs['c] | App['c] | Numb | Var | ??A & 'b | 'a +//│ 'a <: Add[Abs['A] | App['A0] | Object & 'a & ~#Abs & ~#App | ~??A0] | Mul[Abs['A] | App['A0] | Object & 'a & ~#Abs & ~#App | ~??A1] | Numb | Var +//│ 'A <: Abs['A] | App['A0] | Object & 'a & ~#Abs & ~#App | ~??A2 +//│ 'A0 <: Abs['A] & ~#Abs | Abs['A & (Abs['A] | App['A0] | Object & 'a & ~#Abs & ~#App | ~??A3)] | App['A0] | Object & 'a & ~#Abs & ~#App | ~??A4 Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil()), Abs("a", Var("a"))) -//│ Abs['a] | 'a +//│ 'a //│ where -//│ 'a :> Abs['a] | App['a] | Numb | Var +//│ 'a :> Abs['a] | Abs[Var] & ??A | App['a] | Numb | Var & ??A0 Test3.eval(Cons(["c", Abs("d", Var("d"))], Nil()), App(Abs("a", Var("a")), Add(Numb(1), Var("c")))) -//│ Abs['a] | 'a +//│ 'a //│ where -//│ 'a :> Abs['a] | Add[Numb | Var] | App['a] | Numb | Var +//│ 'a :> Abs['a] | Abs[Var] & ??A | Add[Numb | Var] & ??A0 | App['a] | Numb & ??A1 | Var & ??A2 module Test3 extends EvalVar, EvalLambda, EvalExpr //│ module Test3 { -//│ fun eval: (List[{0: Str, 1: 'a}], 'a & (Add['b] | Mul['b] | Numb | Var)) -> (Numb | 'c | 'a | 'b) +//│ fun eval: (List[{0: Str, 1: 'b}], 'a & (Add['A] | Mul['A0] | Numb | Var)) -> (??A & 'A | ??A0 & 'A0 | 'a) //│ } //│ where -//│ 'a :> 'c | 'b -//│ <: Object -//│ 'b <: Add['b] | Mul['b] | Numb | Var -//│ 'c :> Abs['c | 'a] | App['c | 'a] | 'a +//│ 'b :> ??A & 'A | ??A0 & 'A0 | 'a +//│ <: Numb | Object & ~#Numb | Object & ~??A1 | ~??A1 +//│ 'a :> Abs[??A & 'A | ??A0 & 'A0 | 'a] | App[??A & 'A | ??A0 & 'A0 | 'a] | Numb | Var | ??A & 'A | ??A0 & 'A0 | ??A1 & 'b +//│ 'A <: Add['A] | Mul['A0] | Numb | Var | ~??A +//│ 'A0 <: Add['A] | Mul['A0] | Numb | Var | ~??A0 diff --git a/shared/src/test/diff/nu/RawTypes.mls b/shared/src/test/diff/nu/RawTypes.mls new file mode 100644 index 0000000000..1bf223bd38 --- /dev/null +++ b/shared/src/test/diff/nu/RawTypes.mls @@ -0,0 +1,143 @@ +:NewDefs + +// * currently +// Foo => Foo[?] ? is rigid can be uncovered in pattern matching +// * future +// Foo => Foo['a] can place bounds on 'a + +class Foo[type A](val a: A) +//│ class Foo[A](a: A) + +:e +fun foo(f: Foo): Int = f.a : f.A +//│ ╔══[ERROR] Type error in type ascription +//│ ║ l.12: fun foo(f: Foo): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.12: fun foo(f: Foo): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── back into type variable `A` +//│ ║ l.12: fun foo(f: Foo): Int = f.a : f.A +//│ ╙── ^^ +//│ ╔══[ERROR] Type error in type ascription +//│ ║ l.12: fun foo(f: Foo): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.12: fun foo(f: Foo): Int = f.a : f.A +//│ ║ ^^ +//│ ╟── into type `Int` +//│ ║ l.12: fun foo(f: Foo): Int = f.a : f.A +//│ ╙── ^^^ +//│ fun foo: (f: Foo[anything]) -> Int + +// :s +// :ds +fun foo(f: Foo[?]) = f.a +//│ fun foo: (f: Foo[anything]) -> anything + +// TODO +fun foo(f: Foo[?]) = f.a : f.A +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.39: fun foo(f: Foo[?]) = f.a : f.A +//│ ║ ^^^ +//│ ╟── field selection of type `anything` does not match type `nothing` +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.39: fun foo(f: Foo[?]) = f.a : f.A +//│ ╙── ^^ +//│ fun foo: (f: Foo[anything]) -> anything + +foo(Foo(1)) +//│ anything +//│ res +//│ = 1 + +fun foo(f: Foo) = f.a +//│ fun foo: (f: Foo[anything]) -> ??A + +fun foo(f: Foo[Int]) = f.a +//│ fun foo: (f: Foo[Int]) -> Int + +fun foo(f: Foo[?]) = if f is Foo(a) then a : f.A +//│ fun foo: (f: Foo[anything]) -> ??A + +:e +fun foo(f: Foo): Int = if f is Foo(a) then a : f.A +//│ ╔══[ERROR] Type error in `case` expression +//│ ║ l.64: fun foo(f: Foo): Int = if f is Foo(a) then a : f.A +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.8: class Foo[type A](val a: A) +//│ ║ ^ +//│ ╟── into type `Int | ~??A` +//│ ║ l.64: fun foo(f: Foo): Int = if f is Foo(a) then a : f.A +//│ ║ ^^^ +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.64: fun foo(f: Foo): Int = if f is Foo(a) then a : f.A +//│ ╙── ^^ +//│ fun foo: (f: Foo[anything]) -> (Int | error) + +:e +fun foo(f: Foo[?]): Int = if f is Foo(a) then a : f.A else 0 +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.80: fun foo(f: Foo[?]): Int = if f is Foo(a) then a : f.A else 0 +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╟── expression of type `anything` does not match type `Int | ~??A` +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.80: fun foo(f: Foo[?]): Int = if f is Foo(a) then a : f.A else 0 +//│ ║ ^^^ +//│ ╟── from type selection: +//│ ║ l.80: fun foo(f: Foo[?]): Int = if f is Foo(a) then a : f.A else 0 +//│ ║ ^^ +//│ ╟── Note: type parameter A is defined at: +//│ ║ l.8: class Foo[type A](val a: A) +//│ ╙── ^ +//│ fun foo: (f: Foo[anything]) -> Int + +fun foo(f: Foo['a]) = f.a : f.A +//│ fun foo: forall 'a. (f: Foo['a]) -> 'a + +fun foo(a, f: Foo[a]): Int = f.a : f.A +//│ fun foo: forall 'a. ('a, f: Foo['a]) -> Int +//│ where +//│ 'a <: Int + +fun bar(f): Int = f.a : f.A +//│ fun bar: forall 'A. {A :> 'A <: Int, a: 'A} -> Int + +foo(2, Foo(1)) +//│ Int +//│ res +//│ = 1 + +bar(Foo(1)) +//│ Int +//│ res +//│ = 1 + +class Foo[A](val a: A -> A) +//│ class Foo[A](a: A -> A) + +fun foo(f: Foo) = f.a +//│ fun foo: (f: Foo[?]) -> ??A -> ??A0 + +fun foo(f: Foo) = () +//│ fun foo: (f: Foo[?]) -> () + +fun foo(f) = f : Foo +//│ fun foo: Foo[?] -> Foo[?] + +abstract class Foo[type T]: Bar +class Bar(val b: Int) extends Foo[Int] +//│ abstract class Foo[T]: Bar +//│ class Bar(b: Int) extends Foo + +fun foo(x: Foo[?]) = if x is Bar then x.b : x.T +//│ fun foo: (x: Foo[?]) -> Int + +foo(Bar(1)) +//│ Int +//│ res +//│ = 1 + +fun foo(x: Foo['a]) = if x is Bar then x.b : x.T +//│ fun foo: forall 'a. (x: Foo['a]) -> (Int & 'a) diff --git a/shared/src/test/diff/nu/RawUnionTraitSignatures.mls b/shared/src/test/diff/nu/RawUnionTraitSignatures.mls index d2671a4aef..47d80267b7 100644 --- a/shared/src/test/diff/nu/RawUnionTraitSignatures.mls +++ b/shared/src/test/diff/nu/RawUnionTraitSignatures.mls @@ -89,7 +89,14 @@ trait Base2: Foo['FigureItOut] //│ = [Function: res] // :e +// FIXME (b: Base2) => b : Foo['X] +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.93: (b: Base2) => b : Foo['X] +//│ ║ ^ +//│ ╟── type `??FigureItOut` does not match type `??FigureItOut0` +//│ ║ l.93: (b: Base2) => b : Foo['X] +//│ ╙── ^^ //│ forall 'X. (b: Base2) -> Foo['X] //│ where //│ 'X :> ??FigureItOut @@ -101,7 +108,7 @@ trait Base2: Foo['FigureItOut] :e class Impl extends Base2 //│ ╔══[ERROR] Type mismatch in type declaration: -//│ ║ l.102: class Impl extends Base2 +//│ ║ l.109: class Impl extends Base2 //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── expression of type `#Impl` is not an instance of type `Foo` //│ ╟── Note: constraint arises from applied type reference: @@ -117,19 +124,19 @@ class Impl extends Base2 :e (x: Impl) => x : Base2 //│ ╔══[ERROR] Type mismatch in type ascription: -//│ ║ l.118: (x: Impl) => x : Base2 +//│ ║ l.125: (x: Impl) => x : Base2 //│ ║ ^ //│ ╟── type `Impl` is not an instance of type `Foo` -//│ ║ l.118: (x: Impl) => x : Base2 +//│ ║ l.125: (x: Impl) => x : Base2 //│ ║ ^^^^ //│ ╟── but it flows into reference with expected type `#Foo` -//│ ║ l.118: (x: Impl) => x : Base2 +//│ ║ l.125: (x: Impl) => x : Base2 //│ ║ ^ //│ ╟── Note: constraint arises from applied type reference: //│ ║ l.78: trait Base2: Foo['FigureItOut] //│ ║ ^^^^^^^^^^^^^^^^^ //│ ╟── from type reference: -//│ ║ l.118: (x: Impl) => x : Base2 +//│ ║ l.125: (x: Impl) => x : Base2 //│ ╙── ^^^^^ //│ (x: Impl) -> Base2 //│ res @@ -138,13 +145,13 @@ class Impl extends Base2 :e class Impl() extends Base2, Foo //│ ╔══[ERROR] Type error in type declaration -//│ ║ l.139: class Impl() extends Base2, Foo +//│ ║ l.146: class Impl() extends Base2, Foo //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── type variable `'FigureItOut` leaks out of its scope //│ ║ l.78: trait Base2: Foo['FigureItOut] //│ ╙── ^^^^^^^^^^^^ //│ ╔══[ERROR] Member `x` is declared (or its declaration is inherited) but is not implemented in `Impl` -//│ ║ l.139: class Impl() extends Base2, Foo +//│ ║ l.146: class Impl() extends Base2, Foo //│ ║ ^^^^ //│ ╟── Declared here: //│ ║ l.5: trait Foo[A] { fun x: A } @@ -158,11 +165,11 @@ class Impl() extends Base2, Foo { fun x = 1 } //│ ╔══[ERROR] Type error in type declaration -//│ ║ l.157: class Impl() extends Base2, Foo { +//│ ║ l.164: class Impl() extends Base2, Foo { //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.158: fun x = 1 +//│ ║ l.165: fun x = 1 //│ ║ ^^^^^^^^^^^ -//│ ║ l.159: } +//│ ║ l.166: } //│ ║ ^ //│ ╟── type variable `'FigureItOut` leaks out of its scope //│ ║ l.78: trait Base2: Foo['FigureItOut] @@ -179,10 +186,10 @@ Impl().x :e Impl() : Base2 //│ ╔══[ERROR] Type error in type ascription -//│ ║ l.180: Impl() : Base2 +//│ ║ l.187: Impl() : Base2 //│ ║ ^^^^^^ //│ ╟── type variable `'FigureItOut` leaks out of its scope -//│ ║ l.158: fun x = 1 +//│ ║ l.165: fun x = 1 //│ ╙── ^ //│ Base2 //│ res @@ -191,10 +198,10 @@ Impl() : Base2 :e (Impl() : Base2).x //│ ╔══[ERROR] Type error in type ascription -//│ ║ l.192: (Impl() : Base2).x +//│ ║ l.199: (Impl() : Base2).x //│ ║ ^^^^^^ //│ ╟── type variable `'FigureItOut` leaks out of its scope -//│ ║ l.158: fun x = 1 +//│ ║ l.165: fun x = 1 //│ ╙── ^ //│ ??FigureItOut //│ res @@ -205,27 +212,27 @@ class Impl2() extends Base2, Foo[Int] { fun x = 1 } //│ ╔══[ERROR] Type error in type declaration -//│ ║ l.204: class Impl2() extends Base2, Foo[Int] { +//│ ║ l.211: class Impl2() extends Base2, Foo[Int] { //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.205: fun x = 1 +//│ ║ l.212: fun x = 1 //│ ║ ^^^^^^^^^^^ -//│ ║ l.206: } +//│ ║ l.213: } //│ ║ ^ //│ ╟── type variable `'FigureItOut` leaks out of its scope -//│ ║ l.204: class Impl2() extends Base2, Foo[Int] { +//│ ║ l.211: class Impl2() extends Base2, Foo[Int] { //│ ╙── ^^^ //│ ╔══[ERROR] Type error in type declaration -//│ ║ l.204: class Impl2() extends Base2, Foo[Int] { +//│ ║ l.211: class Impl2() extends Base2, Foo[Int] { //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.205: fun x = 1 +//│ ║ l.212: fun x = 1 //│ ║ ^^^^^^^^^^^ -//│ ║ l.206: } +//│ ║ l.213: } //│ ║ ^ //│ ╟── type variable `'FigureItOut` leaks out of its scope //│ ║ l.78: trait Base2: Foo['FigureItOut] //│ ║ ^^^^^^^^^^^^ //│ ╟── into type `Int` -//│ ║ l.204: class Impl2() extends Base2, Foo[Int] { +//│ ║ l.211: class Impl2() extends Base2, Foo[Int] { //│ ╙── ^^^ //│ class Impl2() extends Base2, Foo { //│ fun x: 1 @@ -234,10 +241,10 @@ class Impl2() extends Base2, Foo[Int] { :e (Impl2() : Base2).x //│ ╔══[ERROR] Type error in type ascription -//│ ║ l.235: (Impl2() : Base2).x +//│ ║ l.242: (Impl2() : Base2).x //│ ║ ^^^^^^^ //│ ╟── type variable `'FigureItOut` leaks out of its scope -//│ ║ l.204: class Impl2() extends Base2, Foo[Int] { +//│ ║ l.211: class Impl2() extends Base2, Foo[Int] { //│ ╙── ^^^ //│ ??FigureItOut //│ res diff --git a/shared/src/test/diff/nu/TODO_Classes.mls b/shared/src/test/diff/nu/TODO_Classes.mls index 03707081cf..d3f50bc790 100644 --- a/shared/src/test/diff/nu/TODO_Classes.mls +++ b/shared/src/test/diff/nu/TODO_Classes.mls @@ -15,7 +15,7 @@ class D(x: Int) :e fun foo(c) = new c -//│ ╔══[ERROR] type identifier not found: c +//│ ╔══[ERROR] Unexpected type `?a` after `new` keyword //│ ║ l.17: fun foo(c) = new c //│ ╙── ^ //│ fun foo: anything -> error @@ -39,7 +39,7 @@ foo(C) :e fun bar(c) = new c(123) -//│ ╔══[ERROR] type identifier not found: c +//│ ╔══[ERROR] Unexpected type `?a` after `new` keyword //│ ║ l.41: fun bar(c) = new c(123) //│ ╙── ^ //│ fun bar: anything -> error @@ -100,10 +100,13 @@ let c = new Cls // FIXME let y: c.A = c.x -//│ ╔══[ERROR] type identifier not found: c +//│ ╔══[ERROR] Type `Cls[?A]` does not contain member `A` //│ ║ l.102: let y: c.A = c.x -//│ ╙── ^ -//│ /!!!\ Uncaught error: scala.NotImplementedError: an implementation is missing +//│ ╙── ^^ +//│ let y: error +//│ y +//│ Runtime error: +//│ RangeError: Maximum call stack size exceeded @@ -118,36 +121,14 @@ class Cls[A] { fun x: A = x; fun g: A -> Int; fun g = g } //│ } -:e // TODO fun test(a: Object) = if a is Cls then a.x else error -//│ ╔══[ERROR] Type error in `case` expression -//│ ║ l.122: fun test(a: Object) = if a is -//│ ║ ^^^^ -//│ ║ l.123: Cls then a.x -//│ ║ ^^^^^^^^^^^^^^ -//│ ║ l.124: else error -//│ ║ ^^^^^^^^^^^^ -//│ ╟── type variable `A` leaks out of its scope -//│ ║ l.113: class Cls[A] { fun x: A = x; fun g: A -> Int; fun g = g } -//│ ╙── ^ -//│ fun test: (a: Object) -> anything - -:e // TODO +//│ fun test: (a: Object) -> (??A & ??A0) + fun test(a: Object) = if a is Cls then a.g(a.x) // a.x : a.A ; a.g : a.A -> a.A else 0 -//│ ╔══[ERROR] Type error in `case` expression -//│ ║ l.138: fun test(a: Object) = if a is -//│ ║ ^^^^ -//│ ║ l.139: Cls then a.g(a.x) // a.x : a.A ; a.g : a.A -> a.A -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.140: else 0 -//│ ║ ^^^^^^^^ -//│ ╟── type variable `A` leaks out of its scope -//│ ║ l.113: class Cls[A] { fun x: A = x; fun g: A -> Int; fun g = g } -//│ ╙── ^ //│ fun test: (a: Object) -> Int @@ -160,16 +141,16 @@ class Cls[out A] { fun x: A = x } fun test(a: Object) = if a is Cls then a.x else error -//│ fun test: (a: Object) -> ??A +//│ fun test: (a: Object) -> (??A & ??A0) fun test(a: Object) = if a is Cls then a else error -//│ fun test: (a: Object) -> Cls[??A] +//│ fun test: (a: Object) -> Cls[??A & ??A0] :re test(0).x -//│ ??A +//│ ??A & ??A0 //│ res //│ Runtime error: //│ Error: an error was thrown @@ -210,11 +191,11 @@ fun test(f: ((IntLit | BoolLit) -> Int)) = :e class OopsLit() extends Expr[Bool] //│ ╔══[ERROR] Type mismatch in type declaration: -//│ ║ l.211: class OopsLit() extends Expr[Bool] +//│ ║ l.192: class OopsLit() extends Expr[Bool] //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── expression of type `#OopsLit` does not match type `BoolLit | IntLit` //│ ╟── Note: constraint arises from union type: -//│ ║ l.199: abstract class Expr[A]: (IntLit | BoolLit) {} +//│ ║ l.180: abstract class Expr[A]: (IntLit | BoolLit) {} //│ ╙── ^^^^^^^^^^^^^^^^^^ //│ class OopsLit() extends Expr diff --git a/shared/src/test/diff/nu/TypeMemberBounds.mls b/shared/src/test/diff/nu/TypeMemberBounds.mls new file mode 100644 index 0000000000..ef749a3f8d --- /dev/null +++ b/shared/src/test/diff/nu/TypeMemberBounds.mls @@ -0,0 +1,110 @@ +:NewDefs + +class Foo[] +//│ class Foo { +//│ constructor() +//│ } + +class Foo[A restricts Bool] +//│ class Foo[A] { +//│ constructor() +//│ } + +class Foo[A extends Int] +//│ class Foo[A] { +//│ constructor() +//│ } + +class Foo[type A restricts Int extends Int] +//│ class Foo[A] { +//│ constructor() +//│ } + +class Foo[in A restricts Int] +//│ class Foo[A] { +//│ constructor() +//│ } + + +class Foo[A restricts Bool, B extends Int] +//│ class Foo[A, B] { +//│ constructor() +//│ } + +:pe +class Foo[type restricts] +//│ ╔══[PARSE ERROR] dangling visible type member +//│ ║ l.35: class Foo[type restricts] +//│ ╙── ^^^^ +//│ ╔══[PARSE ERROR] Unexpected 'restricts' keyword here +//│ ║ l.35: class Foo[type restricts] +//│ ╙── ^^^^^^^^^ +//│ class Foo { +//│ constructor() +//│ } + +:pe +class Foo[type extends] +//│ ╔══[PARSE ERROR] dangling visible type member +//│ ║ l.47: class Foo[type extends] +//│ ╙── ^^^^ +//│ ╔══[PARSE ERROR] Unexpected 'extends' keyword here +//│ ║ l.47: class Foo[type extends] +//│ ╙── ^^^^^^^ +//│ class Foo { +//│ constructor() +//│ } + +:pe +class Foo[restricts Int] +//│ ╔══[PARSE ERROR] Unexpected 'restricts' keyword here +//│ ║ l.59: class Foo[restricts Int] +//│ ╙── ^^^^^^^^^ +//│ class Foo { +//│ constructor() +//│ } + +:pe +class Foo[restricts extends] +//│ ╔══[PARSE ERROR] Unexpected 'restricts' keyword here +//│ ║ l.68: class Foo[restricts extends] +//│ ╙── ^^^^^^^^^ +//│ class Foo { +//│ constructor() +//│ } + +:pe +class Foo[extends Int] +//│ ╔══[PARSE ERROR] Unexpected 'extends' keyword here +//│ ║ l.77: class Foo[extends Int] +//│ ╙── ^^^^^^^ +//│ class Foo { +//│ constructor() +//│ } + +:pe +class Foo[A extends] +//│ ╔══[PARSE ERROR] dangling extends keyword +//│ ║ l.86: class Foo[A extends] +//│ ╙── ^^^^^^^ +//│ class Foo[A] { +//│ constructor() +//│ } + +:pe +class Foo[B restricts] +//│ ╔══[PARSE ERROR] dangling restricts keyword +//│ ║ l.95: class Foo[B restricts] +//│ ╙── ^^^^^^^^^ +//│ class Foo[B] { +//│ constructor() +//│ } + +:pe +class Foo[extends] +//│ ╔══[PARSE ERROR] Unexpected 'extends' keyword here +//│ ║ l.104: class Foo[extends] +//│ ╙── ^^^^^^^ +//│ class Foo { +//│ constructor() +//│ } diff --git a/shared/src/test/diff/nu/TypeMembers.mls b/shared/src/test/diff/nu/TypeMembers.mls new file mode 100644 index 0000000000..26725feb19 --- /dev/null +++ b/shared/src/test/diff/nu/TypeMembers.mls @@ -0,0 +1,94 @@ +:NewDefs + + +class Test { type T = Int } +//│ class Test { +//│ constructor() +//│ } + +1 : Test.T +//│ Int +//│ res +//│ = 1 + + +trait Test { type T = Int } +//│ trait Test + +1 : Test.T +//│ Int +//│ res +//│ = 1 + +// TODO inspect +class Foo[T](x: T) { + type T = T +} +//│ class Foo[T](x: T) + +1 : Foo(1).T +//│ 1 +//│ res +//│ = 1 + +:e +false : Foo(1).T +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.35: false : Foo(1).T +//│ ║ ^^^^^ +//│ ╟── reference of type `false` does not match type `1` +//│ ╟── Note: constraint arises from literal type: +//│ ║ l.35: false : Foo(1).T +//│ ║ ^ +//│ ╟── from type selection: +//│ ║ l.35: false : Foo(1).T +//│ ╙── ^^ +//│ 1 +//│ res +//│ = false + +:e +class Foo[type T](x: T) { + type T = T +} +//│ ╔══[ERROR] Class type member 'T' already exists +//│ ║ l.52: type T = T +//│ ╙── ^^^^^^ +//│ class Foo[T](x: T) + +:e +class Foo[type T](x: Int) { + type T = Int +} +//│ ╔══[ERROR] Class type member 'T' already exists +//│ ║ l.61: type T = Int +//│ ╙── ^^^^^^ +//│ class Foo[T](x: Int) + +abstract class Foo { type T = Int } +//│ abstract class Foo + +:e +class Bar extends Foo { type T = Bool } +//│ ╔══[ERROR] Inherited parameter named 'T' is not virtual and cannot be overridden +//│ ╙── Originally declared here: +//│ class Bar extends Foo { +//│ constructor() +//│ } + +abstract class Foo[type T] +//│ abstract class Foo[T] + +// TODO +class Bar extends Foo { type T = Bool } +//│ ╔══[ERROR] Inherited parameter named 'T' is not virtual and cannot be overridden +//│ ╟── Originally declared here: +//│ ║ l.79: abstract class Foo[type T] +//│ ╙── ^ +//│ class Bar extends Foo { +//│ constructor() +//│ } + +// TODO +module Foo { type A = A } +//│ module Foo diff --git a/shared/src/test/diff/nu/TypeSel.mls b/shared/src/test/diff/nu/TypeSel.mls new file mode 100644 index 0000000000..3bfa94c2ab --- /dev/null +++ b/shared/src/test/diff/nu/TypeSel.mls @@ -0,0 +1,419 @@ +:NewDefs + +// * To support: +// * - type parameter members +// * - accessing type members in variables (for now, no need for path dependence) +// * - Interpret absence of type parameters as some fresh type variables: `Foo` means `Foo['a]` + +// * For the future: +// * - Type refinement syntax, as in `Foo { A = Int }` +// * - Support wildcard type argument syntax: `Foo[?]` (for what we currently write `Foo`) +// * - `as` syntax for upcasting + +class Foo[A](val a: A) +//│ class Foo[A](a: A) + +:e +fun foo(f: Foo[Int]): f.A = f.a +//│ ╔══[ERROR] Type `Foo[Int]` does not contain member `A` +//│ ║ l.17: fun foo(f: Foo[Int]): f.A = f.a +//│ ╙── ^^ +//│ fun foo: (f: Foo[Int]) -> error + +class Foo[type A] { + fun f: A -> Int + fun f(x) = 1 +} +//│ class Foo[A] { +//│ constructor() +//│ fun f: A -> Int +//│ } + + +fun foo(f: Foo[Int], g: Foo[f.A], x: f.A) = g.f(f.f(x)) +//│ fun foo: (f: Foo[Int], g: Foo[Int], x: Int) -> Int + +class Bar(val f: Foo[Int]) +//│ class Bar(f: Foo[Int]) + +:e +fun foo(b: Bar): b.f.A = 1 +//│ ╔══[ERROR] Type mismatch in type selection: +//│ ║ l.40: fun foo(b: Bar): b.f.A = 1 +//│ ║ ^^ +//│ ╙── type `Foo[Int]` cannot be reassigned +//│ fun foo: (b: Bar) -> Int + +fun bar(b: Bar) = b.f.f(1) +//│ fun bar: (b: Bar) -> Int + +fun foo(b: Bar) = + let f = id(b).f + let g = x => f.f(x + 1) + g(1) : f.A +//│ fun foo: (b: Bar) -> Int + +:e +fun foo(f: Foo, x: f.A) = f.f(x) +//│ ╔══[ERROR] Type error in application +//│ ║ l.57: fun foo(f: Foo, x: f.A) = f.f(x) +//│ ║ ^^^^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.57: fun foo(f: Foo, x: f.A) = f.f(x) +//│ ║ ^^ +//│ ╟── back into type variable `A` +//│ ║ l.23: class Foo[type A] { +//│ ╙── ^ +//│ fun foo: (f: Foo[nothing], x: ??A) -> (Int | error) + +fun foo(f: Foo['a], x) = f.f(x) +//│ fun foo: forall 'a. (f: Foo['a], 'a) -> Int + +fun foo(p, q, f: (p,q) -> Int) = f(p,q) +//│ fun foo: forall 'a 'b. ('a, 'b, f: ('a, 'b) -> Int) -> Int + +foo(1, 0, (x, y) => x + y) +//│ Int +//│ res +//│ = 1 + +class Foo[type A](val a: A) +//│ class Foo[A](a: A) + +fun foo(f: Foo[Int]): Int = f.a : f.A +//│ fun foo: (f: Foo[Int]) -> Int + +fun foo[T](f: Foo[T]): T = f.a : f.A +//│ fun foo: forall 'T. (f: Foo['T]) -> 'T + +// raw type example +// TODO support +fun foo(f: Foo): Int = f.a : f.A +//│ ╔══[ERROR] Type error in type ascription +//│ ║ l.91: fun foo(f: Foo): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.91: fun foo(f: Foo): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── back into type variable `A` +//│ ║ l.91: fun foo(f: Foo): Int = f.a : f.A +//│ ╙── ^^ +//│ ╔══[ERROR] Type error in type ascription +//│ ║ l.91: fun foo(f: Foo): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.91: fun foo(f: Foo): Int = f.a : f.A +//│ ║ ^^ +//│ ╟── into type `Int` +//│ ║ l.91: fun foo(f: Foo): Int = f.a : f.A +//│ ╙── ^^^ +//│ fun foo: (f: Foo[anything]) -> Int + +:e +fun foo(f: Foo) = f.a : f.A +//│ ╔══[ERROR] Type error in type ascription +//│ ║ l.113: fun foo(f: Foo) = f.a : f.A +//│ ║ ^^^ +//│ ╟── type variable `A` leaks out of its scope +//│ ║ l.113: fun foo(f: Foo) = f.a : f.A +//│ ║ ^^^ +//│ ╟── back into type variable `A` +//│ ║ l.113: fun foo(f: Foo) = f.a : f.A +//│ ╙── ^^ +//│ fun foo: (f: Foo[anything]) -> ??A + +fun foo(f: Foo['a]): Int = f.a : f.A +//│ fun foo: forall 'a. (f: Foo['a]) -> Int +//│ where +//│ 'a <: Int + +:e +fun foo(f: Foo[?]): Int = f.a : f.A +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.131: fun foo(f: Foo[?]): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── field selection of type `anything` does not match type `nothing` +//│ ╟── Note: constraint arises from type selection: +//│ ║ l.131: fun foo(f: Foo[?]): Int = f.a : f.A +//│ ╙── ^^ +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.131: fun foo(f: Foo[?]): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── type `anything` is not an instance of type `Int` +//│ ║ l.131: fun foo(f: Foo[?]): Int = f.a : f.A +//│ ║ ^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.131: fun foo(f: Foo[?]): Int = f.a : f.A +//│ ╙── ^^^ +//│ fun foo: (f: Foo[anything]) -> Int + +fun foo(f) = f.a : f.A +//│ fun foo: forall 'A 'A0. {A :> 'A <: 'A0, a: 'A} -> 'A0 + +fun foo(f): Int = f.a : f.A +//│ fun foo: forall 'A. {A :> 'A <: Int, a: 'A} -> Int + +foo(Foo(1)) +//│ Int +//│ res +//│ = 1 + +:e +foo(Foo(true)) +//│ ╔══[ERROR] Type mismatch in application: +//│ ║ l.162: foo(Foo(true)) +//│ ║ ^^^^^^^^^^^^^^ +//│ ╟── reference of type `true` is not an instance of `Int` +//│ ║ l.162: foo(Foo(true)) +//│ ║ ^^^^ +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.153: fun foo(f): Int = f.a : f.A +//│ ║ ^^^ +//│ ╟── from type selection: +//│ ║ l.153: fun foo(f): Int = f.a : f.A +//│ ╙── ^^ +//│ Int | error +//│ res +//│ = true + +abstract class Foo[type A]: Bar | Baz +module Bar extends Foo[Int] +module Baz extends Foo[Str] +//│ abstract class Foo[A]: Bar | Baz +//│ module Bar extends Foo +//│ module Baz extends Foo + +123 : Bar.A +//│ Int +//│ res +//│ = 123 + +:e +"bad": Bar.A +//│ ╔══[ERROR] Type mismatch in type ascription: +//│ ║ l.192: "bad": Bar.A +//│ ║ ^^^^^ +//│ ╟── string literal of type `"bad"` is not an instance of type `Int` +//│ ╟── Note: constraint arises from type reference: +//│ ║ l.180: module Bar extends Foo[Int] +//│ ║ ^^^ +//│ ╟── from type selection: +//│ ║ l.192: "bad": Bar.A +//│ ╙── ^^ +//│ Int +//│ res +//│ = 'bad' + +fun foo(f, x) = x : f.A +//│ fun foo: forall 'A 'A0. ({A :> 'A <: 'A0}, 'A) -> 'A0 + +foo(Bar, 123) +//│ Int +//│ res +//│ = 123 + +fun test(f) = if f is + Bar then 123 : f.A +//│ fun test: Bar -> Int + +fun test(f) = if f is + Bar then 123 : f.A + Baz then "hello" : f.A +//│ fun test: (Bar | Baz) -> (Int | Str) + +[test(Bar), test(Baz)] +//│ [Int | Str, Int | Str] +//│ res +//│ = [ 123, 'hello' ] + +fun test(f: Foo['a]) = if f is Bar then 123 : f.A else error +//│ fun test: forall 'a. (f: Foo['a]) -> (Int & 'a) + +fun test(f: Foo[Int]) = if f is Bar then 123 : f.A else error +//│ fun test: (f: Foo[Int]) -> Int + +fun test(f: Foo) = if f is Bar then 123 : f.A else error +//│ fun test: (f: Foo[?]) -> Int + +fun test(f: Foo[?]) = if f is Bar then 123 : f.A else error +//│ fun test: (f: Foo[?]) -> Int + +:e +fun test(f: Foo) = if f is + Bar then 123 : f.A + Baz then "hello" : f.A +//│ ╔══[ERROR] Type mismatch in `case` expression: +//│ ║ l.242: fun test(f: Foo) = if f is +//│ ║ ^^^^ +//│ ║ l.243: Bar then 123 : f.A +//│ ║ ^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.244: Baz then "hello" : f.A +//│ ║ ^^^^^^^^^^^^^^^^^^ +//│ ╟── type `Foo[?]` does not match type `Bar | Baz` +//│ ║ l.242: fun test(f: Foo) = if f is +//│ ║ ^^^ +//│ ╟── but it flows into reference with expected type `Bar | Baz` +//│ ║ l.242: fun test(f: Foo) = if f is +//│ ╙── ^ +//│ fun test: (f: Foo[?]) -> (Int | Str) + +[test(Bar), test(Baz)] +//│ [Int | Str, Int | Str] +//│ res +//│ = [ 123, 'hello' ] + +fun test(f: Foo[?]) = if f is + Bar then 123 : f.A + Baz then "hello" : f.A +//│ fun test: (f: Foo[?]) -> (Int | Str) + +fun test[T](f: Foo[T]): T = if f is + Bar then 123 : f.A + Baz then "hello" : f.A +//│ fun test: forall 'T. (f: Foo['T]) -> 'T + +:e +class Foo[type A] +class Bar[type A] extends Foo[A] +//│ ╔══[ERROR] Inherited parameter named 'A' is not virtual and cannot be overridden +//│ ║ l.277: class Bar[type A] extends Foo[A] +//│ ║ ^ +//│ ╟── Originally declared here: +//│ ║ l.276: class Foo[type A] +//│ ╙── ^ +//│ class Foo[A] { +//│ constructor() +//│ } +//│ class Bar[A] extends Foo { +//│ constructor() +//│ } + +class Foo[type A] +//│ class Foo[A] { +//│ constructor() +//│ } + +:e +class Bar[type A] extends Foo[A -> A] +//│ ╔══[ERROR] Inherited parameter named 'A' is not virtual and cannot be overridden +//│ ║ l.297: class Bar[type A] extends Foo[A -> A] +//│ ║ ^ +//│ ╟── Originally declared here: +//│ ║ l.291: class Foo[type A] +//│ ╙── ^ +//│ class Bar[A] extends Foo { +//│ constructor() +//│ } + +:e +class Bar[type A] extends Foo[Int] +//│ ╔══[ERROR] Inherited parameter named 'A' is not virtual and cannot be overridden +//│ ║ l.309: class Bar[type A] extends Foo[Int] +//│ ║ ^ +//│ ╟── Originally declared here: +//│ ║ l.291: class Foo[type A] +//│ ╙── ^ +//│ class Bar[A] extends Foo { +//│ constructor() +//│ } + + + + +class Foo[A] +//│ class Foo[A] { +//│ constructor() +//│ } + +// FIXME +// Would be nice: +fun foo(x: Foo['a], y) = y : x.A // interpreted as `y : x.Foo#A` +//│ ╔══[ERROR] Type `Foo['a]` does not contain member `A` +//│ ║ l.330: fun foo(x: Foo['a], y) = y : x.A // interpreted as `y : x.Foo#A` +//│ ╙── ^^ +//│ fun foo: forall 'a. (x: Foo['a], error) -> error + +fun foo(x, y) = y : x.A +//│ fun foo: forall 'A 'A0. ({A :> 'A <: 'A0}, 'A) -> 'A0 + +// FIXME +fun bar(f: Foo['a], y) = foo(f, y) +//│ ╔══[ERROR] Type `Foo['a]` does not contain member `A` +//│ ║ l.336: fun foo(x, y) = y : x.A +//│ ╙── ^^ +//│ fun bar: forall 'a. (f: Foo['a], error) -> error + +class Bar(val A: Int) +//│ class Bar(A: Int) + +abstract class C[type A]: C1 | C2 +class C1(val s: Bool) extends C[Bool] +class C2(val i: Int) extends C[Int] +//│ abstract class C[A]: C1 | C2 +//│ class C1(s: Bool) extends C +//│ class C2(i: Int) extends C + +let f = (t, x: t.A) => x + t.i +//│ let f: forall 'A. ({A :> 'A <: Int, i: Int}, x: 'A) -> Int +//│ f +//│ = [Function: f] + +f(C2(1), 2) +//│ Int +//│ res +//│ = 3 + +let g = (t, x: t) => t && x +//│ let g: (Bool, x: Bool) -> Bool +//│ g +//│ = [Function: g] + +class Foo(val x: C1) { + fun foo(y: x.A) = y || y +} +//│ class Foo(x: C1) { +//│ fun foo: (y: Bool) -> Bool +//│ } + +Foo(C1(false)).foo(true) +//│ Bool +//│ res +//│ = true + +:pe +class Foo[in type] +//│ ╔══[PARSE ERROR] dangling variance information +//│ ║ l.384: class Foo[in type] +//│ ╙── ^^ +//│ ╔══[PARSE ERROR] Unexpected 'type' keyword here +//│ ║ l.384: class Foo[in type] +//│ ╙── ^^^^ +//│ class Foo { +//│ constructor() +//│ } + +:pe +class Foo[type] +//│ ╔══[PARSE ERROR] dangling visible type member +//│ ║ l.396: class Foo[type] +//│ ╙── ^^^^ +//│ class Foo { +//│ constructor() +//│ } + +:pe +class Foo[type in] +//│ ╔══[PARSE ERROR] dangling type member and variance information +//│ ║ l.405: class Foo[type in] +//│ ╙── ^^^^^^^ +//│ class Foo { +//│ constructor() +//│ } + +// FIXME crash +:pe +fun foo[typ](x) +//│ ╔══[PARSE ERROR] Expected ':' or '=' followed by a function body or signature; found end of input instead +//│ ║ l.415: fun foo[typ](x) +//│ ╙── ^ +//│ fun foo: anything -> () diff --git a/shared/src/test/diff/nu/TypeSelections.mls b/shared/src/test/diff/nu/TypeSelections.mls index 909a1eff52..2880189bc3 100644 --- a/shared/src/test/diff/nu/TypeSelections.mls +++ b/shared/src/test/diff/nu/TypeSelections.mls @@ -8,7 +8,6 @@ module M { } //│ module M { //│ class C(n: Int) -//│ type T = Int -> Int //│ fun mkC: (n: Int) -> C //│ } @@ -29,10 +28,16 @@ foo(M.mkC(42)) :e 42 : M.mkC -//│ ╔══[ERROR] Illegal selection of value member in type position -//│ ║ l.31: 42 : M.mkC +//│ ╔══[ERROR] Type mismatch in type selection: +//│ ║ l.30: 42 : M.mkC +//│ ║ ^^^^ +//│ ╟── member of type `(n: Int) -> C` is not mutable +//│ ║ l.7: fun mkC = C +//│ ║ ^^^^^^^ +//│ ╟── but it flows into type selection with expected type `?mkC` +//│ ║ l.30: 42 : M.mkC //│ ╙── ^^^^ -//│ error +//│ (n: Int) -> C //│ res //│ = 42 diff --git a/shared/src/test/diff/nu/TypeVariables.mls b/shared/src/test/diff/nu/TypeVariables.mls index 327b6ca005..70f9e30d8a 100644 --- a/shared/src/test/diff/nu/TypeVariables.mls +++ b/shared/src/test/diff/nu/TypeVariables.mls @@ -26,7 +26,7 @@ fun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,] //│ ╔══[PARSE ERROR] Unexpected end of square bracket section; an expression was expected here //│ ║ l.25: fun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,] //│ ╙── ^ -//│ ╔══[ERROR] type identifier not found: , +//│ ╔══[ERROR] cannot lift variable , to type //│ ║ l.25: fun x: [Int -> Int] = [id : forall 'a: 'a -> 'a,] //│ ╙── ^^^^^^^^^ //│ fun x: [Int -> Int] diff --git a/shared/src/test/diff/nu/TypreMembers.mls b/shared/src/test/diff/nu/TypreMembers.mls deleted file mode 100644 index af6a856b41..0000000000 --- a/shared/src/test/diff/nu/TypreMembers.mls +++ /dev/null @@ -1,30 +0,0 @@ -:NewDefs - - -class Test { type T = Int } -//│ class Test { -//│ constructor() -//│ type T = Int -//│ } - -1 : Test.T -//│ Int -//│ res -//│ = 1 - - -trait Test { type T = Int } -//│ trait Test { -//│ type T = Int -//│ } - -:e -1 : Test.T -//│ ╔══[ERROR] Illegal prefix of type selection: Test -//│ ║ l.22: 1 : Test.T -//│ ╙── ^^^^ -//│ error -//│ res -//│ = 1 - - diff --git a/shared/src/test/diff/nu/UnionReordering.mls b/shared/src/test/diff/nu/UnionReordering.mls index b7d2d5d3c0..046a3ed8ac 100644 --- a/shared/src/test/diff/nu/UnionReordering.mls +++ b/shared/src/test/diff/nu/UnionReordering.mls @@ -37,7 +37,7 @@ type RegionLang = BaseLang[RegionLang] | ExtLang[RegionLang] type RegionLang1 = ExtLang[RegionLang] | BaseLang[RegionLang] type RegionLang2 = ExtLang[C] | ExtLang[D] //│ type RegionLang1 = BaseLang[RegionLang] | ExtLang[RegionLang] -//│ type RegionLang2 = ExtLang[out C[?] | D[?]] +//│ type RegionLang2 = ExtLang[in C[?] | D[?] out nothing] // * There is currently no deep reordering, though: type RegionLang1 = ExtLang[C] -> Int & ExtLang[D] -> Str diff --git a/shared/src/test/diff/nu/WeirdUnions.mls b/shared/src/test/diff/nu/WeirdUnions.mls index d5b600e875..d004621b2d 100644 --- a/shared/src/test/diff/nu/WeirdUnions.mls +++ b/shared/src/test/diff/nu/WeirdUnions.mls @@ -13,7 +13,7 @@ fun f: (Str | [Str, Int]) :e fun f: Str | (Str, Int) -//│ ╔══[ERROR] type identifier not found: , +//│ ╔══[ERROR] cannot lift variable , to type //│ ║ l.15: fun f: Str | (Str, Int) //│ ╙── ^^^^^^^^^^ //│ fun f: Str | error @@ -24,7 +24,7 @@ fun f: Str | ([Str, Int]) :e fun f: Str | ((Str, Int)) -//│ ╔══[ERROR] type identifier not found: , +//│ ╔══[ERROR] cannot lift variable , to type //│ ║ l.26: fun f: Str | ((Str, Int)) //│ ╙── ^^^^^^^^^^^^ //│ fun f: Str | error diff --git a/shared/src/test/diff/nu/i180.mls b/shared/src/test/diff/nu/i180.mls index 39013ced9f..01d9843c8f 100644 --- a/shared/src/test/diff/nu/i180.mls +++ b/shared/src/test/diff/nu/i180.mls @@ -54,7 +54,7 @@ fun (:-) listExclude(xs, x) = Cons(x', xs') and x === x' then xs' :- x else x' :: (xs' :- x) -//│ fun (:-) listExclude: forall 'A. (Cons['A] | Nil, Eql['A]) -> (Nil | List['A]) +//│ fun (:-) listExclude: forall 'A. (Cons['A] | Nil, Eql[??A & 'A]) -> (Nil | List[??A & 'A]) (Nil :- 0).join(", ") ((0 :: Nil) :- 0).join(", ") diff --git a/shared/src/test/diff/nu/repro0.mls b/shared/src/test/diff/nu/repro0.mls index c02b9aa19e..629170f0ba 100644 --- a/shared/src/test/diff/nu/repro0.mls +++ b/shared/src/test/diff/nu/repro0.mls @@ -12,11 +12,10 @@ let res = EvalAddLit.eval(add11) //│ class Add[E](lhs: E) //│ val add11: 'E //│ module EvalAddLit { -//│ fun eval: forall 'A. (e: 'A) -> nothing +//│ fun eval: (e: Add[anything]) -> nothing //│ } //│ let res: nothing //│ where -//│ 'A <: Add['A] //│ 'E :> Add['E] diff --git a/shared/src/test/diff/nu/repro1.mls b/shared/src/test/diff/nu/repro1.mls index 09c7cb8328..fb45d0a5ee 100644 --- a/shared/src/test/diff/nu/repro1.mls +++ b/shared/src/test/diff/nu/repro1.mls @@ -17,9 +17,9 @@ let circles = go(2) fun contains(a) = if a is Union then contains(a.a) -//│ fun contains: forall 'a. 'a -> nothing +//│ fun contains: forall 'Region. Union['Region] -> nothing //│ where -//│ 'a <: Union['a] +//│ 'Region <: Union['Region] | ~??Region contains(circles) //│ nothing @@ -30,16 +30,16 @@ mixin Contains { if a is Union then this.contains(a.a) } //│ mixin Contains() { -//│ this: {contains: 'a -> 'b} -//│ fun contains: Union['a] -> 'b +//│ this: {contains: (??Region & 'Region) -> 'a} +//│ fun contains: Union['Region] -> 'a //│ } module TestContains extends Contains //│ module TestContains { -//│ fun contains: 'a -> nothing +//│ fun contains: Union['Region] -> nothing //│ } //│ where -//│ 'a <: Union['a] +//│ 'Region <: Union['Region] | ~??Region TestContains.contains(circles) //│ nothing diff --git a/shared/src/test/diff/nu/repro_EvalNegNeg.mls b/shared/src/test/diff/nu/repro_EvalNegNeg.mls index f42ccd5a2b..25c21f0f7a 100644 --- a/shared/src/test/diff/nu/repro_EvalNegNeg.mls +++ b/shared/src/test/diff/nu/repro_EvalNegNeg.mls @@ -19,17 +19,18 @@ mixin EvalBase { Add(l, r) then this.eval(l) + this.eval(r) } //│ mixin EvalBase() { -//│ this: {eval: 'a -> 'b & 'c -> Int} -//│ fun eval: (Add['c] | Lit | Neg['c & (Neg['a] | Object & ~#Neg)]) -> (Int | 'b) +//│ this: {eval: (??A & 'A) -> 'a & (??A0 & 'A0 | ??E & 'E) -> Int} +//│ fun eval: (Add['E] | Lit | Neg['A0 & (Neg['A] | Object & ~#Neg | ~??A0)]) -> (Int | 'a) //│ } // module TestLang extends EvalBase, EvalNeg module TestLang extends EvalBase //│ module TestLang { -//│ fun eval: 'a -> Int +//│ fun eval: (Add['E] | Lit | Neg['A]) -> Int //│ } //│ where -//│ 'a <: Add['a] | Lit | Neg['a & (Neg['a] | Object & ~#Neg)] +//│ 'E <: Add['E] | Lit | Neg['A] | ~??E +//│ 'A <: Add['E] | Lit | Neg['A] & ~#Neg | Neg['A & (Add['E] | Lit | Neg['A] | ~??A)] | ~??A0 fun mk(n) = if n is @@ -45,8 +46,8 @@ TestLang.eval(mk(0)) //│ Int //│ res //│ = 0 -//│ constrain calls : 179 -//│ annoying calls : 51 -//│ subtyping calls : 1203 +//│ constrain calls : 246 +//│ annoying calls : 55 +//│ subtyping calls : 2390 diff --git a/shared/src/test/diff/parser/IfThenElse.mls b/shared/src/test/diff/parser/IfThenElse.mls index 7255013bc7..9af16127a4 100644 --- a/shared/src/test/diff/parser/IfThenElse.mls +++ b/shared/src/test/diff/parser/IfThenElse.mls @@ -440,8 +440,8 @@ let Some(x) = v //│ Parsed: {let Some = (x,) => v} v as Some(x) -//│ |v| |as| |Some|(|x|)| -//│ Parsed: {as(v,)(Some(x,),)} +//│ |v| |#as| |Some|(|x|)| +//│ Parsed: {v : Some[x]} diff --git a/shared/src/test/diff/qq/Codegen.mls b/shared/src/test/diff/qq/Codegen.mls index 3665fac844..abe9e569f2 100644 --- a/shared/src/test/diff/qq/Codegen.mls +++ b/shared/src/test/diff/qq/Codegen.mls @@ -323,7 +323,7 @@ code"p => if p.x === :ne fun test(cde, f) = code"x => x + ${f(cde)}" -//│ fun test: forall 'a 'b. ('a, 'a -> Code[Int, 'b]) -> Code[Int -> Int, 'b] +//│ fun test: forall 'a. ('a, 'a -> Code[Int, anything]) -> Code[Int -> Int, nothing] //│ // Prelude //│ class TypingUnit25 {} //│ const typing_unit25 = new TypingUnit25; @@ -353,7 +353,7 @@ code"""let x = ${log("foo"), Const(0)} in x + 1""" :ne fun foo(dbg) = code"x => ${let c = code"x" in dbg(c)}" -//│ fun foo: forall 'a 'b 'c. (Code['a, ??x] -> Code['b, 'c]) -> Code['a -> 'b, 'c] +//│ fun foo: forall 'a 'b. (Code['a, ??x] -> Code['b, anything]) -> Code['a -> 'b, nothing] :ne code"x => let c = 42 in ${code"x"}" diff --git a/shared/src/test/diff/qq/Extrusions.mls b/shared/src/test/diff/qq/Extrusions.mls index 34a2a9ea65..00aaed2f43 100644 --- a/shared/src/test/diff/qq/Extrusions.mls +++ b/shared/src/test/diff/qq/Extrusions.mls @@ -5,28 +5,28 @@ // * This definition is not good as it leads to extrusion; we need `k` to be polymorphic (which requires annotation) fun (%>) bind(rhs, k) = code"let x = ${rhs} in ${k(code"x")}" -//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Code['a, ??x] -> Code['c, 'b]) -> Code['c, 'b] +//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Code['a, ??x] -> Code['c, anything]) -> Code['c, 'b] fun (%>) bind(rhs, k) = code"let x = ${rhs} in ${k(x)}" -//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Var['a, in ??x out ??x0] -> Code['c, 'b]) -> Code['c, 'b] +//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Var['a, in ??x out ??x0] -> Code['c, anything]) -> Code['c, 'b] // * Notice the extrusion fun foo(k) = code"x => ${k(code"x")}" -//│ fun foo: forall 'a 'b 'c. (Code['a, ??x] -> Code['b, 'c]) -> Code['a -> 'b, 'c] +//│ fun foo: forall 'a 'b. (Code['a, ??x] -> Code['b, anything]) -> Code['a -> 'b, nothing] fun (%>) bind(rhs, k) = code"(x => ${k(code"x")})(${rhs})" -//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Code['a, ??x] -> Code['c, 'b]) -> Code['c, 'b] +//│ fun (%>) bind: forall 'a 'b 'c. (Code['a, 'b], Code['a, ??x] -> Code['c, anything]) -> Code['c, 'b] fun app = code"(f, x) => f(x)" fun (%>) bind(rhs, k) = code"${app}(x => ${k(code"x")}, ${rhs})" //│ fun app: forall 'a 'b. Code[('a -> 'b, 'a) -> 'b, nothing] -//│ fun (%>) bind: forall 'c 'd 'e. (Code['c, 'd], Code['c, ??x] -> Code['e, 'd]) -> Code['e, 'd] +//│ fun (%>) bind: forall 'c 'd 'e. (Code['c, 'd], Code['c, ??x] -> Code['e, anything]) -> Code['e, 'd] fun app(f, x) = f(x) fun bind2(rhs, k) = code"app(x => ${k(code"x")}, ${rhs})" //│ fun app: forall 'a 'b. ('a -> 'b, 'a) -> 'b -//│ fun bind2: forall 'c 'd 'e. (Code['c, 'd], Code['c, ??x] -> Code['e, 'd]) -> Code['e, 'd] +//│ fun bind2: forall 'c 'd 'e. (Code['c, 'd], Code['c, ??x] -> Code['e, anything]) -> Code['e, 'd] :e fun foo() = @@ -44,7 +44,7 @@ code"1 ++ 2" // G <: ??x | 'a fun bind(rhs, k: forall 'C: Code['A, 'C] -> Code['B, 'C | 'G]) = code"let x = ${rhs} in ${k(code"x")}" -//│ fun bind: forall 'A 'a 'B. (Code['A, 'a], k: forall 'C. Code['A, 'C] -> Code['B, 'C | 'a]) -> Code['B, 'a] +//│ fun bind: forall 'A 'a 'B. (Code['A, 'a], k: Code['A, anything] -> Code['B, anything]) -> Code['B, 'a] bind : forall 'a, 'c, 'g: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g] //│ forall 'a 'g. (Code['a, 'g], k: forall 'c. Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g] @@ -52,12 +52,12 @@ bind : forall 'a, 'c, 'g: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, fun foo(dbg) = code"x => ${let c = code"(${x}, ${foo(dbg)})" in dbg(c)}" -//│ fun foo: forall 'a 'b. (Code[anything -> 'a, anything] -> Code['a, 'b]) -> Code[anything -> 'a, 'b] +//│ fun foo: forall 'a. (Code[anything -> 'a, ??x] -> Code['a, anything]) -> Code[anything -> 'a, nothing] fun power(x) = case 0 then `1.0 n then x `*. power(x)(n - 1) -//│ fun power: forall 'a. Code[Num, 'a] -> (0 | Int & ~0) -> Code[Num, 'a] +//│ fun power: Code[Num, anything] -> (0 | Int & ~0) -> Code[1.0, nothing] :e let p3 = y `=> diff --git a/shared/src/test/diff/qq/Hygiene.mls b/shared/src/test/diff/qq/Hygiene.mls index a7dc7e2b60..b72adb56ff 100644 --- a/shared/src/test/diff/qq/Hygiene.mls +++ b/shared/src/test/diff/qq/Hygiene.mls @@ -13,14 +13,14 @@ run(code_test) // Test 2 fun test: forall 'c: (Int, cde: Code[Int, 'c]) => Code[Int, 'c] fun test(n, cde) = if n > 0 then code"let x = ${Const(n)} in ${test(n - 1, code"${cde} + x")}" else cde -//│ fun test: forall 'a. (Int, Code[Int, 'a]) -> Code[Int, 'a] +//│ fun test: forall 'a. (Int, Code[Int, anything] & 'a) -> (Code[Int, nothing] | 'a) //│ fun test: forall 'c. (Int, cde: Code[Int, 'c]) -> Code[Int, 'c] run(test(3, code"0")) //│ Int fun test(n, cde) = if n > 0 then code"${test(n - 1, code"${cde} + ${Const(n)}")}" else cde -//│ fun test: forall 'a 'b. (Int, Code[Int, 'a] & 'b) -> (Code[Int, 'a] | 'b) +//│ fun test: forall 'a 'b. (Int, Code[anything, anything] & 'b) -> (Code[Int, 'a] | 'b) run(test(3, code"0")) @@ -35,10 +35,10 @@ fun test(n, cde) = if n > 0 then code"let x = ${Const(n)} in ${test(n - 1, cde_t //│ ║ l.32: fun cde_template(cde) = code"${cde} + x" //│ ╙── ^ //│ fun cde_template: forall 'a. Code[Int, 'a] -> Code[Int, 'a] -//│ fun test: forall 'b 'c. (Int, Code[Int, 'b] & 'c) -> (Code[Int, 'b] | 'c) +//│ fun test: forall 'b. (Int, Code[anything, anything] & 'b) -> (Code[Int, nothing] | 'b) let c = test(3, code"0") -//│ let c: Code[Int, nothing] +//│ let c: Code[0, nothing] run(c) diff --git a/shared/src/test/diff/qq/LetInsertion.mls b/shared/src/test/diff/qq/LetInsertion.mls index dfdf86ec37..f3d464792a 100644 --- a/shared/src/test/diff/qq/LetInsertion.mls +++ b/shared/src/test/diff/qq/LetInsertion.mls @@ -93,7 +93,7 @@ fun body(x, y) = case 0 then x 1 then y n then code"let tmp = ${x} + ${y} in ${body(x, code"tmp")(n - 1)}" -//│ fun body: forall 'a. (Code[Int, 'a], Code[Int, 'a]) -> (0 | 1 | Int & ~0 & ~1) -> Code[Int, 'a] +//│ fun body: forall 'a 'b. (Code[Int, anything] & 'a, Code[Int, 'b] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, 'b] | 'a) //│ fun body: forall 'g. (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g] fun gib(n) = diff --git a/shared/src/test/diff/qq/LetInsertion_repro.mls b/shared/src/test/diff/qq/LetInsertion_repro.mls index 64543f6375..adf5652ae4 100644 --- a/shared/src/test/diff/qq/LetInsertion_repro.mls +++ b/shared/src/test/diff/qq/LetInsertion_repro.mls @@ -14,7 +14,7 @@ fun body(x, y) = case 0 then x 1 then y n then code"${x} + ${y}" %> z => body(x, z)(n - 1) -//│ fun body: forall 'a. (Code[Int, anything] & 'a, Code[Int, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, anything] | 'a) +//│ fun body: forall 'a. (Code[Int, anything] & 'a, Code[Int, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, ??c] | 'a) :e body : forall 'g: (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g] @@ -55,7 +55,7 @@ fun body(x, y) = case 0 then x 1 then y n then code"${x} + ${y}" %> z => code"${body(x, z)(n - 1)}" -//│ fun body: forall 'a. (Code[Int, anything] & 'a, Code[Int, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, anything] | 'a) +//│ fun body: forall 'b 'a. (Code['b, anything] & 'a, Code['b, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int & (Int | 'b), ??c] | 'a) code"(x, y) => ${body(code"x", code"y")(0)}" //│ Code[(Int, Int) -> Int, ??c & ~??y] diff --git a/shared/src/test/diff/qq/Nested.mls b/shared/src/test/diff/qq/Nested.mls index 750a4a8f00..562c2fec20 100644 --- a/shared/src/test/diff/qq/Nested.mls +++ b/shared/src/test/diff/qq/Nested.mls @@ -33,7 +33,7 @@ let inner1 = code"1" let inner2(x) = code"y => ${x} + 1" let t = code"let x = inner1 in inner2(x)" //│ let inner1: Code[1, nothing] -//│ let inner2: forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a] +//│ let inner2: Code[Int, anything] -> Code[anything -> Int, nothing] //│ let t: Code[Code[anything -> Int, nothing], nothing] run(run(t))(0) @@ -89,18 +89,18 @@ run(r)("happy") let inner4(x) = code"let x = inner2 in ${x}" let c2 = code"let x = inner1 in inner4(x)" -//│ let inner4: anything -> Code[forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a], nothing] -//│ let c2: Code[Code[forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a], nothing], nothing] +//│ let inner4: anything -> Code[Code[Int, anything] -> Code[anything -> Int, nothing], nothing] +//│ let c2: Code[Code[Code[Int, anything] -> Code[anything -> Int, nothing], nothing], nothing] let r = run(c2) -//│ let r: Code[forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a], nothing] +//│ let r: Code[Code[Int, anything] -> Code[anything -> Int, nothing], nothing] let rr = run(r) -//│ let rr: forall 'a. Code[Int, 'a] -> Code[anything -> Int, 'a] +//│ let rr: Code[Int, anything] -> Code[anything -> Int, nothing] rr(code"123") //│ Code[anything -> Int, nothing] let inner4(x) = code"let y = 100 in ${x}" let c3 = code"let x1 = inner1 in let x2 = inner2 in inner4(x)" -//│ let inner4: forall 'a 'b. Code['a, 'b] -> Code['a, 'b] +//│ let inner4: forall 'a. Code['a, anything] -> Code['a, nothing] //│ let c3: Code[Code[2, nothing], nothing] let r = run(c3) //│ let r: Code[2, nothing] @@ -147,7 +147,7 @@ code"x => ${code"${code"${code"x"}"}"}" fun f(cde) = code"x => ${code"${code"${code"x + ${cde}"}"}"}" run(f(Const(114)))(514) -//│ fun f: forall 'a. Code[Int, 'a] -> Code[Int -> Int, 'a] +//│ fun f: Code[Int, anything] -> Code[Int -> Int, nothing] //│ Int fun f(x) = code"${run(x)} + 1" diff --git a/shared/src/test/diff/qq/PEPM.mls b/shared/src/test/diff/qq/PEPM.mls index 74448dc8e9..984bbcf2f1 100644 --- a/shared/src/test/diff/qq/PEPM.mls +++ b/shared/src/test/diff/qq/PEPM.mls @@ -60,7 +60,7 @@ fun power'(x, n) = if (n == 0) then Const(1) else if (even(n)) then code"let t = ${power'(x, Math.floor(n / 2))} in t * t" else code"${x} * ${power'(x, n - 1)}" -//│ fun power': forall 'a. (Code[Int, 'a], Int) -> Code[Int, 'a] +//│ fun power': (Code[Int, anything], Int) -> Code[Int, nothing] //│ // Prelude //│ class TypingUnit7 {} //│ const typing_unit7 = new TypingUnit7; @@ -111,7 +111,7 @@ code"let x = 42 in x" :ne fun test(f) = code"x => x + ${f(code"x + 1")}" -//│ fun test: forall 'a. (Code[Int, ??x] -> Code[Int, 'a]) -> Code[Int -> Int, 'a] +//│ fun test: (Code[Int, ??x] -> Code[Int, anything]) -> Code[Int -> Int, nothing] :ne :e @@ -130,7 +130,7 @@ code"x => ${ test(run) }" :ne fun assertNotZero(x) = code"if (${x} == 0) then error else ${x}" -//│ fun assertNotZero: forall 'a 'b. Code[Num & 'a, 'b] -> Code['a, 'b] +//│ fun assertNotZero: forall 'a 'b. Code[Num | 'a, 'b] -> Code['a, 'b] :ne fun safeDiv = run(code"x => y => let t = ${assertNotZero(code"y")} in x / t") @@ -147,7 +147,7 @@ safeDiv(10)(2) :ne fun fac(n, dbg) = if (n > 0) then code"let x = ${Const(n)} in ${dbg(code"x")} * ${fac(n - 1, dbg)}" else Const(1) -//│ fun fac: forall 'a. (Int, Code[Int, ??x] -> Code[Int, 'a]) -> Code[Int, 'a] +//│ fun fac: (Int, Code[Int, ??x] -> Code[Int, anything]) -> Code[Int, nothing] fun showAndRet(n: Code['a, anything]) = log(n) @@ -161,7 +161,7 @@ fun bar(x: Code['a, 'b]) = x :ne fac(10, showAndRet) -//│ Code[Int, anything] +//│ Code[Int, nothing] fun inc(x, dbg) = diff --git a/shared/src/test/diff/qq/PEPM2.mls b/shared/src/test/diff/qq/PEPM2.mls index a3a2d0cb39..404e3880be 100644 --- a/shared/src/test/diff/qq/PEPM2.mls +++ b/shared/src/test/diff/qq/PEPM2.mls @@ -5,7 +5,7 @@ fun power(x) = case 0 then `1.0 n then x `*. power(x)(n - 1) -//│ fun power: forall 'a. Code[Num, 'a] -> (0 | Int & ~0) -> Code[Num, 'a] +//│ fun power: Code[Num, anything] -> (0 | Int & ~0) -> Code[1.0, nothing] run(x `=> id(x) `* x) //│ Int -> Int @@ -28,7 +28,7 @@ fun assertNotZero(x) = `if (x `== `0.0) then `error else x fun checkedDiv = x `=> y `=> x `/ assertNotZero(y) run(checkedDiv) -//│ fun assertNotZero: forall 'a 'b. Code[Num & 'a, 'b] -> Code['a, 'b] +//│ fun assertNotZero: forall 'a 'b. Code[Num | 'a, 'b] -> Code['a, 'b] //│ fun checkedDiv: Code[Num -> Num -> Num, nothing] //│ Num -> Num -> Num //│ res @@ -45,7 +45,7 @@ fun inc(dbg) = x `=> let c = x `+ `1 in dbg(c), c inc(c => log(show(c))) //│ fun show: Code[anything, anything] -> Str -//│ fun inc: (Code[Int, anything] -> anything) -> Code[Int -> Int, nothing] +//│ fun inc: (Code[Int, ??x] -> anything) -> Code[Int -> Int, nothing] //│ Code[Int -> Int, nothing] //│ res //│ = '(x_3) =>\n (x_3 + 1)' @@ -70,11 +70,11 @@ let gn5 = run(gib_naive(5)) //│ undefined fun bind(rhs, k) = `let x = rhs `in k(x) -//│ fun bind: forall 'a 'b 'c. (Code['a, 'b], Var['a, in ??x out ??x0] -> Code['c, 'b]) -> Code['c, 'b] +//│ fun bind: forall 'a 'b 'c. (Code['a, 'b], Var['a, in ??x out ??x0] -> Code['c, anything]) -> Code['c, 'b] fun bind(rhs, k: forall 'g : Code['a, 'g] -> Code['b, 'c | 'g]) = `let x = rhs `in k(x) -//│ fun bind: forall 'a 'c 'b. (Code['a, 'c], k: forall 'g. Code['a, 'g] -> Code['b, 'c | 'g]) -> Code['b, 'c] +//│ fun bind: forall 'a 'c 'b. (Code['a, 'c], k: Code['a, anything] -> Code['b, anything]) -> Code['b, 'c] bind : forall 'a, 'c, 'g: (Code['a, 'g], k: forall 'c: Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g] //│ forall 'a 'g. (Code['a, 'g], k: forall 'c. Code['a, 'c] -> Code['b, 'c | 'g]) -> Code['b, 'g] @@ -88,7 +88,7 @@ fun body(x, y) = case n then bind of x `+ y, z => body(y, z)(n - 1) fun gib(n) = ((x, y) `=> body(x, y)(n)) let g5 = run(gib(5)) -//│ fun body: forall 'a. (Code[Int, 'a], Code[Int, 'a]) -> (0 | 1 | Int & ~0 & ~1) -> Code[Int, 'a] +//│ fun body: forall 'a 'b. (Code[Int, 'a] & 'b, Code[Int, anything] & 'b) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, 'a] | 'b) //│ fun gib: Int -> Code[(Int, Int) -> Int, nothing] //│ let g5: (Int, Int) -> Int //│ fun body: forall 'g. (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g] diff --git a/shared/src/test/diff/qq/PseudoCod.mls b/shared/src/test/diff/qq/PseudoCod.mls index fae5d5f251..5f0dabd71b 100644 --- a/shared/src/test/diff/qq/PseudoCod.mls +++ b/shared/src/test/diff/qq/PseudoCod.mls @@ -42,7 +42,7 @@ fun body(x, y) = case 0 then x 1 then y n then quote([unquote(x), unquote(y)]) %> z => body(x, z)(n - 1) -//│ fun body: forall 'b 'a. (Cod['b, anything] & 'a, Cod['b, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Cod['b, anything] | 'a) +//│ fun body: forall 'b 'a. (Cod['b, anything] & 'a, Cod['b, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Cod['b, ??c] | 'a) // code"(x, y) => ${body(code"x", code"y")(0)}" diff --git a/shared/src/test/diff/qq/QQFlag.mls b/shared/src/test/diff/qq/QQFlag.mls index da882651cd..07dab46e79 100644 --- a/shared/src/test/diff/qq/QQFlag.mls +++ b/shared/src/test/diff/qq/QQFlag.mls @@ -85,7 +85,7 @@ run(code"x => ${power'(code"x", 10)}") //│ fun floor: (x: Num) -> Int //│ } //│ fun even: Int -> Bool -//│ fun power': forall 'a. (Code[Int, 'a], Int) -> Code[Int, 'a] +//│ fun power': (Code[Int, anything], Int) -> Code[Int, nothing] //│ Int -> Int //│ res //│ = Quoted: diff --git a/shared/src/test/diff/qq/ScopeTypes.mls b/shared/src/test/diff/qq/ScopeTypes.mls index cb4268364e..d1d4ff35af 100644 --- a/shared/src/test/diff/qq/ScopeTypes.mls +++ b/shared/src/test/diff/qq/ScopeTypes.mls @@ -14,60 +14,54 @@ code"x => ${run(code"x")}" //│ Code[forall 'a. Code['a, anything] -> 'a, nothing] -fun test(cde) = +fun test[A](cde: Code[Int, A]) = code"x => x + ${cde}" -//│ fun test: forall 'a. Code[Int, 'a] -> Code[Int -> Int, 'a] +//│ fun test: forall 'A. (cde: Code[Int, 'A]) -> Code[Int -> Int, 'A & ~??x] :e code"y => ${ run(test(code"y")), code"0" }" -//│ ╔══[ERROR] Type mismatch in application: +//│ ╔══[ERROR] Type error in application //│ ║ l.22: code"y => ${ run(test(code"y")), code"0" }" //│ ║ ^^^^^^^^^^^^^^^^^^ -//│ ╟── code fragment context type of type `?y` does not match type `nothing` -//│ ║ l.18: code"x => x + ${cde}" -//│ ╙── ^^^ +//│ ╙── type variable `?x` leaks out of its scope //│ Code[Int -> 0, nothing] fun test(cde, f) = code"x => x + ${f(cde)}" -//│ fun test: forall 'a 'b. ('a, 'a -> Code[Int, 'b]) -> Code[Int -> Int, 'b] +//│ fun test: forall 'a. ('a, 'a -> Code[Int, anything]) -> Code[Int -> Int, nothing] run(test(code"1", id)) //│ Int -> Int -fun test(cde: Code[Int, 'a], f: forall 'c: Code[Int, 'c] -> Code[Int, 'c]) = +fun test[A](cde: Code[Int, A], f: forall 'c: Code[Int, 'c] -> Code[Int, 'c]) = code"x => x + ${f(cde)}" -//│ fun test: forall 'a. (cde: Code[Int, 'a], f: forall 'c. Code[Int, 'c] -> Code[Int, 'c]) -> Code[Int -> Int, 'a] +//│ fun test: forall 'A. (cde: Code[Int, 'A], f: forall 'c. Code[Int, 'c] -> Code[Int, 'c]) -> Code[Int -> Int, 'A & ~??x] run(test(code"1", id)) //│ Int -> Int :e code"x => ${ run(test(code"x", id)), code"x" }" -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.48: code"x => ${ run(test(code"x", id)), code"x" }" +//│ ╔══[ERROR] Type error in application +//│ ║ l.46: code"x => ${ run(test(code"x", id)), code"x" }" //│ ║ ^^^^^^^^^^^^^^^^^^^^^^ -//│ ╟── type `?x` does not match type `nothing` -//│ ║ l.40: fun test(cde: Code[Int, 'a], f: forall 'c: Code[Int, 'c] -> Code[Int, 'c]) = -//│ ╙── ^^ +//│ ╙── type variable `?x` leaks out of its scope //│ Code[forall 'a. (Int & 'a) -> 'a, nothing] :e code"x => ${ let c = code"x" in run(test(c, id)), c }" -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.58: code"x => ${ let c = code"x" in run(test(c, id)), c }" +//│ ╔══[ERROR] Type error in application +//│ ║ l.54: code"x => ${ let c = code"x" in run(test(c, id)), c }" //│ ║ ^^^^^^^^^^^^^^^^ -//│ ╟── type `?x` does not match type `nothing` -//│ ║ l.40: fun test(cde: Code[Int, 'a], f: forall 'c: Code[Int, 'c] -> Code[Int, 'c]) = -//│ ╙── ^^ +//│ ╙── type variable `?x` leaks out of its scope //│ Code[forall 'a. (Int & 'a) -> 'a, nothing] fun test(f) = code"x => x + ${f(code"x + 1")}" -//│ fun test: forall 'a. (Code[Int, ??x] -> Code[Int, 'a]) -> Code[Int -> Int, 'a] +//│ fun test: (Code[Int, ??x] -> Code[Int, anything]) -> Code[Int -> Int, nothing] let myrun = c => run(c) @@ -76,23 +70,23 @@ let myrun = c => run(c) :e code"x => ${ test(myrun) }" //│ ╔══[ERROR] Type error in application -//│ ║ l.77: code"x => ${ test(myrun) }" +//│ ║ l.71: code"x => ${ test(myrun) }" //│ ║ ^^^^^^^^^^^ //│ ╟── type variable `?x` leaks out of its scope //│ ╟── into type `nothing` //│ ╟── adding a type annotation to any of the following terms may help resolve the problem //│ ╟── • this reference: -//│ ║ l.69: code"x => x + ${f(code"x + 1")}" +//│ ║ l.63: code"x => x + ${f(code"x + 1")}" //│ ╙── ^ //│ Code[anything -> nothing, nothing] :e code"x => ${ test(c => run(c), code"0") }" //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.90: code"x => ${ test(c => run(c), code"0") }" +//│ ║ l.84: code"x => ${ test(c => run(c), code"0") }" //│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── argument list of type `[forall ?a ?b. ?b -> ?a, Code[0, nothing]]` does not match type `[?c]` -//│ ║ l.90: code"x => ${ test(c => run(c), code"0") }" +//│ ║ l.84: code"x => ${ test(c => run(c), code"0") }" //│ ╙── ^^^^^^^^^^^^^^^^^^^^^^ //│ Code[anything -> Int -> Int, nothing] @@ -100,21 +94,21 @@ code"x => ${ test(c => run(c), code"0") }" :e code"x => ${ test(c => run(c), code"x") }" //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.101: code"x => ${ test(c => run(c), code"x") }" -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.95: code"x => ${ test(c => run(c), code"x") }" +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ //│ ╟── argument list of type `[forall ?a ?b. ?b -> ?a, Code[?c, ?x]]` does not match type `[?d]` -//│ ║ l.101: code"x => ${ test(c => run(c), code"x") }" -//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^ +//│ ║ l.95: code"x => ${ test(c => run(c), code"x") }" +//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^ //│ Code[anything -> Int -> Int, nothing] :e fun test2(a) = code"x => ${ test(c => run(c), a) }" //│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.112: fun test2(a) = code"x => ${ test(c => run(c), a) }" +//│ ║ l.106: fun test2(a) = code"x => ${ test(c => run(c), a) }" //│ ║ ^^^^^^^^^^^^^^^^^^^^ //│ ╟── argument list of type `[forall ?a ?b. ?b -> ?a, ?c]` does not match type `[?d]` -//│ ║ l.112: fun test2(a) = code"x => ${ test(c => run(c), a) }" +//│ ║ l.106: fun test2(a) = code"x => ${ test(c => run(c), a) }" //│ ╙── ^^^^^^^^^^^^^^^^ //│ fun test2: anything -> Code[anything -> Int -> Int, nothing] diff --git a/shared/src/test/diff/qq/Weird.mls b/shared/src/test/diff/qq/Weird.mls index e0fb8563c3..5b7093ce72 100644 --- a/shared/src/test/diff/qq/Weird.mls +++ b/shared/src/test/diff/qq/Weird.mls @@ -4,7 +4,7 @@ fun power(x) = case 0 then `1.0 n then x `*. power(x)(n - 1) -//│ fun power: forall 'a. Code[Num, 'a] -> (0 | Int & ~0) -> Code[Num, 'a] +//│ fun power: Code[Num, anything] -> (0 | Int & ~0) -> Code[1.0, nothing] :e @@ -42,7 +42,7 @@ let p3 = y `=> fun bind(rhs, k: forall 'g : Code['a, 'g] -> Code['b, 'c | 'g]) = `let x = rhs `in k(x) -//│ fun bind: forall 'a 'c 'b. (Code['a, 'c], k: forall 'g. Code['a, 'g] -> Code['b, 'c | 'g]) -> Code['b, 'c] +//│ fun bind: forall 'a 'c 'b. (Code['a, 'c], k: Code['a, anything] -> Code['b, anything]) -> Code['b, 'c] // fun body: forall 'g : (Code[Int, 'g], Code[Int, 'g]) -> Int -> Code[Int, 'g] @@ -50,7 +50,7 @@ fun body(x, y) = case 0 then x 1 then y n then bind of x `+ y, z => body(y, z)(n - 1) -//│ fun body: forall 'a. (Code[Int, anything] & 'a, Code[Int, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, anything] | 'a) +//│ fun body: forall 'a. (Code[Int, anything] & 'a, Code[Int, anything] & 'a) -> (0 | 1 | Int & ~0 & ~1) -> (Code[Int, ??g] | 'a) n => (x, y) `=> body(x, y)(n) diff --git a/shared/src/test/diff/tapl/NuSimplyTyped.mls b/shared/src/test/diff/tapl/NuSimplyTyped.mls index 65c3b0dba2..666836ab34 100644 --- a/shared/src/test/diff/tapl/NuSimplyTyped.mls +++ b/shared/src/test/diff/tapl/NuSimplyTyped.mls @@ -67,8 +67,15 @@ fun find(t, k) = sgt(k, k') then find(r, k) _ then Some(v) Empty then None -//│ fun insert: forall 'A. (Empty | Node['A], Str, 'A) -> Node['A] -//│ fun find: forall 'A0. (Empty | Node['A0], Str) -> (None | Some['A0]) +//│ fun insert: forall 'A 'A0 'A1 'A2. (Empty | Node[in 'A out 'A0], Str, 'A & 'A2) -> Node[in 'A2 out 'A1] +//│ fun find: forall 'A3. (Empty | Node[out 'A3], Str) -> (None | Some[??A & 'A3]) +//│ where +//│ 'A :> ??A0 & 'A0 | 'A1 +//│ <: 'A2 & 'A0 +//│ 'A0 :> 'A1 +//│ <: 'A & 'A2 | ~??A0 +//│ 'A2 <: 'A +//│ 'A1 :> ??A0 & 'A0 | 'A fun showType(ty) = if ty is @@ -97,7 +104,7 @@ fun typeEqual(t1, t2) = t1 is FunctionType(lhs1, rhs1) and t2 is FunctionType(lhs2, rhs2) then typeEqual(lhs1, lhs2) and typeEqual(rhs1, rhs2) _ then false -//│ fun typeEqual: (Object, Object) -> Bool +//│ fun typeEqual: (Object, FunctionType | Object & ~#FunctionType & ~#PrimitiveType | PrimitiveType) -> Bool fun showTerm(t) = if t is @@ -123,6 +130,7 @@ showTerm(App(Abs(Var("x"), _t("int"), Var("y")), Var("z"))) //│ res //│ = '((&x: int => z) z)' +// :e // FIXME recursion depth excess // Removing the return type annotation causes stack overflow. fun typeTerm(t: Term, ctx: TreeMap[Type]): Result[Type, Str] = if t is @@ -165,3 +173,4 @@ showTypeTerm(App(Var("f"), Lit("0", _t("int"))), insert(Empty, "f", _t("Str"))) //│ = 'Type error: expect the argument to be of type `int` but found `float`' //│ res //│ = 'Type error: cannot apply primitive type `Str`' + diff --git a/shared/src/test/diff/tapl/NuUntyped.mls b/shared/src/test/diff/tapl/NuUntyped.mls index a9427adc52..2cc3741d77 100644 --- a/shared/src/test/diff/tapl/NuUntyped.mls +++ b/shared/src/test/diff/tapl/NuUntyped.mls @@ -1,4 +1,5 @@ :NewDefs +// :NoProvs fun (++) concatOp(a, b) = concat(a)(b) //│ fun (++) concatOp: (Str, Str) -> Str @@ -75,15 +76,15 @@ fun findFirst(list, p) = Cons(x, xs) and p(x) then Some(x) else findFirst(xs, p) -//│ fun findFirst: forall 'A. (Cons['A] | Nil, 'A -> Object) -> (None | Some['A]) +//│ fun findFirst: forall 'A. (Cons[out 'A] | Nil, (??A & 'A) -> Object) -> (None | Some[??A & 'A]) fun listConcat(xs, ys) = if xs is Nil then ys Cons(x, xs') then Cons(x, listConcat(xs', ys)) -//│ fun listConcat: forall 'A 'A0 'a. (Cons['A] | Nil, List['A0] & 'a) -> (Cons['A0] | 'a) +//│ fun listConcat: forall 'A 'A0 'a. (Cons[out 'A & ('A0 | ~??A)] | Nil, List['A0] & 'a) -> (Cons['A0] | 'a) //│ where -//│ 'A <: 'A0 +//│ 'A0 :> ??A & 'A fun listContains(xs, x) = if xs is @@ -91,7 +92,7 @@ fun listContains(xs, x) = Cons(x', xs') and eq(x)(x') then true _ then listContains(xs', x) -//│ fun listContains: forall 'A. (Cons['A] | Nil, anything) -> Bool +//│ fun listContains: (Cons[?] | Nil, anything) -> Bool // Remove all occurrences of x from xs. fun listWithout(xs, x) = @@ -100,9 +101,9 @@ fun listWithout(xs, x) = Cons(x', xs') and eq(x)(x') then listWithout(xs', x) _ then Cons(x', listWithout(xs', x)) -//│ fun listWithout: forall 'A 'A0. (Cons['A] | Nil, anything) -> (Cons['A0] | Nil) +//│ fun listWithout: forall 'A 'A0. (Cons[out 'A & ('A0 | ~??A)] | Nil, anything) -> (Cons['A0] | Nil) //│ where -//│ 'A <: 'A0 +//│ 'A0 :> ??A & 'A // * FIXME? @@ -111,7 +112,7 @@ fun listJoin(xs, sep) = Nil then "" Cons(x, Nil) then toString(x) Cons(x, xs') then toString(x) ++ sep ++ listJoin(xs', sep) -//│ fun listJoin: forall 'A. (Cons['A] | Nil, Str) -> Str +//│ fun listJoin: (Cons[?] | Nil, Str) -> Str fun listJoin(xs, sep) = if xs is @@ -119,7 +120,7 @@ fun listJoin(xs, sep) = Cons(x, xs') and xs' is Nil then toString(x) _ then toString(x) ++ sep ++ listJoin(xs', sep) -//│ fun listJoin: forall 'A. (Cons['A] | Nil, Str) -> Str +//│ fun listJoin: (Cons[?] | Nil, Str) -> Str listJoin(list3("x", "y", "z"), ", ") //│ Str @@ -228,14 +229,33 @@ showHasFree(App(Abs(Var("x"), Var("x")), Var("x")), "y") //│ res //│ = '((&x. x) x) DOES NOT have free variable y' +// // :d +// fun fv(t) = +// if t is +// Var(name) then list1(error) +// App(lhs, rhs) then listConcat(error, fv(rhs)) + +// fun fv(t) = +// if t is +// Var(name) then list1(error) +// App(lhs, rhs) then listConcat(fv(lhs), fv(rhs)) + +:Fuel 100000 +// :d +// :ex fun fv(t) = if t is Var(name) then list1(name) Abs(Var(name), body) then listWithout(fv(body), name) App(lhs, rhs) then listConcat(fv(lhs), fv(rhs)) -//│ fun fv: forall 'A. (Abs | App | Var) -> (Cons['A] | Nil) +//│ fun fv: forall 'A 'A0 'A1 'A2. (Abs | App | Var) -> (Cons[in 'A out 'A0] | Cons[in 'A1 out 'A0] | Nil) //│ where -//│ 'A :> Str +//│ 'A :> ??A & 'A0 | ??A0 & 'A0 | 'A0 +//│ <: 'A1 & ('A2 | ~??A) +//│ 'A1 <: 'A & ('A2 | ~??A) +//│ 'A2 <: 'A & 'A1 +//│ 'A0 :> 'A +:ResetFuel fun showFv(t) = showTerm(t) ++ if fv(t) is @@ -268,7 +288,7 @@ fun tryNextAlphabet(initialCode, currentCode, freeNames) = let name = fromCharCode(currentCode) listContains(freeNames, name) then tryNextAlphabet(initialCode, currentCode + 1, freeNames) _ then Some(name) -//│ fun tryNextAlphabet: forall 'A. (Num, Int, Cons['A] | Nil) -> (None | Some[Str]) +//│ fun tryNextAlphabet: (Num, Int, Cons[?] | Nil) -> (None | Some[Str]) tryNextAlphabet(97, 97, list1("a")).toString() tryNextAlphabet(97, 98, list1("a")).toString() @@ -293,7 +313,7 @@ fun tryAppendDigits(name, index, freeNames) = listContains(freeNames, currentName) then tryAppendDigits(name, index + 1, freeNames) _ then currentName -//│ fun tryAppendDigits: forall 'A. (Str, Int, Cons['A] | Nil) -> Str +//│ fun tryAppendDigits: (Str, Int, Cons[?] | Nil) -> Str // Note: some weird behavior here... Just try the commented code. fun findFreshName(name, freeNames) = @@ -303,7 +323,7 @@ fun findFreshName(name, freeNames) = tryNextAlphabet(charCode, charCode + 1, freeNames) is Some(newName) then newName _ then tryAppendDigits(name, 0, freeNames) -//│ fun findFreshName: forall 'A 'A0 'A1. (Str, Cons[in 'A | 'A0 | 'A1 out 'A & 'A0 & 'A1] | Nil) -> Str +//│ fun findFreshName: (Str, Cons[?] | Nil) -> Str // Find a fresh name to replace `name` that does not conflict with any bound // variables in the `body`. @@ -319,7 +339,7 @@ fun subst(t, n, v) = _ then Abs(Var(name), subst(body, n, v)) App(lhs, rhs) then App(subst(lhs, n, v), subst(rhs, n, v)) _ then t -//│ fun subst: forall 'a. (Abs | App | Term & Object & 'a & ~#Abs & ~#App & ~#Var | Var, anything, Term & Object & 'a) -> ('a | Abs | App | Var) +//│ fun subst: forall 'a. (Abs | App | Term & Object & 'a & ~#Abs & ~#App & ~#Var | Var, anything, 'a & (Term & Object & ~#Var | Var & Term)) -> ('a | Abs | App | Var) fun showSubst(t, n, v) = showTerm(t) ++ " [" ++ n ++ " / " ++ showTerm(v) ++ "]" ++ " => " ++ showTerm(subst(t, n, v)) @@ -445,4 +465,4 @@ fun equalTerm(a, b) = Abs(la, ra) and b is Abs(lb, rb) then equalTerm(la, lb) && equalTerm(ra, rb) App(la, ra) and b is App(lb, rb) then equalTerm(la, lb) && equalTerm(ra, rb) _ then false -//│ fun equalTerm: (Object, Object) -> Bool +//│ fun equalTerm: (Object, Abs | App | Object & ~#Abs & ~#App & ~#Var | Var) -> Bool diff --git a/shared/src/test/diff/tapl/SimplyTyped.mls b/shared/src/test/diff/tapl/SimplyTyped.mls index 4ab0955e17..cc617ec0cf 100644 --- a/shared/src/test/diff/tapl/SimplyTyped.mls +++ b/shared/src/test/diff/tapl/SimplyTyped.mls @@ -249,78 +249,6 @@ fun typeTerm(t, ctx) = Err(message) then Err(message) Ok(PrimitiveType(name)) then Err(concat3("cannot apply primitive type `", name, "`")) Err(message) then Err(message) -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.235: fun typeTerm(t, ctx) = -//│ ║ ^^^^^^^^^^ -//│ ║ l.236: if t is -//│ ║ ^^^^^^^^^ -//│ ║ l.237: Lit(_, ty) then Ok(ty) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.238: Var(name) and find(ctx, name) is -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.239: Some(ty) then Ok(ty) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.240: None then Err(concat3("unbound variable `", name, "`")) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.241: Abs(Var(name), ty, body) and typeTerm(body, insert(ctx, name, ty)) is -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.242: Ok(resTy) then Ok(FunctionType(ty, resTy)) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.243: Err(message) then Err(message) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.244: App(lhs, rhs) and typeTerm(lhs, ctx) is -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.245: Ok(FunctionType(pTy, resTy)) and typeTerm(rhs, ctx) is -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.246: Ok(aTy) and -//│ ║ ^^^^^^^^^^^^^^^^^^^ -//│ ║ l.247: typeEqual(pTy, aTy) then Ok(resTy) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.248: _ then Err(concat5("expect the argument to be of type `", showType(pTy), "` but found `", showType(aTy), "`")) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.249: Err(message) then Err(message) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.250: Ok(PrimitiveType(name)) then Err(concat3("cannot apply primitive type `", name, "`")) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.251: Err(message) then Err(message) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. -//│ ╔══[ERROR] Cyclic-looking constraint while typing binding of lambda expression; a type annotation may be required -//│ ║ l.235: fun typeTerm(t, ctx) = -//│ ║ ^^^^^^^^^^ -//│ ║ l.236: if t is -//│ ║ ^^^^^^^^^ -//│ ║ l.237: Lit(_, ty) then Ok(ty) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.238: Var(name) and find(ctx, name) is -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.239: Some(ty) then Ok(ty) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.240: None then Err(concat3("unbound variable `", name, "`")) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.241: Abs(Var(name), ty, body) and typeTerm(body, insert(ctx, name, ty)) is -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.242: Ok(resTy) then Ok(FunctionType(ty, resTy)) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.243: Err(message) then Err(message) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.244: App(lhs, rhs) and typeTerm(lhs, ctx) is -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.245: Ok(FunctionType(pTy, resTy)) and typeTerm(rhs, ctx) is -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.246: Ok(aTy) and -//│ ║ ^^^^^^^^^^^^^^^^^^^ -//│ ║ l.247: typeEqual(pTy, aTy) then Ok(resTy) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.248: _ then Err(concat5("expect the argument to be of type `", showType(pTy), "` but found `", showType(aTy), "`")) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.249: Err(message) then Err(message) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.250: Ok(PrimitiveType(name)) then Err(concat3("cannot apply primitive type `", name, "`")) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ║ l.251: Err(message) then Err(message) -//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//│ ╙── Note: use flag `:ex` to see internal error info. //│ typeTerm: (Abs & 'a | App & 'b | Lit & {ty: 'ty & (FunctionType & 'c & 'd & 'e | PrimitiveType & {name: string})} | Var & {name: string}, Empty | Node & 'f & 'g,) -> (Err & { //│ message: forall 'message 'message0 'message1. string | 'message | 'message0 | 'message1 //│ } | Ok & {value: forall 'h. 'ty | 'lty | 'h | 'rhs}) @@ -376,78 +304,32 @@ fun showTypeTerm(t, ctx) = Err(message) then concat2("Type error: ", message) //│ showTypeTerm: (Abs & 'a & 'b | App & 'c & 'd | Lit & {ty: FunctionType & 'e & 'f & 'g & 'h | PrimitiveType & {name: string}} | Var & {name: string}, Empty | Node & 'i & 'j,) -> string //│ where +//│ 'i <: {key: string, left: Empty | Node & 'i & 'j, right: Empty | Node & 'i & 'j} //│ 'j <: { //│ key: string, //│ left: Empty | Node & 'j, //│ right: Empty | Node & 'j, -//│ value: FunctionType & 'h & 'k & 'l & 'm | PrimitiveType & {name: string} -//│ } -//│ 'm <: { -//│ lhs: PrimitiveType & {name: string} | 'n & (FunctionType & 'o | FunctionType & ~#FunctionType), -//│ rhs: FunctionType & 'h & 'k & 'l & 'm | PrimitiveType & {name: string} -//│ } -//│ 'o <: { -//│ lhs: FunctionType & 'o | PrimitiveType | ~FunctionType & ~PrimitiveType, -//│ rhs: FunctionType & 'o | PrimitiveType | ~FunctionType & ~PrimitiveType -//│ } -//│ 'n <: { -//│ lhs: FunctionType & 'n | PrimitiveType & {name: string}, -//│ rhs: FunctionType & 'n | PrimitiveType & {name: string} -//│ } -//│ 'l <: { -//│ lhs: FunctionType & 'l | PrimitiveType | ~FunctionType & ~PrimitiveType, -//│ rhs: FunctionType & 'l | PrimitiveType | ~FunctionType & ~PrimitiveType -//│ } -//│ 'k <: { -//│ lhs: FunctionType & 'k | PrimitiveType & {name: string}, -//│ rhs: FunctionType & 'k | PrimitiveType & {name: string} -//│ } -//│ 'i <: {key: string, left: Empty | Node & 'i & 'p, right: Empty | Node & 'i & 'p} -//│ 'p <: { -//│ key: string, -//│ left: Empty | Node & 'p, -//│ right: Empty | Node & 'p, -//│ value: FunctionType & 'h & 'q & 'r & 's | PrimitiveType & {name: string} -//│ } -//│ 's <: { -//│ lhs: PrimitiveType & {name: string} | 't & (FunctionType & 'u | FunctionType & ~#FunctionType), -//│ rhs: FunctionType & 'h & 'q & 'r & 's | PrimitiveType & {name: string} -//│ } -//│ 'u <: { -//│ lhs: FunctionType & 'u | PrimitiveType | ~FunctionType & ~PrimitiveType, -//│ rhs: FunctionType & 'u | PrimitiveType | ~FunctionType & ~PrimitiveType -//│ } -//│ 't <: { -//│ lhs: FunctionType & 't | PrimitiveType & {name: string}, -//│ rhs: FunctionType & 't | PrimitiveType & {name: string} -//│ } -//│ 'r <: { -//│ lhs: FunctionType & 'r | PrimitiveType | ~FunctionType & ~PrimitiveType, -//│ rhs: FunctionType & 'r | PrimitiveType | ~FunctionType & ~PrimitiveType -//│ } -//│ 'q <: { -//│ lhs: FunctionType & 'q | PrimitiveType & {name: string}, -//│ rhs: FunctionType & 'q | PrimitiveType & {name: string} +//│ value: FunctionType & 'e & 'f & 'g & 'h | PrimitiveType & {name: string} //│ } //│ 'b <: { //│ lhs: Abs & 'b | App & 'd | Lit | Var, -//│ lty: FunctionType & 'v | PrimitiveType & {name: string}, +//│ lty: FunctionType & 'k | PrimitiveType & {name: string}, //│ rhs: Abs & 'b | App & 'd | Lit | Var //│ } //│ 'd <: { //│ lhs: App & 'd | Lit | Var | 'b & (Abs & ~#Abs | Abs & { //│ lhs: Abs & 'b | App & 'd | Lit | Var, -//│ lty: FunctionType & 'v | PrimitiveType & {name: string} +//│ lty: FunctionType & 'k | PrimitiveType & {name: string} //│ }), //│ rhs: Abs & 'b | App & 'd | Lit | Var //│ } -//│ 'v <: { -//│ lhs: FunctionType & 'v | PrimitiveType & {name: string}, -//│ rhs: FunctionType & 'v | PrimitiveType & {name: string} +//│ 'k <: { +//│ lhs: FunctionType & 'k | PrimitiveType & {name: string}, +//│ rhs: FunctionType & 'k | PrimitiveType & {name: string} //│ } //│ 'a <: { //│ lhs: Var & {name: string}, -//│ lty: FunctionType & 'e & 'f & 'g & 'w & 'x & 'h | PrimitiveType & {name: string}, +//│ lty: FunctionType & 'e & 'f & 'l & 'm & 'g & 'h | PrimitiveType & {name: string}, //│ rhs: Abs & 'a | App & 'c | Lit & {ty: FunctionType & 'e & 'f & 'g & 'h | PrimitiveType & {name: string}} | Var & {name: string} //│ } //│ 'c <: { @@ -455,20 +337,20 @@ fun showTypeTerm(t, ctx) = //│ rhs: Abs & 'a | App & 'c | Lit & {ty: FunctionType & 'e & 'f & 'g & 'h | PrimitiveType & {name: string}} | Var & {name: string} //│ } //│ 'g <: { -//│ lhs: PrimitiveType & {name: string} | 'x & (FunctionType & 'w | FunctionType & ~#FunctionType), +//│ lhs: PrimitiveType & {name: string} | 'l & (FunctionType & 'm | FunctionType & ~#FunctionType), //│ rhs: FunctionType & 'e & 'f & 'g & 'h | PrimitiveType & {name: string} //│ } //│ 'h <: { //│ lhs: FunctionType & 'h | PrimitiveType & {name: string}, //│ rhs: FunctionType & 'h | PrimitiveType & {name: string} //│ } -//│ 'w <: { -//│ lhs: FunctionType & 'w | PrimitiveType | ~FunctionType & ~PrimitiveType, -//│ rhs: FunctionType & 'w | PrimitiveType | ~FunctionType & ~PrimitiveType +//│ 'm <: { +//│ lhs: FunctionType & 'm | PrimitiveType | ~FunctionType & ~PrimitiveType, +//│ rhs: FunctionType & 'm | PrimitiveType | ~FunctionType & ~PrimitiveType //│ } -//│ 'x <: { -//│ lhs: FunctionType & 'x | PrimitiveType & {name: string}, -//│ rhs: FunctionType & 'x | PrimitiveType & {name: string} +//│ 'l <: { +//│ lhs: FunctionType & 'l | PrimitiveType & {name: string}, +//│ rhs: FunctionType & 'l | PrimitiveType & {name: string} //│ } //│ 'f <: { //│ lhs: FunctionType & 'f | PrimitiveType | ~FunctionType & ~PrimitiveType, diff --git a/shared/src/test/diff/tapl/Untyped.mls b/shared/src/test/diff/tapl/Untyped.mls index 4967cce4a5..0354cec4fe 100644 --- a/shared/src/test/diff/tapl/Untyped.mls +++ b/shared/src/test/diff/tapl/Untyped.mls @@ -437,7 +437,12 @@ fun findFreshName(name, freeNames) = // Find a fresh name to replace `name` that does not conflict with any bound // variables in the `body`. fun freshName(name, body) = findFreshName(name, fv(body)) -//│ freshName: (string, Abs & 'a | App & 'b | Var,) -> string +//│ ╔══[ERROR] Cyclic-looking constraint while typing application; a type annotation may be required +//│ ║ l.439: fun freshName(name, body) = findFreshName(name, fv(body)) +//│ ║ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//│ ╙── Note: use flag `:ex` to see internal error info. +//│ TEST CASE FAILURE: There was an unexpected type error +//│ freshName: (string, Abs & 'a | App & 'b | Var,) -> (error | string) //│ where //│ 'a <: {lhs: Var, rhs: Abs & 'a | App & 'b | Var} //│ 'b <: {lhs: Abs & 'a | App & 'b | Var, rhs: Abs & 'a | App & 'b | Var} @@ -452,21 +457,24 @@ fun subst(t, n, v) = _ then Abs(Var(name), subst(body, n, v)) App(lhs, rhs) then App(subst(lhs, n, v), subst(rhs, n, v)) _ then t -//│ subst: (Abs & 'a | App & 'b | Var & 'c | 'd & ~#Abs & ~#App & ~#Var, anything, 'e & (Var & 'd & ~#Var | Var & 'c | 'f & (App & 'd & ~#App | 'b & (App & 'g | App & ~#App)) | 'h & (Abs & 'd & ~#Abs | 'a & (Abs & 'i | Abs & ~#Abs))),) -> (Var & {name: string} | 'e | 'c | 'a | 'd) +//│ subst: (Abs & 'a | App & 'b | Var & 'c | 'd & ~#Abs & ~#App & ~#Var, anything, 'e & (Var & 'd & ~#Var | Var & 'c | 'f & (App & 'd & ~#App | 'b & (App & 'g | App & ~#App)) | 'h & (Abs & 'd & ~#Abs | 'a & (Abs & 'i | Abs & ~#Abs))),) -> (Var & {name: error | string} | 'e | 'c | 'a | 'd) //│ where //│ 'g <: { //│ lhs: Abs & 'i | App & 'g | Var | ~Abs & ~App & ~Var, //│ rhs: Abs & 'i | App & 'g | Var | ~Abs & ~App & ~Var //│ } //│ 'i <: {lhs: anything, rhs: Abs & 'i | App & 'g | Var | ~Abs & ~App & ~Var} -//│ 'a :> Abs & {lhs: Var & {name: string}, rhs: Var & {name: string} | 'e | 'c | 'a | 'd | 'rhs} +//│ 'a :> Abs & { +//│ lhs: Var & {name: error | string}, +//│ rhs: Var & {name: error | string} | 'e | 'c | 'a | 'd | 'rhs +//│ } //│ <: Abs & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'a & 'h | App & 'b & 'f | Var & 'c} & 'h | App & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'a & 'h | App & 'b & 'f | Var & 'c} & 'b & 'f | Var & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'a & 'h | App & 'b & 'f | Var & 'c} & 'c | 'd & (App & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'a & 'h | App & 'b & 'f | Var & 'c} & 'f & ~#App | Var & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'a & 'h | App & 'b & 'f | Var & 'c} & ~#Var) -//│ 'e :> Abs & {lhs: Var & {name: string}, rhs: 'rhs} | App & { -//│ lhs: Var & {name: string} | 'e | 'c | 'a | 'd, -//│ rhs: Var & {name: string} | 'e | 'c | 'a | 'd -//│ } | Var & {name: string} | 'c | 'a | 'd -//│ 'rhs :> Var & {name: string} | 'e | 'c | 'a | 'd -//│ 'c :> Var & {name: string} +//│ 'e :> Abs & {lhs: Var & {name: error | string}, rhs: 'rhs} | App & { +//│ lhs: Var & {name: error | string} | 'e | 'c | 'a | 'd, +//│ rhs: Var & {name: error | string} | 'e | 'c | 'a | 'd +//│ } | Var & {name: error | string} | 'c | 'a | 'd +//│ 'rhs :> Var & {name: error | string} | 'e | 'c | 'a | 'd +//│ 'c :> Var & {name: error | string} //│ <: Abs & {name: anything} & 'a & 'h | App & {name: anything} & 'b & 'f | Var | 'd & (Abs & {name: anything} & 'h & ~#Abs | App & {name: anything} & 'f & ~#App) //│ 'b <: { //│ lhs: Abs & 'a | App & 'b | Var & 'c | 'd & ~#Abs & ~#App & ~#Var, @@ -540,30 +548,30 @@ fun stepByValue(t) = Abs(Var(name), body) then Some(subst(body, name, rhs)) _ then None() //│ stepByValue: (Abs | App & 'a | Var) -> (None | Some & { -//│ value: Var & {name: string} | App & { -//│ lhs: Var & {name: string} | App & {lhs: 'lhs, rhs: Var & {name: string} | 'rhs | 'b | 'c | 'd | 'e} | 'rhs | 'b | 'c | 'd | 'e, +//│ value: Var & {name: error | string} | App & { +//│ lhs: Var & {name: error | string} | App & {lhs: 'lhs, rhs: Var & {name: error | string} | 'rhs | 'b | 'c | 'd | 'e} | 'rhs | 'b | 'c | 'd | 'e, //│ rhs: 'rhs -//│ } | App & {lhs: 'lhs, rhs: Var & {name: string} | 'rhs | 'b | 'c | 'd | 'e} | 'rhs | 'b | 'c | 'd | 'e +//│ } | App & {lhs: 'lhs, rhs: Var & {name: error | string} | 'rhs | 'b | 'c | 'd | 'e} | 'rhs | 'b | 'c | 'd | 'e //│ }) //│ where //│ 'a <: {lhs: 'lhs, rhs: 'rhs} //│ 'lhs <: Abs & ~#Abs | Abs & {rhs: Abs & 'd | App & 'f | Var & 'b | 'e & ~#Abs & ~#App & ~#Var} | App & 'a | Var //│ 'd :> Abs & { -//│ lhs: Var & {name: string}, -//│ rhs: Var & {name: string} | 'rhs | 'b | 'c | 'd | 'e | 'rhs0 +//│ lhs: Var & {name: error | string}, +//│ rhs: Var & {name: error | string} | 'rhs | 'b | 'c | 'd | 'e | 'rhs0 //│ } //│ <: Abs & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'd & 'g | App & 'h & 'f | Var & 'b} & 'g | Var & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'd & 'g | App & 'h & 'f | Var & 'b} & 'e & ~#Var | Var & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'd & 'g | App & 'h & 'f | Var & 'b} & 'b | 'h & (App & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'd & 'g | App & 'h & 'f | Var & 'b} & 'e & ~#App | App & {lhs: Var & {name: string} | ~Var, rhs: Abs & 'd & 'g | App & 'h & 'f | Var & 'b} & 'f) -//│ 'c :> Abs & {lhs: Var & {name: string}, rhs: 'rhs0} | App & { -//│ lhs: Var & {name: string} | 'rhs | 'b | 'c | 'd | 'e, -//│ rhs: Var & {name: string} | 'rhs | 'b | 'c | 'd | 'e -//│ } | Var & {name: string} | 'rhs | 'b | 'd | 'e -//│ 'rhs0 :> Var & {name: string} | 'rhs | 'b | 'c | 'd | 'e +//│ 'c :> Abs & {lhs: Var & {name: error | string}, rhs: 'rhs0} | App & { +//│ lhs: Var & {name: error | string} | 'rhs | 'b | 'c | 'd | 'e, +//│ rhs: Var & {name: error | string} | 'rhs | 'b | 'c | 'd | 'e +//│ } | Var & {name: error | string} | 'rhs | 'b | 'd | 'e +//│ 'rhs0 :> Var & {name: error | string} | 'rhs | 'b | 'c | 'd | 'e //│ 'rhs <: Abs & 'd & 'g & 'i | App & 'a & 'h & 'f & 'j | Var & 'b //│ 'f <: { //│ lhs: Abs & 'd | App & 'f | Var & 'b | 'e & ~#Abs & ~#App & ~#Var, //│ rhs: Abs & 'd | App & 'f | Var & 'b | 'e & ~#Abs & ~#App & ~#Var //│ } -//│ 'b :> Var & {name: string} +//│ 'b :> Var & {name: error | string} //│ <: Var | 'h & (App & {name: anything} & 'e & ~#App | App & {name: anything} & 'f) | 'g & (Abs & {name: anything} & 'e & ~#Abs | Abs & {name: anything} & 'd) //│ 'e <: Var & ~#Var | Var & 'b | 'h & (App & 'f | App & ~#App) | 'g & (Abs & 'd | Abs & ~#Abs) //│ 'i <: {lhs: anything, rhs: Abs & 'i | App & 'j | Var | ~Abs & ~App & ~Var} diff --git a/shared/src/test/diff/ucs/CrossBranchCapture.mls b/shared/src/test/diff/ucs/CrossBranchCapture.mls index 364aa0c6ed..02b4c68e9d 100644 --- a/shared/src/test/diff/ucs/CrossBranchCapture.mls +++ b/shared/src/test/diff/ucs/CrossBranchCapture.mls @@ -43,14 +43,14 @@ fun process(e) = Pair(Vec(xs), Vec(ys)) then n Pair(Vec(n), Numb(n)) then n Pair(Numb(n), Vec(n)) then n -//│ fun process: Pair[Numb | Vec, Numb | Vec] -> (Int | Numb | Array[Numb | Vec]) +//│ fun process: Pair[Numb | Vec | ~??A, Numb | Vec | ~??B] -> (Int | Numb | Array[Numb | Vec]) // * FIXME should warn, be rejected, or compare both values for equality fun process(e) = if e is Pair(Numb(n), Numb(n)) then n -//│ fun process: Pair[Numb, Numb] -> Int +//│ fun process: Pair[Numb | ~??A, Numb | ~??B] -> Int process(Pair(Numb(1), Numb(2))) //│ Int diff --git a/shared/src/test/diff/ucs/ElseIf.mls b/shared/src/test/diff/ucs/ElseIf.mls index 5b8446a1f0..8a0777e5b9 100644 --- a/shared/src/test/diff/ucs/ElseIf.mls +++ b/shared/src/test/diff/ucs/ElseIf.mls @@ -10,7 +10,7 @@ fun f(x, y) = if x === 0 then true 1 then false else false -//│ fun f: (Eql[0 | 1], Eql[0 | 1]) -> Bool +//│ fun f: (Eql[out 0 | 1], Eql[out 0 | 1]) -> Bool fun f(x, y) = if x === 0 then true @@ -18,7 +18,7 @@ fun f(x, y) = if x === else if y === 0 then true _ then false -//│ fun f: (Eql[0 | 1], Eql[0]) -> Bool +//│ fun f: (Eql[out 0 | 1], Eql[0]) -> Bool module Tru module Fals diff --git a/shared/src/test/diff/ucs/Hygiene.mls b/shared/src/test/diff/ucs/Hygiene.mls index 10424de6ff..c2b1dff1fb 100644 --- a/shared/src/test/diff/ucs/Hygiene.mls +++ b/shared/src/test/diff/ucs/Hygiene.mls @@ -11,14 +11,14 @@ class Right[out T](value: T) fun foo(x) = if x is Some(Left(y)) then x Some(x) then x -//│ fun foo: forall 'a. Some['a & (Left[anything] | Object & ~#Left)] -> 'a +//│ fun foo: forall 'T. Some['T & (Left[anything] | Object & ~#Left | ~??T)] -> (??T & 'T) foo(Some(Left(1))) -//│ Left[1] +//│ Left[1] & ??T //│ res //│ = Left {} foo(Some(2)) -//│ 2 +//│ 2 & ??T //│ res //│ = 2 diff --git a/shared/src/test/diff/ucs/HygienicBindings.mls b/shared/src/test/diff/ucs/HygienicBindings.mls index ca19c9412b..21274c31d2 100644 --- a/shared/src/test/diff/ucs/HygienicBindings.mls +++ b/shared/src/test/diff/ucs/HygienicBindings.mls @@ -26,7 +26,7 @@ fun h0(a) = a is Some(Left(y)) then y a is Some(Right(z)) then z a is None then 0 -//│ fun h0: forall 'a. (None | Some[Left['a] | Right['a]]) -> (0 | 'a) +//│ fun h0: forall 'A 'B. (None | Some[Left['A] | Right['B] | ~??T]) -> (0 | ??A & 'A | ??B & 'B) // FIXME: Precise scrutinee identification (easy) // This seems fine. But the subtrees are not merged. @@ -35,7 +35,7 @@ fun h1(a) = a is Some(x) and x is Left(y) then y a is Some(y) and y is Right(z) then z a is None then 0 -//│ fun h1: forall 'a. (None | Some[Right['a]]) -> (0 | 'a) +//│ fun h1: forall 'B. (None | Some[Right['B] | ~??T]) -> (0 | ??B & 'B) // This is the desugared version of the test case above. fun h1'(a) = @@ -53,7 +53,7 @@ fun h1'(a) = let z = y.rightValue z None then 0 -//│ fun h1': forall 'rightValue. (None | Some[Right['rightValue]]) -> (0 | 'rightValue) +//│ fun h1': forall 'B. (None | Some[Right['B] | ~??T]) -> (0 | ??B & 'B) // FIXME This seems fine but the desugared term does not merge the cases. // See the example below. @@ -62,42 +62,18 @@ fun h1''(a) = a is Some(x) and x is Left(y) then y a is Some(x) and x is Right(z) then z a is None then 0 -//│ fun h1'': forall 'a. (None | Some[Left['a] | Right['a]]) -> (0 | 'a) +//│ fun h1'': forall 'A 'B. (None | Some[Left['A] | Right['B] | ~??T]) -> (0 | ??A & 'A | ??B & 'B) // FIXME h1(Some(Left(0))) h1'(Some(Left(0))) h1''(Some(Left(0))) -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.68: h1(Some(Left(0))) -//│ ║ ^^^^^^^^^^^^^^^^^ -//│ ╟── application of type `Left[?A]` is not an instance of type `Right` -//│ ║ l.68: h1(Some(Left(0))) -//│ ║ ^^^^^^^ -//│ ╟── Note: constraint arises from class pattern: -//│ ║ l.36: a is Some(y) and y is Right(z) then z -//│ ║ ^^^^^ -//│ ╟── from field selection: -//│ ║ l.5: class Some[out T](val value: T) -//│ ║ ^^^^^ -//│ ╟── Note: type parameter T is defined at: -//│ ║ l.5: class Some[out T](val value: T) -//│ ╙── ^ -//│ ╔══[ERROR] Type mismatch in application: -//│ ║ l.69: h1'(Some(Left(0))) -//│ ║ ^^^^^^^^^^^^^^^^^^ -//│ ╟── application of type `Left[?A]` is not an instance of type `Right` -//│ ║ l.69: h1'(Some(Left(0))) -//│ ║ ^^^^^^^ -//│ ╟── Note: constraint arises from class pattern: -//│ ║ l.52: Right then -//│ ║ ^^^^^ -//│ ╟── from field selection: -//│ ║ l.45: let y = a.value -//│ ║ ^^^^^^^ -//│ ╟── Note: type parameter T is defined at: -//│ ║ l.5: class Some[out T](val value: T) -//│ ╙── ^ +//│ ╔══[ERROR] Type `Left[?A] & ??T` does not contain member `Right#B` +//│ ║ l.12: class Right[B](val rightValue: B) +//│ ╙── ^ +//│ ╔══[ERROR] Type `Left[?A] & ??T` does not contain member `Right#B` +//│ ║ l.12: class Right[B](val rightValue: B) +//│ ╙── ^ //│ 0 //│ res //│ = 0 @@ -115,12 +91,12 @@ fun h2(a) = y' is Right(z) then z a is None then 0 //│ ╔══[ERROR] identifier not found: y -//│ ║ l.114: let y' = y -//│ ╙── ^ +//│ ║ l.90: let y' = y +//│ ╙── ^ //│ ╔══[ERROR] identifier not found: y -//│ ║ l.114: let y' = y -//│ ╙── ^ -//│ fun h2: forall 'a. (None | Some[Left['a] | Object & ~#Left]) -> (0 | error | 'a) +//│ ║ l.90: let y' = y +//│ ╙── ^ +//│ fun h2: forall 'A. (None | Some[Left['A] | Object & ~#Left | ~??T]) -> (0 | ??A & 'A) //│ Code generation encountered an error: //│ unresolved symbol y @@ -133,7 +109,7 @@ fun h3(x, y, f, p) = h3("anything", "not me", _ => "should be me", _ => true) h3(None, "should be me", _ => "not me", _ => false) h3("anything", "anything", _ => "not me", _ => false) -//│ fun h3: forall 'a 'b. (None | Object & 'a & ~#None, 'b, (None | 'a) -> anything, (None | 'a) -> Object) -> ("anyway" | 'b) +//│ fun h3: forall 'a 'b. (None | Object & 'a & ~#None, 'b, (None | 'a) -> anything, None -> Object & 'a -> Object) -> ("anyway" | 'b) //│ "anything" | "anyway" //│ res //│ = 'not me' @@ -152,7 +128,7 @@ h4("should be me", "not me", _ => true) // WRONG! h4(None, "not me", _ => true) // WRONG! h4(None, "should be me", _ => false) h4("anything", "not me", _ => false) -//│ fun h4: forall 'a 'b. (None | Object & 'a & ~#None, 'b, (None | 'a) -> Object) -> ("default" | 'b) +//│ fun h4: forall 'a 'b. (None | Object & 'a & ~#None, 'b, None -> Object & 'a -> Object) -> ("default" | 'b) //│ "default" | "not me" //│ res //│ = 'not me' diff --git a/shared/src/test/diff/ucs/JSON.mls b/shared/src/test/diff/ucs/JSON.mls index 222be75ba3..ba22dc448f 100644 --- a/shared/src/test/diff/ucs/JSON.mls +++ b/shared/src/test/diff/ucs/JSON.mls @@ -104,10 +104,10 @@ fun listJoin(xs, sep) = //│ type List[A] = Cons[A] | Nil //│ module Nil //│ class Cons[A](head: A, tail: List[A]) -//│ fun listConcat: forall 'A 'A0 'a. (Cons['A] | Nil, List['A0] & 'a) -> (Cons['A0] | 'a) -//│ fun listJoin: forall 'A1. (Cons['A1] | Nil, Str) -> Str +//│ fun listConcat: forall 'A 'A0 'a. (Cons[out 'A & ('A0 | ~??A)] | Nil, List['A0] & 'a) -> (Cons['A0] | 'a) +//│ fun listJoin: (Cons[?] | Nil, Str) -> Str //│ where -//│ 'A <: 'A0 +//│ 'A0 :> ??A & 'A type TreeMap[out A] = Node[A] | Empty module Empty @@ -134,9 +134,19 @@ fun traverse(t, f) = //│ type TreeMap[A] = Empty | Node[A] //│ module Empty //│ class Node[A](key: Str, value: A, left: TreeMap[A], right: TreeMap[A]) -//│ fun insert: forall 'A. (Empty | Node['A], Str, 'A) -> Node['A] -//│ fun find: forall 'A0. (Empty | Node['A0], Str) -> (None | Some['A0]) -//│ fun traverse: forall 'a 'A1. (Empty | Node['a], (Str, 'a) -> 'A1) -> (Cons['A1] | Nil) +//│ fun insert: forall 'a. (Empty | Node[anything], Str, 'a) -> Node['a] +//│ fun find: forall 'A 'A0. (Empty | Node['A], Str) -> (None | Some[??A & 'A | 'A0]) +//│ fun traverse: forall 'A1 'A2 'A3 'A4 'A5 'A6 'A7. (Empty | Node['A1], (Str, ??A0 & 'A1) -> ('A2 & 'A4 & 'A7 & (~??A1 | 'A6 | ~'A2))) -> (Cons[in 'A7 out 'A2 & 'A5] | Nil) +//│ where +//│ 'A2 :> ??A1 & 'A3 | 'A4 | 'A5 +//│ <: 'A4 & 'A7 +//│ 'A3 :> 'A2 & 'A4 | 'A5 +//│ 'A4 :> ??A1 & 'A3 | 'A2 | 'A5 +//│ <: 'A2 & 'A7 & (~??A1 | 'A6 | ~'A2) +//│ 'A5 :> ??A1 & 'A3 | 'A6 +//│ 'A6 :> 'A5 | 'A4 | 'A2 +//│ <: 'A2 & 'A4 & 'A7 +//│ 'A7 <: 'A2 & 'A4 type JsonValue = JsonNull | JsonNumber | JsonString | JsonBoolean | JsonObject | JsonArray module JsonNull { @@ -245,9 +255,7 @@ fun expect(scanner, ch) = eq(ch)(ch') then ParseSuccess((), scanner.advance) else ParseFailure(concat4("expect '", ch, "' but found ", ch'), scanner) None then ParseFailure(concat3("expect '", ch, "' but found EOF"), scanner) -//│ fun expect: forall 'T. (Scanner & {advance: Scanner}, Str) -> (ParseFailure | ParseSuccess['T]) -//│ where -//│ 'T :> () +//│ fun expect: forall 'T. (Scanner & {advance: Scanner}, Str) -> (ParseFailure | ParseSuccess[() | 'T]) fun expectWord(scanner, word, result) = if @@ -262,7 +270,7 @@ fun expectWord(scanner, word, result) = ParseFailure(concat3("there should not be other alphabets after\"", word, "\""), scanner) else ParseSuccess(result, scanner) -//│ fun expectWord: forall 'T. (Scanner & {peek: Object & ~#Some | Some[anything], advance: Scanner}, Str, 'T) -> (ParseFailure | ParseSuccess['T]) +//│ fun expectWord: forall 'a 'T 'T0 'T1 'T2. (Scanner & {peek: Object & ~#Some | Some[anything], advance: Scanner}, Str, 'a & 'T & 'T0) -> (ParseFailure | ParseSuccess['T & 'T0 & ('a | 'T1 & 'T2)]) // If we put this function together with the next block, there will be type // mismatch errors. @@ -272,7 +280,7 @@ fun parseMatched(scanner, closingSymbol, parse, fn) = ParseSuccess(_, scanner) then ParseSuccess(fn(outcome), scanner) ParseFailure(message, scanner) then ParseFailure(message, scanner) ParseFailure(message, scanner) then ParseFailure(message, scanner) -//│ fun parseMatched: forall 'advance 'a 'T. ({advance: 'advance}, Str, 'advance -> (ParseFailure | ParseSuccess['a]), 'a -> 'T) -> (ParseFailure | ParseSuccess['T]) +//│ fun parseMatched: forall 'advance 'T 'T0. ({advance: 'advance}, Str, 'advance -> (ParseFailure | ParseSuccess['T]), (??T & 'T) -> 'T0) -> (ParseFailure | ParseSuccess['T0]) :ng fun parseEntries(scanner): ParseResult[TreeMap[JsonValue]] = error @@ -309,7 +317,7 @@ fun parse(scanner) = //│ fun parseElements: Scanner -> ParseResult[List[JsonValue]] //│ fun parseStringContent: anything -> ParseResult[Str] //│ fun parseNumber: anything -> ParseResult[JsonNumber] -//│ fun parse: forall 'T. Scanner -> (ParseFailure | ParseSuccess[in JsonValue & 'T out JsonNull | 'T | JsonBoolean | JsonString | JsonArray | JsonObject] | ParseResult[JsonNumber]) +//│ fun parse: forall 'T 'T0 'T1 'T2 'T3 'T4 'T5 'T6 'T7 'T8 'T9 'T10 'T11 'T12 'T13. Scanner -> (ParseFailure | ParseSuccess[JsonObject & 'T & 'T0 & 'T1 & 'T2 & 'T3 & 'T4 & 'T5 & 'T6 & 'T7 & 'T8 & 'T9 & 'T10 & 'T11 & 'T12 | 'T13 & (JsonString & 'T & 'T1 & 'T2 & 'T3 & 'T4 & 'T5 & 'T6 & 'T7 & 'T8 & 'T9 & 'T10 & 'T11 & 'T12 | 'T0 & (JsonBoolean & 'T & 'T9 & 'T10 & 'T11 & 'T12 | 'T1 & 'T2 & 'T3 & 'T4 & 'T5 & 'T6 & 'T7 & 'T8 & (JsonNull & 'T | 'T9 & 'T10 & 'T11 & 'T12 & (JsonArray | 'T))))] | ParseResult[JsonNumber]) :ng toString of parse of scan of " true" diff --git a/shared/src/test/diff/ucs/LeadingAnd.mls b/shared/src/test/diff/ucs/LeadingAnd.mls index 2303e4ebbe..79a16c682f 100644 --- a/shared/src/test/diff/ucs/LeadingAnd.mls +++ b/shared/src/test/diff/ucs/LeadingAnd.mls @@ -25,7 +25,7 @@ fun f(a, b) = if a is Some(av) //│ |#fun| |f|(|a|,| |b|)| |#=| |#if| |a| |is| |Some|(|av|)|→|and| |b| |is| |Some|(|bv|)|↵|#then| |av| |+| |bv|←| //│ AST: TypingUnit(List(NuFunDef(None,Var(f),None,List(),Left(Lam(Tup(List((None,Fld(_,Var(a))), (None,Fld(_,Var(b))))),If(IfOpApp(Var(a),Var(is),IfOpsApp(App(Var(Some),Tup(List((None,Fld(_,Var(av)))))),List((Var(and),IfThen(App(Var(is),Tup(List((None,Fld(_,Var(b))), (None,Fld(_,App(Var(Some),Tup(List((None,Fld(_,Var(bv))))))))))),App(Var(+),Tup(List((None,Fld(_,Var(av))), (None,Fld(_,Var(bv))))))))))),None)))))) //│ Parsed: fun f = (a, b,) => if a is Some(av,) ‹· and (is(b, Some(bv,),)) then +(av, bv,)›; -//│ fun f: (Some[Int], Some[Int]) -> Int +//│ fun f: (Some[Int | ~??T], Some[Int | ~??T0]) -> Int // TODO :p diff --git a/shared/src/test/diff/ucs/LitUCS.mls b/shared/src/test/diff/ucs/LitUCS.mls index 6c77687f0f..56bb3e536b 100644 --- a/shared/src/test/diff/ucs/LitUCS.mls +++ b/shared/src/test/diff/ucs/LitUCS.mls @@ -31,7 +31,7 @@ fun test(x: 0 | A) = //│ ╟── Note: constraint arises from class pattern: //│ ║ l.18: x is A then A //│ ╙── ^ -//│ fun test: (x: 0 | A) -> (0 | A) +//│ fun test: (x: 0 | A) -> (0 | A | error) fun test2(x) = if diff --git a/shared/src/test/diff/ucs/NestedBranches.mls b/shared/src/test/diff/ucs/NestedBranches.mls index 7aa2059ba1..3db1b20ea7 100644 --- a/shared/src/test/diff/ucs/NestedBranches.mls +++ b/shared/src/test/diff/ucs/NestedBranches.mls @@ -24,7 +24,7 @@ fun optionApply(x, y, f) = Some(yv) then Some(f(xv, yv)) None then None None then None -//│ fun optionApply: forall 'a 'b 'A. (None | Some['a], None | Some['b], ('a, 'b) -> 'A) -> (None | Some['A]) +//│ fun optionApply: forall 'A 'A0 'a. (None | Some['A], None | Some['A0], (??A & 'A, ??A0 & 'A0) -> 'a) -> (None | Some['a]) let zeroToThree = Cons(0, Cons(1, Cons(2, Cons(3, Nil)))) //│ let zeroToThree: Cons[0 | 1 | 2 | 3] @@ -39,15 +39,15 @@ fun mapPartition(f, xs) = if xs is Cons(x, xs) and mapPartition(f, xs) is Pair(l, r) and f(x) is Left(v) then Pair(Cons(v, l), r) Right(v) then Pair(l, Cons(v, r)) -//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil] +//│ fun mapPartition: forall 'A. ((??A & 'A) -> (Left[anything] | Right[anything]), Cons['A] | Nil) -> Pair[nothing, nothing] mapPartition(x => Left(x + 1), zeroToThree) -//│ Pair[Cons[Int] | Nil, Cons[nothing] | Nil] +//│ Pair[nothing, nothing] //│ res //│ = Pair {} mapPartition(f, zeroToThree) -//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil] +//│ Pair[nothing, nothing] //│ res //│ = Pair {} @@ -58,10 +58,10 @@ fun mapPartition(f, xs) = if xs is mapPartition(f, xs) is Pair(l, r) and f(x) is Left(v) then Pair(Cons(v, l), r) Right(v) then Pair(l, Cons(v, r)) -//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil] +//│ fun mapPartition: forall 'A. ((??A & 'A) -> (Left[anything] | Right[anything]), Cons['A] | Nil) -> Pair[nothing, nothing] mapPartition(f, zeroToThree) -//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil] +//│ Pair[nothing, nothing] //│ res //│ = Pair {} @@ -77,10 +77,10 @@ fun mapPartition(f, xs) = if xs is Pair(Cons(v, l), r) Right(v) then Pair(l, Cons(v, r)) -//│ fun mapPartition: forall 'a 'A 'A0. ('a -> (Left['A] | Right['A0]), Cons['a] | Nil) -> Pair[Cons['A] | Nil, Cons['A0] | Nil] +//│ fun mapPartition: forall 'A. ((??A & 'A) -> (Left[anything] | Right[anything]), Cons['A] | Nil) -> Pair[nothing, nothing] mapPartition(f, zeroToThree) -//│ Pair[Cons[0 | 1 | 2 | 3] | Nil, Cons[0 | 1 | 2 | 3] | Nil] +//│ Pair[nothing, nothing] //│ res //│ = Pair {} diff --git a/shared/src/test/diff/ucs/NuPlainConditionals.mls b/shared/src/test/diff/ucs/NuPlainConditionals.mls index 328fbf5c57..754207fe07 100644 --- a/shared/src/test/diff/ucs/NuPlainConditionals.mls +++ b/shared/src/test/diff/ucs/NuPlainConditionals.mls @@ -43,10 +43,10 @@ if Pair(0, 1) is Pair(a, b) then a > b else false fun foo(x) = x is Pair(a, b) and a > b -//│ fun foo: (Object & ~#Pair | Pair[Num]) -> Bool +//│ fun foo: (Object & ~#Pair | Pair[Num | ~??A]) -> Bool fun foo(x) = if x is Pair(a, b) then a > b else false -//│ fun foo: (Object & ~#Pair | Pair[Num]) -> Bool +//│ fun foo: (Object & ~#Pair | Pair[Num | ~??A]) -> Bool // TODO proper error diff --git a/shared/src/test/diff/ucs/SplitAroundOp.mls b/shared/src/test/diff/ucs/SplitAroundOp.mls index 198590fa4d..34bc5fa0de 100644 --- a/shared/src/test/diff/ucs/SplitAroundOp.mls +++ b/shared/src/test/diff/ucs/SplitAroundOp.mls @@ -12,7 +12,7 @@ fun f(x, b) = "1" then "s1" "2" then "s2" else ":p" -//│ fun f: (Eql["0" | "1" | "2" | 0 | 1 | 2], Object) -> (":p" | "n0" | "n1" | "n2" | "s0" | "s1" | "s2") +//│ fun f: (Eql[out "0" | "1" | "2" | 0 | 1 | 2], Object) -> (":p" | "n0" | "n1" | "n2" | "s0" | "s1" | "s2") fun f(x, y, a, b) = if x === 0 diff --git a/shared/src/test/diff/ucs/Tree.mls b/shared/src/test/diff/ucs/Tree.mls index 2802614176..05b4127bcc 100644 --- a/shared/src/test/diff/ucs/Tree.mls +++ b/shared/src/test/diff/ucs/Tree.mls @@ -20,7 +20,7 @@ fun find(t, v) = if t is v > v' then find(r, v) _ then Some(v) Empty then None -//│ fun find: forall 'A. (Empty | Node[Num], Num & 'A) -> (None | Some['A]) +//│ fun find: forall 'a. (Empty | Node[Num | ~??A], Num & 'a) -> (None | Some['a]) fun insert(t, v) = if t is Node(v', l, r) and @@ -28,7 +28,7 @@ fun insert(t, v) = if t is v > v' then Node(v', l, insert(r, v)) _ then t Empty then Node(v, Empty, Empty) -//│ fun insert: forall 'A. (Empty | Node[Num & 'A], Num & 'A) -> (Node[nothing] | Node['A]) +//│ fun insert: forall 'A 'a 'A0. (Empty | Node['A & (Num | ~??A)], Num & 'a & 'A0) -> (Node[??A & 'A] | Node['a & (??A & 'A | 'A0)]) find(Empty, 0) find(Node(0, Empty, Empty), 0) diff --git a/shared/src/test/diff/ucs/Wildcard.mls b/shared/src/test/diff/ucs/Wildcard.mls index 19908bf2e9..f9a3285354 100644 --- a/shared/src/test/diff/ucs/Wildcard.mls +++ b/shared/src/test/diff/ucs/Wildcard.mls @@ -23,7 +23,7 @@ fun w1(x, e_0, e_1) = Left(Some(lv)) then concat("Left of Some of ")(toString(lv)) _ and e_1 is y_1 and x is Right(Some(rv)) then concat("Right of Some of ")(toString(rv)) -//│ fun w1: (Left[None | Some[anything]] | Right[None | Some[anything]], anything, anything) -> Str +//│ fun w1: (Left[None | Some[anything] | ~??A] | Right[None | Some[anything] | ~??B], anything, anything) -> Str w1(Left(None), "a", "b") w1(Right(None), "a", "b") @@ -45,7 +45,7 @@ fun w2(x, p) = _ and p(x) then 2 None then 3 _ then 4 -//│ fun w2: forall 'a. (None | Object & 'a & ~#None & ~#Some | Some[anything], (None | 'a) -> Object) -> (1 | 2 | 3 | 4) +//│ fun w2: forall 'a. (None | Object & 'a & ~#None & ~#Some | Some[anything], None -> Object & 'a -> Object) -> (1 | 2 | 3 | 4) w2(Some(0), x => true) w2(None, x => true) @@ -66,7 +66,7 @@ fun w3(x, p) = if x is Some(xv) then concat("r2: ")(toString(xv)) None then "r3" _ then "r4" -//│ fun w3: forall 'a. (None | Object & 'a & ~#None & ~#Some | Some[anything], (None | Some[nothing] | 'a) -> Object) -> Str +//│ fun w3: forall 'a 'T. (None | Object & 'a & ~#None & ~#Some | Some['T], (None | Some[??T & 'T]) -> Object & 'a -> Object) -> Str // Expect "r1" w3(0, _ => true) @@ -142,7 +142,7 @@ fun w4(x, p) = if x is Some(xv) then concat("r2: ")(toString(xv)) None then "r3" _ then "r4" -//│ fun w4: forall 'a. (None | Object & 'a & ~#None & ~#Some | Some[anything], (None | Some[nothing] | 'a) -> Object) -> Str +//│ fun w4: forall 'a 'T. (None | Object & 'a & ~#None & ~#Some | Some['T], (None | Some[??T & 'T]) -> Object & 'a -> Object) -> Str // Expect "r1" @@ -221,7 +221,7 @@ fun w6(x, y) = Some(z) then z None then 0 else x -//│ fun w6: forall 'a. ('a, Object & ~#Some | Some['a]) -> (0 | 'a) +//│ fun w6: forall 'a 'T. ('a, Object & ~#Some | Some['T]) -> (0 | ??T & 'T | 'a) w6("42", Some(42)) w6("42", None) @@ -243,7 +243,7 @@ fun w7(x, f) = None then x Left(x) then x + 1 Right(x) then x + 2 -//│ fun w7: forall 'a 'b. (Left[Int] | Object & 'a & ~#Left & ~#Right | Right[Int], 'a -> (None | Some['b])) -> (Int | 'b | 'a) +//│ fun w7: forall 'a 'T. (Left[Int | ~??A] | Object & 'a & ~#Left & ~#Right | Right[Int | ~??B], 'a -> (None | Some['T])) -> (Int | ??T & 'T | 'a) // The results are wrong: w7(Left(99), _ => Some(0)) // => 0 diff --git a/shared/src/test/diff/ucs/zipWith.mls b/shared/src/test/diff/ucs/zipWith.mls index 6451eb48d5..7c05b317b8 100644 --- a/shared/src/test/diff/ucs/zipWith.mls +++ b/shared/src/test/diff/ucs/zipWith.mls @@ -77,14 +77,14 @@ fun zipWith_wrong(f, xs, ys) = and ys is Cons(y, ys) and zipWith_wrong(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail)) else None -//│ fun zipWith_wrong: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A]]) +//│ fun zipWith_wrong: forall 'A 'A0 'A1. ((??A & 'A, ??A0 & 'A0) -> 'A1, Cons['A] | Object & ~#Cons, Cons['A0] | Object & ~#Cons) -> (None | Some[Cons['A1]]) fun zipWith_wrong(f, xs, ys) = if xs is Cons(x, xs) and ys is Cons(y, ys) and zipWith_wrong(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail)) else None -//│ fun zipWith_wrong: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A]]) +//│ fun zipWith_wrong: forall 'A 'A0 'A1. ((??A & 'A, ??A0 & 'A0) -> 'A1, Cons['A] | Object & ~#Cons, Cons['A0] | Object & ~#Cons) -> (None | Some[Cons['A1]]) // * Notice the result is wrong (duh) zipWith_wrong(pairup, Nil, Nil) @@ -99,7 +99,7 @@ fun zipWith(f, xs, ys) = Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail)) Nil and ys is Nil then Some(Nil) else None -//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil]) +//│ fun zipWith: forall 'A 'A0. ((??A & 'A, ??A0 & 'A0) -> anything, Cons['A] | Object & ~#Cons, Cons['A0] | Nil | Object & ~#Cons & ~#Nil) -> (None | Some[nothing]) zipWith(pairup, Cons(0, Nil), Cons("0", Nil)).value.toArray //│ Array[anything] @@ -112,7 +112,7 @@ fun zipWith(f, xs, ys) = Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail)) Nil and ys is Nil then Some(Nil) else None -//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil]) +//│ fun zipWith: forall 'A 'A0. ((??A & 'A, ??A0 & 'A0) -> anything, Cons['A] | Object & ~#Cons, Cons['A0] | Nil | Object & ~#Cons & ~#Nil) -> (None | Some[nothing]) zipWith(pairup, Cons(0, Nil), Cons("0", Nil)).value.toArray //│ Array[anything] @@ -124,7 +124,7 @@ fun zipWith(f, xs, ys) = if xs is Cons(x, xs) and ys is Cons(y, ys) and zipWith(f, xs, ys) is Some(tail) then Some(Cons(f(x, y), tail)) else if xs is Nil and ys is Nil then Some(Nil) else None -//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil]) +//│ fun zipWith: forall 'A 'A0. ((??A & 'A, ??A0 & 'A0) -> anything, Cons['A] | Object & ~#Cons, Cons['A0] | Nil | Object & ~#Cons & ~#Nil) -> (None | Some[nothing]) zipWith(pairup, Cons(0, Nil), Cons("0", Nil)).value.toArray //│ Array[anything] @@ -138,7 +138,7 @@ fun zipWith(f, xs, ys) = else None else if xs is Nil and ys is Nil then Some(Nil) else None -//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (None | Some[Cons['A] | Nil]) +//│ fun zipWith: forall 'A 'A0. ((??A & 'A, ??A0 & 'A0) -> anything, Cons['A] | Object & ~#Cons, Cons['A0] | Nil | Object & ~#Cons & ~#Nil) -> (None | Some[nothing]) zipWith(pairup, Cons(0, Nil), Cons("0", Nil)).value.toArray //│ Array[anything] @@ -157,7 +157,7 @@ fun zipWith(f, xs, ys) = Nil then None Nil then if ys is Nil then Some(Nil) else None -//│ fun zipWith: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Nil, Cons['b] | Nil) -> (None | Some[Cons['A] | Nil]) +//│ fun zipWith: forall 'A 'A0. ((??A & 'A, ??A0 & 'A0) -> anything, Cons['A] | Nil, Cons['A0] | Nil) -> (None | Some[nothing]) zipWith(pairup, Nil, Nil).value.toArray //│ Array[anything] @@ -178,7 +178,7 @@ zipWith(pairup, Cons(0, Nil), Cons("0", Nil)).value.toArray let ls = zipWith(pairup, Cons(0, Cons(1, Nil)), Cons("0", Cons("1", Nil))) ls.value.toArray -//│ let ls: None | Some[Cons[[0 | 1, "0" | "1"]] | Nil] +//│ let ls: None | Some[nothing] //│ Array[anything] //│ ls //│ = Some {} @@ -191,11 +191,11 @@ fun zipWith_wrong2(f, xs, ys) = if xs is Cons(x, xs) and ys is Cons(y, ys) and zipWith_wrong2(f, xs, ys) is Some(tail) then Cons(Some(f(x, y)), tail) else if xs is Nil and ys is Nil then Some(Nil) else None -//│ fun zipWith_wrong2: forall 'a 'b 'A. (('a, 'b) -> 'A, Cons['a] | Object & ~#Cons, Cons['b] | Object & ~#Cons) -> (Cons[Some['A]] | None | Some[Nil]) +//│ fun zipWith_wrong2: forall 'A 'A0 'a. ((??A & 'A, ??A0 & 'A0) -> 'a, Cons['A] | Object & ~#Cons, Cons['A0] | Nil | Object & ~#Cons & ~#Nil) -> (Cons[Some['a]] | None | Some[Nil]) // * No type error! The definition and use are well-typed... zipWith_wrong2(pairup, Cons(0, Cons(1, Nil)), Cons("0", Cons("1", Nil))) -//│ Cons[Some[[0 | 1, "0" | "1"]]] | None | Some[Nil] +//│ Cons[Some[[??A & (0 | 1), ??A0 & ("0" | "1")]]] | None | Some[Nil] //│ res //│ = None { class: [class None] }