[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.
This commit is contained in:
Hamish Knight
2025-10-05 11:19:59 +01:00
parent d06d12632b
commit 7465928b45
3 changed files with 12 additions and 4 deletions

View File

@@ -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<Type *>(this + 1) = originalType;

View File

@@ -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<ErrorType>(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:

View File

@@ -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'