Skip to content

Commit 876fe2f

Browse files
committed
Sema: Redeclaration checking should not mark implicit decls as invalid
If both the 'other' and 'current' declarations are implicit, we don't emit a diagnostic unless they are both derived from property wrappers or lazy property storage. However, we would still call setInvalid() unconditionally, which splats an ErrorType into the interface type, which would crash in the AST verifier if no other diagnostic was emitted. Fixes <rdar://problem/67259506>.
1 parent 18af945 commit 876fe2f

File tree

2 files changed

+59
-26
lines changed

2 files changed

+59
-26
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -754,44 +754,48 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current) const {
754754
declToDiagnose->diagnose(diag::invalid_redecl_implicit,
755755
current->getDescriptiveKind(),
756756
isProtocolRequirement, other->getName());
757-
}
758757

759-
// Emit a specialized note if the one of the declarations is
760-
// the backing storage property ('_foo') or projected value
761-
// property ('$foo') for a wrapped property. The backing or
762-
// projected var has the same source location as the wrapped
763-
// property we diagnosed above, so we don't need to extract
764-
// the original property.
765-
const VarDecl *varToDiagnose = nullptr;
766-
auto kind = PropertyWrapperSynthesizedPropertyKind::Backing;
767-
if (auto currentVD = dyn_cast<VarDecl>(current)) {
768-
if (auto currentKind =
769-
currentVD->getPropertyWrapperSynthesizedPropertyKind()) {
770-
varToDiagnose = currentVD;
771-
kind = *currentKind;
758+
// Emit a specialized note if the one of the declarations is
759+
// the backing storage property ('_foo') or projected value
760+
// property ('$foo') for a wrapped property. The backing or
761+
// projected var has the same source location as the wrapped
762+
// property we diagnosed above, so we don't need to extract
763+
// the original property.
764+
const VarDecl *varToDiagnose = nullptr;
765+
auto kind = PropertyWrapperSynthesizedPropertyKind::Backing;
766+
if (auto currentVD = dyn_cast<VarDecl>(current)) {
767+
if (auto currentKind =
768+
currentVD->getPropertyWrapperSynthesizedPropertyKind()) {
769+
varToDiagnose = currentVD;
770+
kind = *currentKind;
771+
}
772772
}
773-
}
774-
if (auto otherVD = dyn_cast<VarDecl>(other)) {
775-
if (auto otherKind =
776-
otherVD->getPropertyWrapperSynthesizedPropertyKind()) {
777-
varToDiagnose = otherVD;
778-
kind = *otherKind;
773+
if (auto otherVD = dyn_cast<VarDecl>(other)) {
774+
if (auto otherKind =
775+
otherVD->getPropertyWrapperSynthesizedPropertyKind()) {
776+
varToDiagnose = otherVD;
777+
kind = *otherKind;
778+
}
779+
}
780+
781+
if (varToDiagnose) {
782+
assert(declToDiagnose);
783+
varToDiagnose->diagnose(
784+
diag::invalid_redecl_implicit_wrapper, varToDiagnose->getName(),
785+
kind == PropertyWrapperSynthesizedPropertyKind::Backing);
779786
}
780-
}
781787

782-
if (varToDiagnose) {
783-
varToDiagnose->diagnose(
784-
diag::invalid_redecl_implicit_wrapper, varToDiagnose->getName(),
785-
kind == PropertyWrapperSynthesizedPropertyKind::Backing);
788+
current->setInvalid();
786789
}
787790
} else {
788791
ctx.Diags.diagnoseWithNotes(
789792
current->diagnose(diag::invalid_redecl,
790793
current->getName()), [&]() {
791794
other->diagnose(diag::invalid_redecl_prev, other->getName());
792795
});
796+
797+
current->setInvalid();
793798
}
794-
current->setInvalid();
795799
}
796800

797801
// Make sure we don't do this checking again for the same decl. We also
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-swift-frontend -emit-ir %s
2+
3+
public func foo<T : P & Q>(_: T, _: S<T>.A) {}
4+
5+
public protocol P {
6+
associatedtype A
7+
8+
func foo() -> A
9+
}
10+
11+
public protocol Q {
12+
associatedtype A
13+
14+
func bar() -> A
15+
}
16+
17+
public struct S<T> {}
18+
19+
extension S : P where T : P {
20+
public func foo() -> Int {
21+
return 0
22+
}
23+
}
24+
25+
extension S : Q where T : Q {
26+
public func bar() -> Int {
27+
return 0
28+
}
29+
}

0 commit comments

Comments
 (0)