Skip to content
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

Named tuples second implementation #19174

Merged
merged 68 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
9d1f20d
Improvements to tuples: Drop experimental
odersky Dec 13, 2023
2395ece
Improvements to Tuples: New methods
odersky Dec 13, 2023
64a79c9
Improvements to tuples: Allow prefix slice in fromArray
odersky Dec 13, 2023
cb95265
Improvements to tuples: Rearrange types into a more logical order
odersky Dec 13, 2023
6ae8252
Improvements to tuples: more new types and methods
odersky Dec 13, 2023
1f79b87
Add NamedTuple object to library
odersky Dec 2, 2023
b9899b7
Support for named tuples with new representation
odersky Dec 3, 2023
27d6288
Add doc page
odersky Dec 3, 2023
5dd48f9
Make NamedTuple covariant in its value type
odersky Dec 3, 2023
bd9bb8a
Various tweaks
odersky Dec 5, 2023
e0a11cd
Harden NamedTuple handling against ill-formed NamedTuples
odersky Dec 5, 2023
b9d86fe
Fix test
odersky Dec 5, 2023
0fbdb49
Simplify tupleElementTypes unapply handling
odersky Dec 8, 2023
6f53dcd
Fix pattern matching for get matches
odersky Dec 8, 2023
b44f15d
Another fix for named get patterns
odersky Dec 14, 2023
02aa578
Avoid widening into unreducible types when inferring types
odersky Dec 14, 2023
b7115e7
Fix rebase breakage
odersky Jan 12, 2024
5c9bb5f
Make NamedTuples work under new MatchType spec
odersky Jan 12, 2024
4758830
Avoid TypeError exception in RefinedPrinter
odersky Jan 12, 2024
18f600d
Move named-tuples-strawman.ccala to pending
odersky Jan 12, 2024
5513ed6
Update check file
odersky Jan 12, 2024
fb1541a
Better printing of NamedTuple type trees
odersky Jan 14, 2024
cf09b19
Add FieldsOf type
odersky Jan 14, 2024
4baa509
Describe and add tests for source incompabilities
odersky Jan 14, 2024
702dcd5
Rename NamedTuple.FieldsOf --> NamedTuple.From
odersky Jan 14, 2024
1e31d16
Implement Fields as a Selectable type member
odersky Feb 5, 2024
22e6c89
Refactor typedSelect
odersky Feb 5, 2024
d0888f6
Add section on computable field names to reference doc page
odersky Feb 5, 2024
69964b0
Fix fields as a selectable type member
odersky Feb 6, 2024
a3409e0
Make NamedTuple.From work for named tuple arguments
odersky Feb 6, 2024
111674c
Fix NamedArg term/type classification
odersky Feb 7, 2024
1fd5962
Rename inMode to withModeBits
odersky Feb 10, 2024
c0b792f
Revert NamedArg term/type classification
odersky Feb 10, 2024
611861b
Update MimaFilters
odersky Feb 10, 2024
640da16
Fix rebase breakage in Parsers.scala
odersky Feb 16, 2024
67c0af2
Add tyql test case
odersky Feb 16, 2024
2cd5d7e
Introduce auto-conversion from named tuples to tuples
odersky Feb 17, 2024
d8b7595
Update documentation following review suggestions
odersky Feb 18, 2024
e0eb247
Drop TreeInfo's `dropNamedArg`
odersky Apr 24, 2024
4279a58
Print wildcard types in named tuples correctly
odersky Apr 24, 2024
c0bd1e4
Don't abbreviate tuple bindings if right-hand-side is named
odersky Apr 24, 2024
b997f3d
Strip named tuple from scrutinee when testing refutability of a named…
odersky Apr 24, 2024
2206d88
Fix tuple selection in pattern matcher
odersky Apr 24, 2024
ca19f1a
Fixes to NamedTuple
odersky Apr 25, 2024
984fe62
More tests
odersky Apr 25, 2024
21bcfef
Mention restriction against `_1`, `_2`, ... as named tuple labels
odersky Apr 25, 2024
92d22c9
Address review comments on Tuple.scala
odersky Apr 26, 2024
1613ee1
Reject recursive dynamicSelect corner case
odersky Apr 27, 2024
a04d3a7
Update compiler/src/dotty/tools/dotc/typer/Typer.scala
odersky Apr 27, 2024
37b1bd2
Update tests/neg/unselectable-fields.check
odersky Apr 27, 2024
3f8f6c6
Use consistent naming and drop remaining braces in tuple type ops
EugeneFlesselle Apr 29, 2024
9627c08
Add an infix shorthand for `Append[X, Y]`
EugeneFlesselle Apr 29, 2024
8a4162f
Drop unreachable case from `type Zip`
EugeneFlesselle Apr 29, 2024
0ab9e7b
Document `Concat` covariance in 2nd parameter
EugeneFlesselle Apr 29, 2024
075b7d1
Refine bounds of `type Filter` predicate
EugeneFlesselle Apr 29, 2024
c58c8c2
Do `contains` runtime operation based on term equality
EugeneFlesselle Apr 29, 2024
57b17ac
Do `indexOf` runtime operation based on term equality
EugeneFlesselle Apr 29, 2024
f427ec9
Do `filter` runtime operation based on a term level predicate
EugeneFlesselle Apr 29, 2024
94b7c1f
Mark `type Append` 2nd argument as covariant
EugeneFlesselle Apr 29, 2024
5df2120
Move `NonEmptyTuple` methods into `Tuple`
EugeneFlesselle Apr 29, 2024
40c6138
Reorder operations to be same between term and type level
EugeneFlesselle Apr 29, 2024
03509b8
Drop braces remaining at term level
EugeneFlesselle Apr 29, 2024
9047ac3
Fix `def indexOf` to return the size instead of -1
EugeneFlesselle May 1, 2024
579e14a
Revert doing tuple runtime operations based on a term level predicates
EugeneFlesselle May 1, 2024
8d6fa37
Make named-tuples-strawman-2.scala a run test
EugeneFlesselle May 1, 2024
1e29c4f
import language.experimental.namedTuples in pos/fieldsOf.scala
EugeneFlesselle May 2, 2024
0c89c92
Undo all unnecessary changes to Tuples.
odersky May 7, 2024
f80a8dd
Revert the addition of `type Fields` in `Selectable`.
sjrd May 6, 2024
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
110 changes: 94 additions & 16 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import Decorators.*
import Annotations.Annotation
import NameKinds.{UniqueName, ContextBoundParamName, ContextFunctionParamName, DefaultGetterName, WildcardParamName}
import typer.{Namer, Checking}
import util.{Property, SourceFile, SourcePosition, Chars}
import util.{Property, SourceFile, SourcePosition, SrcPos, Chars}
import config.Feature.{sourceVersion, migrateTo3, enabled}
import config.SourceVersion.*
import collection.mutable.ListBuffer
import collection.mutable
import reporting.*
import annotation.constructorOnly
import printing.Formatting.hl
Expand Down Expand Up @@ -234,7 +234,7 @@ object desugar {

private def elimContextBounds(meth: DefDef, isPrimaryConstructor: Boolean)(using Context): DefDef =
val DefDef(_, paramss, tpt, rhs) = meth
val evidenceParamBuf = ListBuffer[ValDef]()
val evidenceParamBuf = mutable.ListBuffer[ValDef]()

var seenContextBounds: Int = 0
def desugarContextBounds(rhs: Tree): Tree = rhs match
Expand Down Expand Up @@ -1254,8 +1254,9 @@ object desugar {
pats.forall(isVarPattern)
case _ => false
}

val isMatchingTuple: Tree => Boolean = {
case Tuple(es) => isTuplePattern(es.length)
case Tuple(es) => isTuplePattern(es.length) && !hasNamedArg(es)
case _ => false
}

Expand Down Expand Up @@ -1441,22 +1442,99 @@ object desugar {
AppliedTypeTree(
TypeTree(defn.throwsAlias.typeRef).withSpan(op.span), tpt :: excepts :: Nil)

/** Translate tuple expressions of arity <= 22
private def checkWellFormedTupleElems(elems: List[Tree])(using Context): List[Tree] =
val seen = mutable.Set[Name]()
for case arg @ NamedArg(name, _) <- elems do
if seen.contains(name) then
report.error(em"Duplicate tuple element name", arg.srcPos)
seen += name
if name.startsWith("_") && name.toString.tail.toIntOption.isDefined then
report.error(
em"$name cannot be used as the name of a tuple element because it is a regular tuple selector",
odersky marked this conversation as resolved.
Show resolved Hide resolved
arg.srcPos)

elems match
case elem :: elems1 =>
val mismatchOpt =
if elem.isInstanceOf[NamedArg]
then elems1.find(!_.isInstanceOf[NamedArg])
else elems1.find(_.isInstanceOf[NamedArg])
mismatchOpt match
case Some(misMatch) =>
report.error(em"Illegal combination of named and unnamed tuple elements", misMatch.srcPos)
elems.mapConserve(stripNamedArg)
case None => elems
case _ => elems
end checkWellFormedTupleElems

/** Translate tuple expressions
*
* () ==> ()
* (t) ==> t
* (t1, ..., tN) ==> TupleN(t1, ..., tN)
*/
def smallTuple(tree: Tuple)(using Context): Tree = {
val ts = tree.trees
val arity = ts.length
assert(arity <= Definitions.MaxTupleArity)
def tupleTypeRef = defn.TupleType(arity).nn
if (arity == 0)
if (ctx.mode is Mode.Type) TypeTree(defn.UnitType) else unitLiteral
else if (ctx.mode is Mode.Type) AppliedTypeTree(ref(tupleTypeRef), ts)
else Apply(ref(tupleTypeRef.classSymbol.companionModule.termRef), ts)
}
def tuple(tree: Tuple, pt: Type)(using Context): Tree =
var elems = checkWellFormedTupleElems(tree.trees)
if ctx.mode.is(Mode.Pattern) then elems = adaptPatternArgs(elems, pt)
val elemValues = elems.mapConserve(stripNamedArg)
val tup =
val arity = elems.length
if arity <= Definitions.MaxTupleArity then
def tupleTypeRef = defn.TupleType(arity).nn
val tree1 =
if arity == 0 then
if ctx.mode is Mode.Type then TypeTree(defn.UnitType) else unitLiteral
else if ctx.mode is Mode.Type then AppliedTypeTree(ref(tupleTypeRef), elemValues)
else Apply(ref(tupleTypeRef.classSymbol.companionModule.termRef), elemValues)
tree1.withSpan(tree.span)
else
cpy.Tuple(tree)(elemValues)
val names = elems.collect:
case NamedArg(name, arg) => name
if names.isEmpty || ctx.mode.is(Mode.Pattern) then
tup
else
def namesTuple = withModeBits(ctx.mode &~ Mode.Pattern | Mode.Type):
tuple(Tuple(
names.map: name =>
SingletonTypeTree(Literal(Constant(name.toString))).withSpan(tree.span)),
WildcardType)
if ctx.mode.is(Mode.Type) then
AppliedTypeTree(ref(defn.NamedTupleTypeRef), namesTuple :: tup :: Nil)
else
TypeApply(
Apply(Select(ref(defn.NamedTupleModule), nme.withNames), tup),
namesTuple :: Nil)

/** When desugaring a list pattern arguments `elems` adapt them and the
* expected type `pt` to each other. This means:
* - If `elems` are named pattern elements, rearrange them to match `pt`.
* This requires all names in `elems` to be also present in `pt`.
*/
def adaptPatternArgs(elems: List[Tree], pt: Type)(using Context): List[Tree] =

def reorderedNamedArgs(wildcardSpan: Span): List[untpd.Tree] =
var selNames = pt.namedTupleElementTypes.map(_(0))
if selNames.isEmpty && pt.classSymbol.is(CaseClass) then
selNames = pt.classSymbol.caseAccessors.map(_.name.asTermName)
val nameToIdx = selNames.zipWithIndex.toMap
val reordered = Array.fill[untpd.Tree](selNames.length):
untpd.Ident(nme.WILDCARD).withSpan(wildcardSpan)
for case arg @ NamedArg(name: TermName, _) <- elems do
nameToIdx.get(name) match
case Some(idx) =>
if reordered(idx).isInstanceOf[Ident] then
reordered(idx) = arg
else
report.error(em"Duplicate named pattern", arg.srcPos)
case _ =>
report.error(em"No element named `$name` is defined in selector type $pt", arg.srcPos)
reordered.toList

elems match
case (first @ NamedArg(_, _)) :: _ => reorderedNamedArgs(first.span.startPos)
case _ => elems
end adaptPatternArgs

private def isTopLevelDef(stat: Tree)(using Context): Boolean = stat match
case _: ValDef | _: PatDef | _: DefDef | _: Export | _: ExtMethods => true
Expand Down Expand Up @@ -1990,7 +2068,7 @@ object desugar {
* without duplicates
*/
private def getVariables(tree: Tree, shouldAddGiven: Context ?=> Bind => Boolean)(using Context): List[VarInfo] = {
val buf = ListBuffer[VarInfo]()
val buf = mutable.ListBuffer[VarInfo]()
def seenName(name: Name) = buf exists (_._1.name == name)
def add(named: NameTree, t: Tree): Unit =
if (!seenName(named.name) && named.name.isTermName) buf += ((named, t))
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ trait TreeInfo[T <: Untyped] { self: Trees.Instance[T] =>
case _ =>
tree

def stripNamedArg(tree: Tree) = tree match
case NamedArg(_, arg) => arg
case _ => tree

/** The number of arguments in an application */
def numArgs(tree: Tree): Int = unsplice(tree) match {
case Apply(fn, args) => numArgs(fn) + args.length
Expand Down
10 changes: 5 additions & 5 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def forwardTo: Tree = t
}
case class Tuple(trees: List[Tree])(implicit @constructorOnly src: SourceFile) extends Tree {
override def isTerm: Boolean = trees.isEmpty || trees.head.isTerm
override def isTerm: Boolean = trees.isEmpty || stripNamedArg(trees.head).isTerm
override def isType: Boolean = !isTerm
}
case class Throw(expr: Tree)(implicit @constructorOnly src: SourceFile) extends TermTree
Expand Down Expand Up @@ -528,15 +528,15 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def makeSelfDef(name: TermName, tpt: Tree)(using Context): ValDef =
ValDef(name, tpt, EmptyTree).withFlags(PrivateLocal)

def makeTupleOrParens(ts: List[Tree])(using Context): Tree = ts match {
def makeTupleOrParens(ts: List[Tree])(using Context): Tree = ts match
case (t: NamedArg) :: Nil => Tuple(t :: Nil)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will probably need a warning of changing behaviour, before this would be considered an assignment in parens:

scala> var x = 0
var x: Int = 0

scala> (x = 23)

scala> println(x)
23

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted for further work. We need to think of this migration when named tuples become standard.

case t :: Nil => Parens(t)
case _ => Tuple(ts)
}

def makeTuple(ts: List[Tree])(using Context): Tree = ts match {
def makeTuple(ts: List[Tree])(using Context): Tree = ts match
case (t: NamedArg) :: Nil => Tuple(t :: Nil)
case t :: Nil => t
case _ => Tuple(ts)
}

def makeAndType(left: Tree, right: Tree)(using Context): AppliedTypeTree =
AppliedTypeTree(ref(defn.andType.typeRef), left :: right :: Nil)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/Feature.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ object Feature:
val pureFunctions = experimental("pureFunctions")
val captureChecking = experimental("captureChecking")
val into = experimental("into")
val namedTuples = experimental("namedTuples")

def experimentalAutoEnableFeatures(using Context): List[TermName] =
defn.languageExperimentalFeatures
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ object Contexts {
inline def atPhaseNoEarlier[T](limit: Phase)(inline op: Context ?=> T)(using Context): T =
op(using if !limit.exists || limit <= ctx.phase then ctx else ctx.withPhase(limit))

inline private def inMode[T](mode: Mode)(inline op: Context ?=> T)(using ctx: Context): T =
inline def withModeBits[T](mode: Mode)(inline op: Context ?=> T)(using ctx: Context): T =
op(using if mode != ctx.mode then ctx.fresh.setMode(mode) else ctx)

inline def withMode[T](mode: Mode)(inline op: Context ?=> T)(using ctx: Context): T =
inMode(ctx.mode | mode)(op)
withModeBits(ctx.mode | mode)(op)

inline def withoutMode[T](mode: Mode)(inline op: Context ?=> T)(using ctx: Context): T =
inMode(ctx.mode &~ mode)(op)
withModeBits(ctx.mode &~ mode)(op)

/** A context is passed basically everywhere in dotc.
* This is convenient but carries the risk of captured contexts in
Expand Down
17 changes: 16 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,9 @@ class Definitions {
def TupleXXL_fromIterator(using Context): Symbol = TupleXXLModule.requiredMethod("fromIterator")
def TupleXXL_unapplySeq(using Context): Symbol = TupleXXLModule.requiredMethod(nme.unapplySeq)

@tu lazy val NamedTupleModule = requiredModule("scala.NamedTuple")
@tu lazy val NamedTupleTypeRef: TypeRef = NamedTupleModule.termRef.select(tpnme.NamedTuple).asInstanceOf

@tu lazy val RuntimeTupleMirrorTypeRef: TypeRef = requiredClassRef("scala.runtime.TupleMirror")

@tu lazy val RuntimeTuplesModule: Symbol = requiredModule("scala.runtime.Tuples")
Expand Down Expand Up @@ -1304,9 +1307,20 @@ class Definitions {
case ByNameFunction(_) => true
case _ => false

object NamedTuple:
def apply(nmes: Type, vals: Type)(using Context): Type =
AppliedType(NamedTupleTypeRef, nmes :: vals :: Nil)
def unapply(t: Type)(using Context): Option[(Type, Type)] = t match
case AppliedType(tycon, nmes :: vals :: Nil) if tycon.typeSymbol == NamedTupleTypeRef.symbol =>
Some((nmes, vals))
case _ => None

final def isCompiletime_S(sym: Symbol)(using Context): Boolean =
sym.name == tpnme.S && sym.owner == CompiletimeOpsIntModuleClass

final def isNamedTuple_From(sym: Symbol)(using Context): Boolean =
sym.name == tpnme.From && sym.owner == NamedTupleModule.moduleClass

private val compiletimePackageAnyTypes: Set[Name] = Set(
tpnme.Equals, tpnme.NotEquals, tpnme.IsConst, tpnme.ToString
)
Expand Down Expand Up @@ -1335,7 +1349,7 @@ class Definitions {
tpnme.Plus, tpnme.Length, tpnme.Substring, tpnme.Matches, tpnme.CharAt
)
private val compiletimePackageOpTypes: Set[Name] =
Set(tpnme.S)
Set(tpnme.S, tpnme.From)
++ compiletimePackageAnyTypes
++ compiletimePackageIntTypes
++ compiletimePackageLongTypes
Expand All @@ -1348,6 +1362,7 @@ class Definitions {
compiletimePackageOpTypes.contains(sym.name)
&& (
isCompiletime_S(sym)
|| isNamedTuple_From(sym)
|| sym.owner == CompiletimeOpsAnyModuleClass && compiletimePackageAnyTypes.contains(sym.name)
|| sym.owner == CompiletimeOpsIntModuleClass && compiletimePackageIntTypes.contains(sym.name)
|| sym.owner == CompiletimeOpsLongModuleClass && compiletimePackageLongTypes.contains(sym.name)
Expand Down
5 changes: 5 additions & 0 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ object StdNames {
val EnumValue: N = "EnumValue"
val ExistentialTypeTree: N = "ExistentialTypeTree"
val Flag : N = "Flag"
val Fields: N = "Fields"
val From: N = "From"
val Ident: N = "Ident"
val Import: N = "Import"
val Literal: N = "Literal"
Expand All @@ -374,6 +376,7 @@ object StdNames {
val MirroredMonoType: N = "MirroredMonoType"
val MirroredType: N = "MirroredType"
val Modifiers: N = "Modifiers"
val NamedTuple: N = "NamedTuple"
val NestedAnnotArg: N = "NestedAnnotArg"
val NoFlags: N = "NoFlags"
val NoPrefix: N = "NoPrefix"
Expand Down Expand Up @@ -620,6 +623,7 @@ object StdNames {
val throws: N = "throws"
val toArray: N = "toArray"
val toList: N = "toList"
val toTuple: N = "toTuple"
val toObjectArray : N = "toObjectArray"
val toSeq: N = "toSeq"
val toString_ : N = "toString"
Expand Down Expand Up @@ -649,6 +653,7 @@ object StdNames {
val wildcardType: N = "wildcardType"
val withFilter: N = "withFilter"
val withFilterIfRefutable: N = "withFilterIfRefutable$"
val withNames: N = "withNames"
val WorksheetWrapper: N = "WorksheetWrapper"
val wrap: N = "wrap"
val writeReplace: N = "writeReplace"
Expand Down
28 changes: 25 additions & 3 deletions compiler/src/dotty/tools/dotc/core/TypeEval.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import Types.*, Contexts.*, Symbols.*, Constants.*, Decorators.*
import config.Printers.typr
import reporting.trace
import StdNames.tpnme
import Flags.CaseClass
import TypeOps.nestedPairs

object TypeEval:

def tryCompiletimeConstantFold(tp: AppliedType)(using Context): Type = tp.tycon match
case tycon: TypeRef if defn.isCompiletimeAppliedType(tycon.symbol) =>

extension (tp: Type) def fixForEvaluation: Type =
tp.normalized.dealias match
// enable operations for constant singleton terms. E.g.:
Expand Down Expand Up @@ -94,6 +97,22 @@ object TypeEval:
throw TypeError(em"${e.getMessage.nn}")
ConstantType(Constant(result))

def fieldsOf: Option[Type] =
expectArgsNum(1)
val arg = tp.args.head
val cls = arg.classSymbol
if cls.is(CaseClass) then
val fields = cls.caseAccessors
val fieldLabels = fields.map: field =>
ConstantType(Constant(field.name.toString))
val fieldTypes = fields.map(arg.memberInfo)
Some:
defn.NamedTupleTypeRef.appliedTo:
nestedPairs(fieldLabels) :: nestedPairs(fieldTypes) :: Nil
Comment on lines +110 to +111
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
defn.NamedTupleTypeRef.appliedTo:
nestedPairs(fieldLabels) :: nestedPairs(fieldTypes) :: Nil
defn.NamedTuple(nestedPairs(fieldLabels), nestedPairs(fieldTypes))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposed replacement does not compiler. There is no NamedTuple method in Definitions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's a NamedTuple object with apply method that's being used in some other places

else arg.widenDealias match
case arg @ defn.NamedTuple(_, _) => Some(arg)
case _ => None

def constantFold1[T](extractor: Type => Option[T], op: T => Any): Option[Type] =
expectArgsNum(1)
extractor(tp.args.head).map(a => runConstantOp(op(a)))
Expand Down Expand Up @@ -122,11 +141,14 @@ object TypeEval:
yield runConstantOp(op(a, b, c))

trace(i"compiletime constant fold $tp", typr, show = true) {
val name = tycon.symbol.name
val owner = tycon.symbol.owner
val sym = tycon.symbol
val name = sym.name
val owner = sym.owner
val constantType =
if defn.isCompiletime_S(tycon.symbol) then
if defn.isCompiletime_S(sym) then
constantFold1(natValue, _ + 1)
else if defn.isNamedTuple_From(sym) then
fieldsOf
else if owner == defn.CompiletimeOpsAnyModuleClass then name match
case tpnme.Equals => constantFold2(constValue, _ == _)
case tpnme.NotEquals => constantFold2(constValue, _ != _)
Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,12 @@ object TypeOps:
(tp.tp1.dealias, tp.tp2.dealias) match
case (tp1 @ AppliedType(tycon1, args1), tp2 @ AppliedType(tycon2, args2))
if tycon1.typeSymbol == tycon2.typeSymbol && (tycon1 =:= tycon2) =>
mergeRefinedOrApplied(tp1, tp2)
mergeRefinedOrApplied(tp1, tp2) match
Copy link
Member

@bishabosha bishabosha Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its not obvious here how this change relates to NamedTuples, or which example needs this change

case tp: AppliedType if tp.isUnreducibleWild =>
// fall back to or-dominators rather than inferring a type that would
// cause an unreducible type error later.
approximateOr(tp1, tp2)
case tp => tp
case (tp1, tp2) =>
approximateOr(tp1, tp2)
case _ =>
Expand Down
Loading