@@ -484,8 +484,20 @@ swift::matchWitness(
484484 assert (!req->isInvalid () && " Cannot have an invalid requirement here" );
485485
486486 // / Make sure the witness is of the same kind as the requirement.
487- if (req->getKind () != witness->getKind ())
488- return RequirementMatch (witness, MatchKind::KindConflict);
487+ if (req->getKind () != witness->getKind ()) {
488+ // An enum case can witness:
489+ // 1. A static get-only property requirement, as long as the property's
490+ // type is `Self` or it matches the type of the enum explicitly.
491+ // 2. A static function requirement, if the enum case has a payload
492+ // and the payload types and labels match the function and the
493+ // function returns `Self` or the type of the enum.
494+ //
495+ // If there are any discrepencies, we'll diagnose it later. For now,
496+ // let's assume the match is valid.
497+ if (!((isa<VarDecl>(req) || isa<FuncDecl>(req)) &&
498+ isa<EnumElementDecl>(witness)))
499+ return RequirementMatch (witness, MatchKind::KindConflict);
500+ }
489501
490502 // If we're currently validating the witness, bail out.
491503 if (witness->isRecursiveValidation ())
@@ -502,7 +514,8 @@ swift::matchWitness(
502514 // Perform basic matching of the requirement and witness.
503515 bool decomposeFunctionType = false ;
504516 bool ignoreReturnType = false ;
505- if (auto funcReq = dyn_cast<FuncDecl>(req)) {
517+ if (isa<FuncDecl>(req) && isa<FuncDecl>(witness)) {
518+ auto funcReq = cast<FuncDecl>(req);
506519 auto funcWitness = cast<FuncDecl>(witness);
507520
508521 // Either both must be 'static' or neither.
@@ -564,6 +577,18 @@ swift::matchWitness(
564577 } else if (isa<ConstructorDecl>(witness)) {
565578 decomposeFunctionType = true ;
566579 ignoreReturnType = true ;
580+ } else if (isa<EnumElementDecl>(witness)) {
581+ auto enumCase = cast<EnumElementDecl>(witness);
582+ if (enumCase->hasAssociatedValues () && isa<VarDecl>(req))
583+ return RequirementMatch (witness, MatchKind::EnumCaseWithAssociatedValues);
584+ auto isValid = isa<VarDecl>(req) || isa<FuncDecl>(req);
585+ if (!isValid)
586+ return RequirementMatch (witness, MatchKind::KindConflict);
587+ if (!cast<ValueDecl>(req)->isStatic ())
588+ return RequirementMatch (witness, MatchKind::StaticNonStaticConflict);
589+ if (isa<VarDecl>(req) &&
590+ cast<VarDecl>(req)->getParsedAccessor (AccessorKind::Set))
591+ return RequirementMatch (witness, MatchKind::SettableConflict);
567592 }
568593
569594 // If the requirement is @objc, the witness must not be marked with @nonobjc.
@@ -2182,7 +2207,8 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
21822207 if (match.Kind != MatchKind::RenamedMatch &&
21832208 !match.Witness ->getAttrs ().hasAttribute <ImplementsAttr>() &&
21842209 match.Witness ->getFullName () &&
2185- req->getFullName () != match.Witness ->getFullName ())
2210+ req->getFullName () != match.Witness ->getFullName () &&
2211+ !isa<EnumElementDecl>(match.Witness ))
21862212 return ;
21872213
21882214 // Form a string describing the associated type deductions.
@@ -2234,7 +2260,7 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
22342260 break ;
22352261
22362262 case MatchKind::TypeConflict: {
2237- if (!isa<TypeDecl>(req)) {
2263+ if (!isa<TypeDecl>(req) && !isa<EnumElementDecl>(match. Witness ) ) {
22382264 computeFixitsForOverridenDeclaration (match.Witness , req, [&](bool ){
22392265 return diags.diagnose (match.Witness ,
22402266 diag::protocol_witness_type_conflict,
@@ -2278,6 +2304,8 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
22782304 auto witness = match.Witness ;
22792305 auto diag = diags.diagnose (witness, diag::protocol_witness_static_conflict,
22802306 !req->isInstanceMember ());
2307+ if (isa<EnumElementDecl>(witness))
2308+ break ;
22812309 if (req->isInstanceMember ()) {
22822310 SourceLoc loc;
22832311 if (auto FD = dyn_cast<FuncDecl>(witness)) {
@@ -2403,6 +2431,9 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
24032431 }
24042432 break ;
24052433 }
2434+ case MatchKind::EnumCaseWithAssociatedValues:
2435+ diags.diagnose (match.Witness , diag::protocol_witness_enum_case_payload);
2436+ break ;
24062437 }
24072438}
24082439
@@ -3325,12 +3356,10 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
33253356 auto &diags = proto->getASTContext ().Diags ;
33263357 {
33273358 SourceLoc diagLoc = getLocForDiagnosingWitness (conformance,witness);
3328- auto diag = diags.diagnose (diagLoc,
3329- diag::witness_argument_name_mismatch,
3330- isa<ConstructorDecl>(witness),
3331- witness->getFullName (),
3332- proto->getDeclaredType (),
3333- requirement->getFullName ());
3359+ auto diag = diags.diagnose (
3360+ diagLoc, diag::witness_argument_name_mismatch,
3361+ witness->getDescriptiveKind (), witness->getFullName (),
3362+ proto->getDeclaredType (), requirement->getFullName ());
33343363 if (diagLoc == witness->getLoc ()) {
33353364 fixDeclarationName (diag, witness, requirement->getFullName ());
33363365 } else {
0 commit comments