Skip to content

Commit 78ad65f

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-rebranch
2 parents a6f4a46 + 6d90558 commit 78ad65f

File tree

2 files changed

+99
-28
lines changed

2 files changed

+99
-28
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 63 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2089,53 +2089,88 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
20892089
break;
20902090
}
20912091

2092-
case MatchKind::StaticNonStaticConflict:
2093-
// FIXME: Could emit a Fix-It here.
2094-
diags.diagnose(match.Witness, diag::protocol_witness_static_conflict,
2095-
!req->isInstanceMember());
2092+
case MatchKind::StaticNonStaticConflict: {
2093+
auto witness = match.Witness;
2094+
auto diag = diags.diagnose(witness, diag::protocol_witness_static_conflict,
2095+
!req->isInstanceMember());
2096+
if (req->isInstanceMember()) {
2097+
SourceLoc loc;
2098+
if (auto FD = dyn_cast<FuncDecl>(witness)) {
2099+
loc = FD->getStaticLoc();
2100+
} else if (auto VD = dyn_cast<VarDecl>(witness)) {
2101+
loc = VD->getParentPatternBinding()->getStaticLoc();
2102+
} else if (auto SD = dyn_cast<SubscriptDecl>(witness)) {
2103+
loc = SD->getStaticLoc();
2104+
} else {
2105+
llvm_unreachable("Unexpected witness");
2106+
}
2107+
diag.fixItRemove(loc);
2108+
} else {
2109+
diag.fixItInsert(witness->getAttributeInsertionLoc(true), "static ");
2110+
}
20962111
break;
2097-
2098-
case MatchKind::SettableConflict:
2099-
diags.diagnose(match.Witness, diag::protocol_witness_settable_conflict);
2112+
}
2113+
2114+
case MatchKind::SettableConflict: {
2115+
auto witness = match.Witness;
2116+
auto diag =
2117+
diags.diagnose(witness, diag::protocol_witness_settable_conflict);
2118+
if (auto VD = dyn_cast<VarDecl>(witness)) {
2119+
if (VD->hasStorage()) {
2120+
auto PBD = VD->getParentPatternBinding();
2121+
diag.fixItReplace(PBD->getStartLoc(), getTokenText(tok::kw_var));
2122+
}
2123+
}
21002124
break;
2125+
}
21012126

2102-
case MatchKind::PrefixNonPrefixConflict:
2103-
// FIXME: Could emit a Fix-It here.
2104-
diags.diagnose(match.Witness,
2105-
diag::protocol_witness_prefix_postfix_conflict, false,
2106-
match.Witness->getAttrs().hasAttribute<PostfixAttr>() ? 2
2107-
: 0);
2127+
case MatchKind::PrefixNonPrefixConflict: {
2128+
auto witness = match.Witness;
2129+
auto diag = diags.diagnose(
2130+
witness, diag::protocol_witness_prefix_postfix_conflict, false,
2131+
witness->getAttrs().hasAttribute<PostfixAttr>() ? 2 : 0);
2132+
// We already emit a fix-it when we're missing the attribute, so only
2133+
// emit a fix-it if the attribute is there, but is not correct.
2134+
if (auto attr = witness->getAttrs().getAttribute<PostfixAttr>()) {
2135+
diag.fixItReplace(attr->getLocation(), "prefix");
2136+
}
21082137
break;
2138+
}
21092139

2110-
case MatchKind::PostfixNonPostfixConflict:
2111-
// FIXME: Could emit a Fix-It here.
2112-
diags.diagnose(match.Witness,
2113-
diag::protocol_witness_prefix_postfix_conflict, true,
2114-
match.Witness->getAttrs().hasAttribute<PrefixAttr>() ? 1
2115-
: 0);
2140+
case MatchKind::PostfixNonPostfixConflict: {
2141+
auto witness = match.Witness;
2142+
auto diag = diags.diagnose(
2143+
witness, diag::protocol_witness_prefix_postfix_conflict, true,
2144+
witness->getAttrs().hasAttribute<PrefixAttr>() ? 1 : 0);
2145+
// We already emit a fix-it when we're missing the attribute, so only
2146+
// emit a fix-it if the attribute is there, but is not correct.
2147+
if (auto attr = witness->getAttrs().getAttribute<PrefixAttr>()) {
2148+
diag.fixItReplace(attr->getLocation(), "postfix");
2149+
}
21162150
break;
2151+
}
21172152
case MatchKind::MutatingConflict:
2118-
// FIXME: Could emit a Fix-It here.
21192153
diags.diagnose(match.Witness,
21202154
diag::protocol_witness_mutation_modifier_conflict,
21212155
SelfAccessKind::Mutating);
21222156
break;
21232157
case MatchKind::NonMutatingConflict:
2124-
// FIXME: Could emit a Fix-It here.
2125-
diags.diagnose(match.Witness,
2126-
diag::protocol_witness_mutation_modifier_conflict,
2127-
SelfAccessKind::NonMutating);
2158+
// Don't bother about this, because a non-mutating witness can satisfy
2159+
// a mutating requirement.
21282160
break;
21292161
case MatchKind::ConsumingConflict:
2130-
// FIXME: Could emit a Fix-It here.
21312162
diags.diagnose(match.Witness,
21322163
diag::protocol_witness_mutation_modifier_conflict,
21332164
SelfAccessKind::Consuming);
21342165
break;
2135-
case MatchKind::RethrowsConflict:
2136-
// FIXME: Could emit a Fix-It here.
2137-
diags.diagnose(match.Witness, diag::protocol_witness_rethrows_conflict);
2166+
case MatchKind::RethrowsConflict: {
2167+
auto witness = match.Witness;
2168+
auto diag =
2169+
diags.diagnose(witness, diag::protocol_witness_rethrows_conflict);
2170+
auto FD = cast<FuncDecl>(witness);
2171+
diag.fixItReplace(FD->getThrowsLoc(), getTokenText(tok::kw_rethrows));
21382172
break;
2173+
}
21392174
case MatchKind::NonObjC:
21402175
diags.diagnose(match.Witness, diag::protocol_witness_not_objc);
21412176
break;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
prefix operator ^^^
4+
postfix operator ^^^^
5+
6+
protocol Foo {
7+
var bar1: Int { get set } // expected-note {{protocol requires property 'bar1' with type 'Int'; do you want to add a stub?}}
8+
static var bar2: Int { get set } // expected-note {{protocol requires property 'bar2' with type 'Int'; do you want to add a stub?}}
9+
var bar3: Int { get set } // expected-note {{protocol requires property 'bar3' with type 'Int'; do you want to add a stub?}}
10+
static prefix func ^^^(value: Self) -> Int // expected-note {{protocol requires function '^^^' with type '(ConformsToFoo) -> Int'; do you want to add a stub?}}
11+
static postfix func ^^^^(value: Self) -> Int // expected-note {{protocol requires function '^^^^' with type '(ConformsToFoo) -> Int'; do you want to add a stub?}}
12+
func bar4(closure: () throws -> Int) rethrows // expected-note {{protocol requires function 'bar4(closure:)' with type '(() throws -> Int) throws -> ()'; do you want to add a stub?}}
13+
var bar5: Int { get set } // expected-note {{protocol requires property 'bar5' with type 'Int'; do you want to add a stub?}}
14+
static subscript(_ pos: Int) -> Int { get } // expected-note {{protocol requires subscript with type '(Int) -> Int'; do you want to add a stub?}}
15+
}
16+
17+
struct ConformsToFoo: Foo { // expected-error {{type 'ConformsToFoo' does not conform to protocol 'Foo'}}
18+
let bar1: Int // expected-note {{candidate is not settable, but protocol requires it}}{{3-6=var}}
19+
var bar2: Int // expected-note {{candidate operates on an instance, not a type as required}}{{3-3=static }}
20+
static var bar3: Int = 1 // expected-note {{candidate operates on a type, not an instance as required}}{{3-10=}}
21+
static postfix func ^^^(value: ConformsToFoo) -> Int { return 0 } // expected-error {{operator implementation without matching operator declaration}}
22+
// expected-note@-1 {{candidate is postfix, not prefix as required}}{{10-17=prefix}}
23+
static prefix func ^^^^(value: ConformsToFoo) -> Int { return 0 } // expected-error {{operator implementation without matching operator declaration}}
24+
// expected-note@-1 {{candidate is prefix, not postfix as required}}{{10-16=postfix}}
25+
func bar4(closure: () throws -> Int) throws {} // expected-note {{candidate is not 'rethrows', but protocol requires it}}{{40-46=rethrows}}
26+
var bar5: Int { return 0 } // expected-note {{candidate is not settable, but protocol requires it}}{{none}}
27+
subscript(_ pos: Int) -> Int { return 0 } // expected-note {{candidate operates on an instance, not a type as required}}{{3-3=static }}
28+
}
29+
30+
protocol Foo1 {
31+
subscript(value: Bool) -> Bool { get set } // expected-note {{protocol requires subscript with type '(Bool) -> Bool'; do you want to add a stub?}}
32+
}
33+
34+
struct ConformsToFoo1: Foo1 { // expected-error {{type 'ConformsToFoo1' does not conform to protocol 'Foo1'}}
35+
subscript(value: Bool) -> Bool { return false } // expected-note {{candidate is not settable, but protocol requires it}}{{none}}
36+
}

0 commit comments

Comments
 (0)