@@ -711,7 +711,69 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const {
711
711
current->diagnose (diag::invalid_redecl_init,
712
712
current->getName (),
713
713
otherInit->isMemberwiseInitializer ());
714
- } else if (!current->isImplicit () && !other->isImplicit ()) {
714
+ } else if (current->isImplicit () || other->isImplicit ()) {
715
+ // If both declarations are implicit, we diagnose the nearest
716
+ // non-implicit DC because it is likely that we do not have a
717
+ // valid source location for the declaration and we want to
718
+ // avoid emitting it at an unknown location.
719
+ //
720
+ // Otherwise, if 'current' is implicit, then we diagnose 'other'
721
+ // since 'other' is a redeclaration of 'current'. Similarly, if
722
+ // 'other' is implicit, we diagnose 'current'.
723
+ const auto *declToDiagnose = currentDC->getAsDecl ();
724
+ if (current->isImplicit () && other->isImplicit ()) {
725
+ // Get the nearest non-implicit decl context
726
+ while (declToDiagnose && declToDiagnose->isImplicit () &&
727
+ declToDiagnose->getDeclContext ()) {
728
+ declToDiagnose = declToDiagnose->getDeclContext ()->getAsDecl ();
729
+ }
730
+ } else {
731
+ declToDiagnose = current->isImplicit () ? other : current;
732
+ }
733
+
734
+ // Figure out if the the declaration we've redeclared is a synthesized
735
+ // witness for a protocol requirement.
736
+ bool isProtocolRequirement = false ;
737
+ if (auto VD = dyn_cast<ValueDecl>(current->isImplicit () ? current
738
+ : other)) {
739
+ isProtocolRequirement = llvm::any_of (
740
+ VD->getSatisfiedProtocolRequirements (), [&](ValueDecl *req) {
741
+ return req->getName () == VD->getName ();
742
+ });
743
+ }
744
+ declToDiagnose->diagnose (diag::invalid_redecl_implicit,
745
+ current->getDescriptiveKind (),
746
+ isProtocolRequirement, other->getName ());
747
+
748
+ // Emit a specialized note if the one of the declarations is
749
+ // the backing storage property ('_foo') or projected value
750
+ // property ('$foo') for a wrapped property. The backing or
751
+ // storage var has the same source location as the wrapped
752
+ // property we diagnosed above, so we don't need to extract
753
+ // the original property.
754
+ const VarDecl *varToDiagnose = nullptr ;
755
+ auto kind = PropertyWrapperSynthesizedPropertyKind::Backing;
756
+ if (auto currentVD = dyn_cast<VarDecl>(current)) {
757
+ if (auto currentKind =
758
+ currentVD->getPropertyWrapperSynthesizedPropertyKind ()) {
759
+ varToDiagnose = currentVD;
760
+ kind = *currentKind;
761
+ }
762
+ }
763
+ if (auto otherVD = dyn_cast<VarDecl>(other)) {
764
+ if (auto otherKind =
765
+ otherVD->getPropertyWrapperSynthesizedPropertyKind ()) {
766
+ varToDiagnose = otherVD;
767
+ kind = *otherKind;
768
+ }
769
+ }
770
+
771
+ if (varToDiagnose) {
772
+ varToDiagnose->diagnose (
773
+ diag::invalid_redecl_implicit_wrapper, varToDiagnose->getName (),
774
+ kind == PropertyWrapperSynthesizedPropertyKind::Backing);
775
+ }
776
+ } else {
715
777
ctx.Diags .diagnoseWithNotes (
716
778
current->diagnose (diag::invalid_redecl,
717
779
current->getName ()), [&]() {
0 commit comments