Skip to content

Commit 7856bba

Browse files
committed
sema: require witness for _const decls to be also _const
1 parent 03c76bd commit 7856bba

File tree

6 files changed

+41
-1
lines changed

6 files changed

+41
-1
lines changed

include/swift/AST/Decl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4583,6 +4583,7 @@ class AbstractStorageDecl : public ValueDecl {
45834583
void setStatic(bool IsStatic) {
45844584
Bits.AbstractStorageDecl.IsStatic = IsStatic;
45854585
}
4586+
bool isCompileTimeConst() const;
45864587

45874588
/// \returns the way 'static'/'class' should be spelled for this declaration.
45884589
StaticSpellingKind getCorrectStaticSpelling() const;

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2323,6 +2323,9 @@ WARNING(warn_protocol_witness_optionality,none,
23232323
NOTE(protocol_witness_static_conflict,none,
23242324
"candidate operates on %select{a type|an instance}0, not "
23252325
"%select{an instance|a type}0 as required", (bool))
2326+
NOTE(protocol_witness_const_conflict,none,
2327+
"candidate operates as %select{const|non-const}0, not "
2328+
"%select{non-const|const}0 as required", (bool))
23262329
NOTE(protocol_witness_prefix_postfix_conflict,none,
23272330
"candidate is %select{|prefix, |postfix, }1not "
23282331
"%select{prefix|postfix}0 as required", (bool, unsigned))

lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,10 @@ void AbstractFunctionDecl::setSingleExpressionBody(Expr *NewBody) {
763763
getBody()->setLastElement(NewBody);
764764
}
765765

766+
bool AbstractStorageDecl::isCompileTimeConst() const {
767+
return getAttrs().hasAttribute<CompileTimeConstAttr>();
768+
}
769+
766770
bool AbstractStorageDecl::isTransparent() const {
767771
return getAttrs().hasAttribute<TransparentAttr>();
768772
}

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,11 @@ swift::matchWitness(
627627
if (reqASD->isStatic() != witnessASD->isStatic())
628628
return RequirementMatch(witness, MatchKind::StaticNonStaticConflict);
629629

630+
// Check that the compile-time constness matches.
631+
if (reqASD->isCompileTimeConst() && !witnessASD->isCompileTimeConst()) {
632+
return RequirementMatch(witness, MatchKind::CompileTimeConstConflict);
633+
}
634+
630635
// If the requirement is settable and the witness is not, reject it.
631636
if (reqASD->isSettable(req->getDeclContext()) &&
632637
!witnessASD->isSettable(witness->getDeclContext()))
@@ -2566,7 +2571,16 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
25662571
diag);
25672572
break;
25682573
}
2569-
2574+
case MatchKind::CompileTimeConstConflict: {
2575+
auto witness = match.Witness;
2576+
auto missing = !witness->getAttrs().getAttribute<CompileTimeConstAttr>();
2577+
auto diag = diags.diagnose(witness, diag::protocol_witness_const_conflict,
2578+
missing);
2579+
if (missing) {
2580+
diag.fixItInsert(witness->getAttributeInsertionLoc(true), "_const");
2581+
}
2582+
break;
2583+
}
25702584
case MatchKind::StaticNonStaticConflict: {
25712585
auto witness = match.Witness;
25722586
auto diag = diags.diagnose(witness, diag::protocol_witness_static_conflict,

lib/Sema/TypeCheckProtocol.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ enum class MatchKind : uint8_t {
282282
/// The witness did not match because it is an enum case with
283283
/// associated values.
284284
EnumCaseWithAssociatedValues,
285+
286+
/// The witness did not match due to _const/non-_const differences.
287+
CompileTimeConstConflict,
285288
};
286289

287290
/// Describes the kind of optional adjustment performed when
@@ -507,6 +510,7 @@ struct RequirementMatch {
507510
case MatchKind::TypeConflict:
508511
case MatchKind::MissingRequirement:
509512
case MatchKind::StaticNonStaticConflict:
513+
case MatchKind::CompileTimeConstConflict:
510514
case MatchKind::SettableConflict:
511515
case MatchKind::PrefixNonPrefixConflict:
512516
case MatchKind::PostfixNonPostfixConflict:
@@ -542,6 +546,7 @@ struct RequirementMatch {
542546
case MatchKind::TypeConflict:
543547
case MatchKind::MissingRequirement:
544548
case MatchKind::StaticNonStaticConflict:
549+
case MatchKind::CompileTimeConstConflict:
545550
case MatchKind::SettableConflict:
546551
case MatchKind::PrefixNonPrefixConflict:
547552
case MatchKind::PostfixNonPostfixConflict:
@@ -576,6 +581,7 @@ struct RequirementMatch {
576581
case MatchKind::Circularity:
577582
case MatchKind::KindConflict:
578583
case MatchKind::StaticNonStaticConflict:
584+
case MatchKind::CompileTimeConstConflict:
579585
case MatchKind::SettableConflict:
580586
case MatchKind::PrefixNonPrefixConflict:
581587
case MatchKind::PostfixNonPostfixConflict:

test/Sema/const_pass_as_arguments.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,15 @@ func main_member(_ u: Utils, _ i: Int, _ d: Double, _ s: String) {
3131
u.takeStringConst("\(d)") // expected-error {{expect a compile-time constant literal}}
3232
u.takeStringConst(s) // expected-error {{expect a compile-time constant literal}}
3333
}
34+
35+
protocol ConstFan {
36+
static _const var v: String { get } // expected-note {{protocol requires property 'v' with type 'String'; do you want to add a stub?}}
37+
}
38+
39+
class ConstFanClass1: ConstFan { // expected-error {{type 'ConstFanClass1' does not conform to protocol 'ConstFan'}}
40+
static var v: String = "" // expected-note {{candidate operates as non-const, not const as required}}
41+
}
42+
43+
class ConstFanClassCorrect: ConstFan {
44+
static _const var v: String = ""
45+
}

0 commit comments

Comments
 (0)