Skip to content

Fix type aliases in beta-reduction of polyfunctions #17054

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/BetaReduce.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ object BetaReduce:
case ref @ TypeRef(NoPrefix, _) =>
ref.symbol
case _ =>
val binding = TypeDef(newSymbol(ctx.owner, tparam.name, EmptyFlags, targ.tpe, coord = targ.span)).withSpan(targ.span)
val binding = TypeDef(newSymbol(ctx.owner, tparam.name, EmptyFlags, TypeAlias(targ.tpe), coord = targ.span)).withSpan(targ.span)
bindings += binding
binding.symbol

Expand Down
5 changes: 5 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,11 @@ object TreeChecker {
i"owner chain = ${tree.symbol.ownersIterator.toList}%, %, ctxOwners = ${ctx.outersIterator.map(_.owner).toList}%, %")
}

override def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(using Context): Tree = {
assert(sym.info.isInstanceOf[ClassInfo | TypeBounds], i"wrong type, expect a template or type bounds for ${sym.fullName}, but found: ${sym.info}")
super.typedTypeDef(tdef, sym)
}

override def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(using Context): Tree = {
val TypeDef(_, impl @ Template(constr, _, _, _)) = cdef: @unchecked
assert(cdef.symbol == cls)
Expand Down
28 changes: 16 additions & 12 deletions compiler/src/scala/quoted/runtime/impl/printers/SourceCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1345,18 +1345,22 @@ object SourceCode {
}

private def printBoundsTree(bounds: TypeBoundsTree)(using elideThis: Option[Symbol]): this.type = {
bounds.low match {
case Inferred() =>
case low =>
this += " >: "
printTypeTree(low)
}
bounds.hi match {
case Inferred() => this
case hi =>
this += " <: "
printTypeTree(hi)
}
if bounds.low.tpe == bounds.hi.tpe then
this += " = "
printTypeTree(bounds.low)
else
bounds.low match {
case Inferred() =>
case low =>
this += " >: "
printTypeTree(low)
}
bounds.hi match {
case Inferred() => this
case hi =>
this += " <: "
printTypeTree(hi)
}
}

private def printBounds(bounds: TypeBounds)(using elideThis: Option[Symbol]): this.type = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,66 @@ import scala.util.matching.Regex

object Scaladoc2AnchorCreator:

def getScaladoc2Type(using Quotes)(t: reflect.Tree) =
import reflect.*
val regex = t match
case d: DefDef => "def"
case t: TypeDef => "type"
case v: ValDef => "val|var"
t.show(using Printer.TreeShortCode).split(regex, 2)(1).replace(" ","")
def getScaladoc2Type(using Quotes)(sym: quotes.reflect.Symbol) = signatureAnchor(sym)

/** Creates the signature anchor
*
* - `X` for a `type X ...`
* - `x:X` for a `val x: X`
* - `f[U1,...](x1:T1,...)(impliciti1:U1,impliciti2:U2,...)...:R` for a `def f[U1, ...](x1: T1, ...)(implicit i1: U1, i2: U2...)...: R`
*
* Types are printed without their paths. No spaces are printed in the output.
*/
private def signatureAnchor(using Quotes)(sym: quotes.reflect.Symbol): String =
import quotes.reflect.*
def signatureType(tp: quotes.reflect.TypeRepr): String =
tp match
case mt @ MethodType(paramNames, paramTypes, res) =>
val implicitPrefix = if mt.isImplicit then "implicit" else ""
val closeClause = res match
case _: MethodOrPoly => ")"
case _ => "):"
paramNames.zip(paramTypes.map(signatureType))
.map((name, tpe) => s"$implicitPrefix$name:$tpe")
.mkString("(", ",", closeClause) + signatureType(res)
case PolyType(paramNames, paramBounds, res) =>
val closeClause = res match
case _: MethodOrPoly => "]"
case _ => "]:"
paramNames.zip(paramBounds.map(signatureType))
.map((name, tpe) => s"$name$tpe")
.mkString("[", ",", closeClause) + signatureType(res)
case TypeLambda(paramNames, paramBounds, res) =>
paramNames.zip(paramBounds.map(signatureType))
.map((name, tpe) => s"$name$tpe")
.mkString("[", ",", "]") + "=>" + signatureType(res)
case ByNameType(tp) =>
":" + signatureType(tp)
case TypeBounds(low, hi) =>
val lowBound = if low =:= defn.NothingClass.typeRef then "" else ">:" + signatureType(low)
val hiBound = if low =:= defn.AnyClass.typeRef then "" else "<:" + signatureType(hi)
lowBound + hiBound
case tp: ParamRef =>
tp.binder match
case binder: MethodType => binder.paramNames(tp.paramNum) + ".type"
case binder: PolyType => binder.paramNames(tp.paramNum)
case binder: LambdaType => binder.paramNames(tp.paramNum)
case AppliedType(tycon, args) =>
args.map {
case tp: TypeBounds => "_" + signatureType(tp)
case tp => signatureType(tp)
}.mkString(signatureType(tycon) + "[", ",", "]")
case tp: AnnotatedType =>
signatureType(tp.underlying) + "@" + tp.annotation.symbol.owner.name
case tp: ThisType =>
signatureType(tp.tref) + ".this"
case tp: TypeRef =>
tp.name
case tp =>
// TODO handle other cases without using show (show does not have a stable representation)
tp.show(using Printer.TypeReprShortCode).replace(" ","")

sym match
case sym if sym.isType => sym.name
case sym if sym.flags.is(Flags.Method) => sym.name + signatureType(sym.info)
case sym => sym.name + ":" + signatureType(sym.info)
2 changes: 1 addition & 1 deletion scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ class SymOpsWithLinkCache:
def constructPathForScaladoc2: String =
val l = escapeUrl(location.mkString("/"))
val scaladoc2Anchor = if anchor.isDefined then {
"#" + getScaladoc2Type(sym.tree)
"#" + getScaladoc2Type(sym)
} else ""
docURL + l + extension + scaladoc2Anchor

Expand Down
2 changes: 2 additions & 0 deletions tests/pos/i17052.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def test[F[_]](fAny: F[Any]) =
{ [X] => (fx: F[X]) => { val fx2: F[X] = fx; () } }.apply[Any](fAny)