From 7f2cb472ce3ef810648a54445cf9522a53e7f737 Mon Sep 17 00:00:00 2001 From: Nikhil0487 Date: Sun, 19 Jul 2020 16:40:25 +0530 Subject: [PATCH 1/5] [Diagnostic] Fix diagnostic when checking conformance for IUO of generic parameter Prints TypeRepr in diagnostic if possible to throw accurate diagnostic for IUO conformance checking Fixes [rdar://problem/64953106]. Fixes SR-13119 --- include/swift/AST/DiagnosticsSema.def | 2 +- lib/Sema/DerivedConformanceCodable.cpp | 22 +++++++++++++++++-- ...codable_excluded_optional_properties.swift | 4 ++-- ...codable_excluded_optional_properties.swift | 8 +++---- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 2368540dcc059..9fa095aa5852f 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -2795,7 +2795,7 @@ WARNING(differentiable_let_property_implicit_noderivative_fixit,none, NOTE(codable_extraneous_codingkey_case_here,none, "CodingKey case %0 does not match any stored properties", (Identifier)) NOTE(codable_non_conforming_property_here,none, - "cannot automatically synthesize %0 because %1 does not conform to %0", (Type, Type)) + "cannot automatically synthesize %0 because %1 does not conform to %0", (Type, TypeLoc)) NOTE(codable_non_decoded_property_here,none, "cannot automatically synthesize %0 because %1 does not have a matching CodingKey and does not have a default value", (Type, Identifier)) NOTE(codable_codingkeys_type_is_not_an_enum_here,none, diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index 843049dea1a4d..06b04b4d42a19 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -173,8 +173,13 @@ static bool validateCodingKeysEnum(DerivedConformance &derived, break; case DoesNotConform: + // for accurate diagnostic, we show TypeRepr if present + TypeLoc typeLoc = { + it->second->getTypeReprOrParentPatternTypeRepr(), + it->second->getType(), + }; it->second->diagnose(diag::codable_non_conforming_property_here, - derived.getProtocolType(), it->second->getType()); + derived.getProtocolType(), typeLoc); LLVM_FALLTHROUGH; case TypeNotValidated: @@ -353,8 +358,21 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) { } case DoesNotConform: + // for accurate diagnostic, we show TypeRepr if present for IUO + TypeLoc typeLoc = TypeLoc(); + if(varDecl->isImplicitlyUnwrappedOptional()){ + typeLoc = { + varDecl->getTypeReprOrParentPatternTypeRepr(), + varDecl->getType(), + }; + } else { + typeLoc = { + NULL, + varDecl->getType(), + }; + } varDecl->diagnose(diag::codable_non_conforming_property_here, - derived.getProtocolType(), varDecl->getType()); + derived.getProtocolType(),typeLoc); LLVM_FALLTHROUGH; case TypeNotValidated: diff --git a/test/decl/protocol/special/coding/class_codable_excluded_optional_properties.swift b/test/decl/protocol/special/coding/class_codable_excluded_optional_properties.swift index fe5c36bcc2acd..1b2d1ccb5f6a5 100644 --- a/test/decl/protocol/special/coding/class_codable_excluded_optional_properties.swift +++ b/test/decl/protocol/special/coding/class_codable_excluded_optional_properties.swift @@ -45,8 +45,8 @@ class ClassWithNonExcludedVarMembers : Codable { // expected-error {{type 'Class // AnyHashable does not conform to Codable. var p3: AnyHashable? // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable?' does not conform to 'Decodable'}} // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable?' does not conform to 'Encodable'}} - var p4: AnyHashable! // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable?' does not conform to 'Decodable'}} - // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable?' does not conform to 'Encodable'}} + var p4: AnyHashable! // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable!' does not conform to 'Decodable'}} + // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable!' does not conform to 'Encodable'}} } class ClassWithExcludedVarMembers : Codable { diff --git a/test/decl/protocol/special/coding/struct_codable_excluded_optional_properties.swift b/test/decl/protocol/special/coding/struct_codable_excluded_optional_properties.swift index 8d8d5939fee02..84e9b9c3022ec 100644 --- a/test/decl/protocol/special/coding/struct_codable_excluded_optional_properties.swift +++ b/test/decl/protocol/special/coding/struct_codable_excluded_optional_properties.swift @@ -12,8 +12,8 @@ struct StructWithNonExcludedLetMembers : Codable { // expected-error {{type 'Str // AnyHashable does not conform to Codable. let p3: AnyHashable? // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable?' does not conform to 'Decodable'}} // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable?' does not conform to 'Encodable'}} - let p4: AnyHashable! // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable?' does not conform to 'Decodable'}} - // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable?' does not conform to 'Encodable'}} + let p4: AnyHashable! // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable!' does not conform to 'Decodable'}} + // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable!' does not conform to 'Encodable'}} } struct StructWithExcludedLetMembers : Codable { // expected-error {{type 'StructWithExcludedLetMembers' does not conform to protocol 'Decodable'}} @@ -46,8 +46,8 @@ struct StructWithNonExcludedVarMembers : Codable { // expected-error {{type 'Str // AnyHashable does not conform to Codable. var p3: AnyHashable? // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable?' does not conform to 'Decodable'}} // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable?' does not conform to 'Encodable'}} - var p4: AnyHashable! // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable?' does not conform to 'Decodable'}} - // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable?' does not conform to 'Encodable'}} + var p4: AnyHashable! // expected-note {{cannot automatically synthesize 'Decodable' because 'AnyHashable!' does not conform to 'Decodable'}} + // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'AnyHashable!' does not conform to 'Encodable'}} } struct StructWithExcludedVarMembers : Codable { From b9fff8b2b69f0a9301bd5b85ce29c83169e004af Mon Sep 17 00:00:00 2001 From: Nikhil0487 Date: Sun, 19 Jul 2020 23:04:52 +0530 Subject: [PATCH 2/5] Nested name lookup tests update Name lookup will see the innermost name anyway and preferred over fully qualified name. Hence the test cases are also updated. --- lib/Sema/DerivedConformanceCodable.cpp | 18 +++++------------- .../class_codable_failure_diagnostics.swift | 4 ++-- .../struct_codable_failure_diagnostics.swift | 4 ++-- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index 06b04b4d42a19..d56b7d0416f1e 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -358,19 +358,11 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) { } case DoesNotConform: - // for accurate diagnostic, we show TypeRepr if present for IUO - TypeLoc typeLoc = TypeLoc(); - if(varDecl->isImplicitlyUnwrappedOptional()){ - typeLoc = { - varDecl->getTypeReprOrParentPatternTypeRepr(), - varDecl->getType(), - }; - } else { - typeLoc = { - NULL, - varDecl->getType(), - }; - } + // for accurate diagnostic, we show TypeRepr if present + TypeLoc typeLoc = { + it->second->getTypeReprOrParentPatternTypeRepr(), + it->second->getType(), + }; varDecl->diagnose(diag::codable_non_conforming_property_here, derived.getProtocolType(),typeLoc); LLVM_FALLTHROUGH; diff --git a/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift b/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift index ba35fb4e92e4a..e06724325099c 100644 --- a/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift +++ b/test/decl/protocol/special/coding/class_codable_failure_diagnostics.swift @@ -9,8 +9,8 @@ class C1 : Codable { var a: String = "" var b: Int = 0 var c: Nested = Nested() - // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'C1.Nested' does not conform to 'Decodable'}} - // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'C1.Nested' does not conform to 'Encodable'}} + // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'Nested' does not conform to 'Decodable'}} + // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'Nested' does not conform to 'Encodable'}} } // Codable class with non-enum CodingKeys. diff --git a/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift b/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift index fa26222b73602..4e644cb519faf 100644 --- a/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift +++ b/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift @@ -9,8 +9,8 @@ struct S1 : Codable { var a: String = "" var b: Int = 0 var c: Nested = Nested() - // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'S1.Nested' does not conform to 'Decodable'}} - // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'S1.Nested' does not conform to 'Encodable'}} + // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'Nested' does not conform to 'Decodable'}} + // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'sNested' does not conform to 'Encodable'}} } // Codable struct with non-enum CodingKeys. From 033e56a4cd7b8f474865795c1e5446dbf10dbb87 Mon Sep 17 00:00:00 2001 From: Nikhil0487 Date: Sun, 19 Jul 2020 23:13:31 +0530 Subject: [PATCH 3/5] Replaced a letter in test case that inadvertently got added --- .../special/coding/struct_codable_failure_diagnostics.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift b/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift index 4e644cb519faf..4928fb44ecc68 100644 --- a/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift +++ b/test/decl/protocol/special/coding/struct_codable_failure_diagnostics.swift @@ -10,7 +10,7 @@ struct S1 : Codable { var b: Int = 0 var c: Nested = Nested() // expected-note@-1 {{cannot automatically synthesize 'Decodable' because 'Nested' does not conform to 'Decodable'}} - // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'sNested' does not conform to 'Encodable'}} + // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'Nested' does not conform to 'Encodable'}} } // Codable struct with non-enum CodingKeys. From 4585153ea5df3681e3b8e88a7a4d69b0467bb814 Mon Sep 17 00:00:00 2001 From: Nikhil0487 Date: Mon, 20 Jul 2020 10:35:47 +0530 Subject: [PATCH 4/5] Code format, corrections and better comments This commit includes better comments for easy understanding, formatted the bug fix code with clang-format and fixes wrong variables inadvertently introduced. --- lib/Sema/DerivedConformanceCodable.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index d56b7d0416f1e..a76fd5e3be6fe 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -172,8 +172,12 @@ static bool validateCodingKeysEnum(DerivedConformance &derived, properties.erase(it); break; - case DoesNotConform: - // for accurate diagnostic, we show TypeRepr if present + case DoesNotConform: { + // We use a TypeLoc here so diagnostics can show the type + // as written by the user in source if possible. This is useful + // when the user has written an IUO type for example, since + // diagnostics would show the type as 'T?' instead of 'T!' if + // we use a Type instead. TypeLoc typeLoc = { it->second->getTypeReprOrParentPatternTypeRepr(), it->second->getType(), @@ -181,6 +185,7 @@ static bool validateCodingKeysEnum(DerivedConformance &derived, it->second->diagnose(diag::codable_non_conforming_property_here, derived.getProtocolType(), typeLoc); LLVM_FALLTHROUGH; + } case TypeNotValidated: // We don't produce a diagnostic for a type which failed to validate. @@ -357,15 +362,20 @@ static EnumDecl *synthesizeCodingKeysEnum(DerivedConformance &derived) { break; } - case DoesNotConform: - // for accurate diagnostic, we show TypeRepr if present + case DoesNotConform: { + // We use a TypeLoc here so diagnostics can show the type + // as written by the user in source if possible. This is useful + // when the user has written an IUO type for example, since + // diagnostics would show the type as 'T?' instead of 'T!' if + // we use a Type instead. TypeLoc typeLoc = { - it->second->getTypeReprOrParentPatternTypeRepr(), - it->second->getType(), + varDecl->getTypeReprOrParentPatternTypeRepr(), + varDecl->getType(), }; varDecl->diagnose(diag::codable_non_conforming_property_here, - derived.getProtocolType(),typeLoc); + derived.getProtocolType(), typeLoc); LLVM_FALLTHROUGH; + } case TypeNotValidated: // We don't produce a diagnostic for a type which failed to validate. From 41b609942725d3cd082bf888236fc3ba04a30d7a Mon Sep 17 00:00:00 2001 From: Nikhil0487 Date: Tue, 21 Jul 2020 08:36:12 +0530 Subject: [PATCH 5/5] [Test] Update type in struct codable test This commit changes diagnostic type from error type to Int. Although this diagnostic updated is incorrect, this will be resolved when 32371 gets pulled. --- test/decl/protocol/special/coding/struct_codable_simple.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/decl/protocol/special/coding/struct_codable_simple.swift b/test/decl/protocol/special/coding/struct_codable_simple.swift index 05b04f37f8374..05b6423f98cd7 100644 --- a/test/decl/protocol/special/coding/struct_codable_simple.swift +++ b/test/decl/protocol/special/coding/struct_codable_simple.swift @@ -34,8 +34,8 @@ let _ = SimpleStruct.CodingKeys.self // expected-error {{'CodingKeys' is inacces struct SR_12248_1: Codable { // expected-error {{type 'SR_12248_1' does not conform to protocol 'Encodable'}} var x: Int // expected-note {{'x' previously declared here}} var x: Int // expected-error {{invalid redeclaration of 'x'}} - // expected-note@-1 {{cannot automatically synthesize 'Encodable' because '<>' does not conform to 'Encodable'}} - // expected-note@-2 {{cannot automatically synthesize 'Encodable' because '<>' does not conform to 'Encodable'}} + // expected-note@-1 {{cannot automatically synthesize 'Encodable' because 'Int' does not conform to 'Encodable'}} + // expected-note@-2 {{cannot automatically synthesize 'Encodable' because 'Int' does not conform to 'Encodable'}} } struct SR_12248_2: Decodable {