Skip to content

Commit d9c82b1

Browse files
committed
Sema: Clean up printing of generic signatures in missing witness diagnostics
Instead of stripping out requirements, let's pass the right PrintOptions.
1 parent a68c806 commit d9c82b1

File tree

5 files changed

+55
-28
lines changed

5 files changed

+55
-28
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ namespace swift {
105105
Type getType() const { return t; }
106106
};
107107

108+
struct WitnessType {
109+
Type t;
110+
111+
WitnessType(Type t) : t(t) {}
112+
113+
Type getType() { return t; }
114+
};
115+
108116
/// Describes the kind of diagnostic argument we're storing.
109117
///
110118
enum class DiagnosticArgumentKind {
@@ -117,6 +125,7 @@ namespace swift {
117125
Type,
118126
TypeRepr,
119127
FullyQualifiedType,
128+
WitnessType,
120129
DescriptivePatternKind,
121130
SelfAccessKind,
122131
ReferenceOwnership,
@@ -151,6 +160,7 @@ namespace swift {
151160
Type TypeVal;
152161
TypeRepr *TyR;
153162
FullyQualified<Type> FullyQualifiedTypeVal;
163+
WitnessType WitnessTypeVal;
154164
DescriptivePatternKind DescriptivePatternKindVal;
155165
SelfAccessKind SelfAccessKindVal;
156166
ReferenceOwnership ReferenceOwnershipVal;
@@ -214,6 +224,10 @@ namespace swift {
214224
: Kind(DiagnosticArgumentKind::FullyQualifiedType),
215225
FullyQualifiedTypeVal(FQT) {}
216226

227+
DiagnosticArgument(WitnessType WT)
228+
: Kind(DiagnosticArgumentKind::WitnessType),
229+
WitnessTypeVal(WT) {}
230+
217231
DiagnosticArgument(const TypeLoc &TL) {
218232
if (TypeRepr *tyR = TL.getTypeRepr()) {
219233
Kind = DiagnosticArgumentKind::TypeRepr;
@@ -329,6 +343,11 @@ namespace swift {
329343
return FullyQualifiedTypeVal;
330344
}
331345

346+
WitnessType getAsWitnessType() const {
347+
assert(Kind == DiagnosticArgumentKind::WitnessType);
348+
return WitnessTypeVal;
349+
}
350+
332351
DescriptivePatternKind getAsDescriptivePatternKind() const {
333352
assert(Kind == DiagnosticArgumentKind::DescriptivePatternKind);
334353
return DescriptivePatternKindVal;

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,19 +2883,19 @@ NOTE(no_witnesses,none,
28832883
"protocol requires "
28842884
"%select{initializer %1|function %1|property %1|subscript}0 with type %2"
28852885
"%select{|; add a stub for conformance}3",
2886-
(RequirementKind, const ValueDecl *, Type, bool))
2886+
(RequirementKind, const ValueDecl *, WitnessType, bool))
28872887
NOTE(missing_witnesses_general,none, "add stubs for conformance",
28882888
())
28892889
NOTE(ambiguous_witnesses,none,
28902890
"multiple matching "
28912891
"%select{initializers named %1|functions named %1|properties named %1|"
28922892
"subscript operators}0 with type %2",
2893-
(RequirementKind, const ValueDecl *, Type))
2893+
(RequirementKind, const ValueDecl *, WitnessType))
28942894
NOTE(ambiguous_witnesses_wrong_name,none,
28952895
"multiple matching "
28962896
"%select{initializers named %1|functions named %1|properties named %1|"
28972897
"subscript operators}0 with type %2",
2898-
(RequirementKind, const ValueDecl *, Type))
2898+
(RequirementKind, const ValueDecl *, WitnessType))
28992899
NOTE(no_witnesses_type,none,
29002900
"protocol requires nested type %0; add nested type %0 for conformance",
29012901
(const AssociatedTypeDecl *))
@@ -2982,7 +2982,7 @@ NOTE(protocol_witness_kind_conflict,none,
29822982
"candidate is not %select{an initializer|a function|a variable|"
29832983
"a subscript}0", (RequirementKind))
29842984
NOTE(protocol_witness_type_conflict,none,
2985-
"candidate has non-matching type %0%1", (Type, StringRef))
2985+
"candidate has non-matching type %0%1", (WitnessType, StringRef))
29862986
NOTE(protocol_witness_missing_requirement,none,
29872987
"candidate would match if %0 %select{conformed to|subclassed|"
29882988
"was the same type as|%error|%error}2 %1", (Type, Type, unsigned))

lib/AST/DiagnosticEngine.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,8 @@ static void formatDiagnosticArgument(StringRef Modifier,
755755
}
756756

757757
case DiagnosticArgumentKind::FullyQualifiedType:
758-
case DiagnosticArgumentKind::Type: {
758+
case DiagnosticArgumentKind::Type:
759+
case DiagnosticArgumentKind::WitnessType: {
759760
assert(Modifier.empty() && "Improper modifier for Type argument");
760761

761762
// Strip extraneous parentheses; they add no value.
@@ -777,8 +778,7 @@ static void formatDiagnosticArgument(StringRef Modifier,
777778
printOptions.PrintFunctionRepresentationAttrs =
778779
PrintOptions::FunctionRepresentationMode::Full;
779780
needsQualification = typeSpellingIsAmbiguous(type, Args, printOptions);
780-
} else {
781-
assert(Arg.getKind() == DiagnosticArgumentKind::FullyQualifiedType);
781+
} else if (Arg.getKind() == DiagnosticArgumentKind::FullyQualifiedType) {
782782
type = Arg.getAsFullyQualifiedType().getType()->getWithoutParens();
783783
if (type.isNull()) {
784784
// FIXME: We should never receive a nullptr here, but this is causing
@@ -791,6 +791,19 @@ static void formatDiagnosticArgument(StringRef Modifier,
791791
printOptions.PrintFunctionRepresentationAttrs =
792792
PrintOptions::FunctionRepresentationMode::Full;
793793
needsQualification = true;
794+
} else {
795+
assert(Arg.getKind() == DiagnosticArgumentKind::WitnessType);
796+
type = Arg.getAsWitnessType().getType()->getWithoutParens();
797+
if (type.isNull()) {
798+
// FIXME: We should never receive a nullptr here, but this is causing
799+
// crashes (rdar://75740683). Remove once ParenType never contains
800+
// nullptr as the underlying type.
801+
Out << "<null>";
802+
break;
803+
}
804+
printOptions.PrintGenericRequirements = false;
805+
printOptions.PrintInverseRequirements = false;
806+
needsQualification = typeSpellingIsAmbiguous(type, Args, printOptions);
794807
}
795808

796809
// If a type has an unresolved type, print it with syntax sugar removed for

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,24 +2493,18 @@ static Type getTypeForDisplay(ModuleDecl *module, ValueDecl *decl) {
24932493
if (!decl->getDeclContext()->isTypeContext())
24942494
return type;
24952495

2496-
GenericSignature sigWithoutReqts;
2497-
if (auto genericFn = type->getAs<GenericFunctionType>()) {
2498-
// For generic functions, build a new generic function... but strip off
2499-
// the requirements. They don't add value.
2500-
sigWithoutReqts
2501-
= GenericSignature::get(genericFn->getGenericParams(), {});
2502-
}
2503-
25042496
// For functions, strip off the 'Self' parameter clause.
2505-
if (isa<AbstractFunctionDecl>(decl))
2506-
type = type->castTo<AnyFunctionType>()->getResult();
2497+
if (isa<AbstractFunctionDecl>(decl)) {
2498+
if (auto genericFn = type->getAs<GenericFunctionType>()) {
2499+
auto sig = genericFn->getGenericSignature();
2500+
auto resultFn = genericFn->getResult()->castTo<FunctionType>();
2501+
return GenericFunctionType::get(sig,
2502+
resultFn->getParams(),
2503+
resultFn->getResult(),
2504+
resultFn->getExtInfo());
2505+
}
25072506

2508-
if (sigWithoutReqts) {
2509-
auto resultFn = type->castTo<AnyFunctionType>();
2510-
return GenericFunctionType::get(sigWithoutReqts,
2511-
resultFn->getParams(),
2512-
resultFn->getResult(),
2513-
resultFn->getExtInfo());
2507+
return type->castTo<FunctionType>()->getResult();
25142508
}
25152509

25162510
return type;
@@ -2800,18 +2794,18 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
28002794
break;
28012795

28022796
case MatchKind::TypeConflict: {
2797+
auto witnessType = getTypeForDisplay(module, match.Witness);
2798+
28032799
if (!isa<TypeDecl>(req) && !isa<EnumElementDecl>(match.Witness)) {
28042800
computeFixitsForOverriddenDeclaration(match.Witness, req, [&](bool){
28052801
return diags.diagnose(match.Witness,
28062802
diag::protocol_witness_type_conflict,
2807-
getTypeForDisplay(module, match.Witness),
2808-
withAssocTypes);
2803+
witnessType, withAssocTypes);
28092804
});
28102805
} else {
28112806
diags.diagnose(match.Witness,
28122807
diag::protocol_witness_type_conflict,
2813-
getTypeForDisplay(module, match.Witness),
2814-
withAssocTypes);
2808+
witnessType, withAssocTypes);
28152809
}
28162810
break;
28172811
}
@@ -4367,6 +4361,7 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
43674361
// Determine the type that the requirement is expected to have.
43684362
Type reqType = getRequirementTypeForDisplay(dc->getParentModule(),
43694363
conformance, requirement);
4364+
43704365
auto &diags = dc->getASTContext().Diags;
43714366
auto diagnosticMessage = diag::ambiguous_witnesses;
43724367
if (ignoringNames) {

test/Constraints/generic_protocol_witness.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class EqualConstraints : NeedsGenericMethods {
2525
func twoArgsOneVar<U>(x: U, y: U) {}
2626
func twoArgsTwoVars<V, U>(x: U, y: V) {}
2727
}
28-
func <T : Fungible>(x: EqualConstraints, y: T) {} // expected-note {{candidate has non-matching type '<T where T : Fungible> (EqualConstraints, T) -> ()'}}
28+
func <T : Fungible>(x: EqualConstraints, y: T) {} // expected-note {{candidate has non-matching type '<T> (EqualConstraints, T) -> ()'}}
2929

3030
class LooseConstraints : NeedsGenericMethods {
3131
func oneArgNoConstraints<U>(x: U) {}

0 commit comments

Comments
 (0)