Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 9 additions & 0 deletions compiler/src/dotty/tools/dotc/core/TypeUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ class TypeUtils:
case defn.NamedTuple(_, _) => true
case _ => false

def derivesFromNamedTuple(using Context): Boolean = self match
case defn.NamedTuple(_, _) => true
case tp: MatchType =>
tp.bound.derivesFromNamedTuple || tp.reduced.derivesFromNamedTuple
case tp: TypeProxy => tp.superType.derivesFromNamedTuple
case tp: AndType => tp.tp1.derivesFromNamedTuple || tp.tp2.derivesFromNamedTuple
case tp: OrType => tp.tp1.derivesFromNamedTuple && tp.tp2.derivesFromNamedTuple
case _ => false

/** Drop all named elements in tuple type */
def stripNamedTuple(using Context): Type = self.normalized.dealias match
case defn.NamedTuple(_, vals) =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4641,7 +4641,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
case _: SelectionProto =>
tree // adaptations for selections are handled in typedSelect
case _ if ctx.mode.is(Mode.ImplicitsEnabled) && tree.tpe.isValueType =>
if tree.tpe.widen.isNamedTupleType && pt.derivesFrom(defn.TupleClass) then
if tree.tpe.derivesFromNamedTuple && pt.derivesFrom(defn.TupleClass) then
readapt(typed(untpd.Select(untpd.TypedSplice(tree), nme.toTuple)))
else if pt.isRef(defn.AnyValClass, skipRefined = false)
|| pt.isRef(defn.ObjectClass, skipRefined = false)
Expand Down
20 changes: 20 additions & 0 deletions tests/pos/named-tuple-downcast.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type Person = (name: String, age: Int)

val Bob: Person = (name = "Bob", age = 33)

type SI = (String, Int)

def id[X](x: X): X = x
val x: (String, Int) = Bob
val y: SI = id(Bob)
val and: Person & String = ???
val _: SI = and
val or: Person | (name: "Bob", age: 33) = ???
val _: SI = or

class C[P <: Person](p: P):
val x: (String, Int) = p




Loading