From 7465928b453f9a47b7e0abb7e09b4673e0f39546 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Sun, 5 Oct 2025 11:19:59 +0100 Subject: [PATCH] [AST] Canonicalize original type for ErrorType Make sure we canonicalize the original type for an ErrorType to ensure that diagnostic logic can coalesce ErrorTypes that have the same canonical type. --- include/swift/AST/Types.h | 5 +++-- lib/AST/Type.cpp | 9 ++++++++- test/Constraints/tuple_arguments.swift | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index c019ea5d60231..b67c7f908819e 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -1668,9 +1668,10 @@ class ErrorType final : public TypeBase { return props; } - // The Error type is always canonical. ErrorType(ASTContext &C, Type originalType) - : TypeBase(TypeKind::Error, &C, getProperties(originalType)) { + : TypeBase(TypeKind::Error, + (!originalType || originalType->isCanonical()) ? &C : nullptr, + getProperties(originalType)) { if (originalType) { Bits.ErrorType.HasOriginalType = true; *reinterpret_cast(this + 1) = originalType; diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 1cb25e0025c7a..a8e0ea87dd30b 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1765,7 +1765,6 @@ CanType TypeBase::computeCanonicalType() { #define ALWAYS_CANONICAL_TYPE(id, parent) case TypeKind::id: #define TYPE(id, parent) #include "swift/AST/TypeNodes.def" - case TypeKind::Error: case TypeKind::TypeVariable: case TypeKind::Placeholder: case TypeKind::BuiltinTuple: @@ -1779,6 +1778,14 @@ CanType TypeBase::computeCanonicalType() { #define TYPE(id, parent) #include "swift/AST/TypeNodes.def" + case TypeKind::Error: { + auto errTy = cast(this); + auto originalTy = errTy->getOriginalType(); + ASSERT(originalTy && "The bare ErrorType singleton is already canonical"); + Result = ErrorType::get(originalTy->getCanonicalType()).getPointer(); + break; + } + case TypeKind::Enum: case TypeKind::Struct: case TypeKind::Class: diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift index a1c4d635fd180..4a504c156203f 100644 --- a/test/Constraints/tuple_arguments.swift +++ b/test/Constraints/tuple_arguments.swift @@ -1728,7 +1728,7 @@ do { do { func f(_: Int...) {} let _ = [(1, 2, 3)].map(f) // expected-error {{no exact matches in call to instance method 'map'}} - // expected-note@-1 2{{found candidate with type '(((Int, Int, Int)) -> T) -> [T]'}} + // expected-note@-1 {{found candidate with type '(((Int, Int, Int)) -> T) -> [T]'}} } // rdar://problem/48443263 - cannot convert value of type '() -> Void' to expected argument type '(_) -> Void'