Skip to content

Commit 7baf6a2

Browse files
committed
Sema: Move a few more things from validateDecl() to typeCheckDecl()
1 parent 6bfe518 commit 7baf6a2

File tree

1 file changed

+47
-41
lines changed

1 file changed

+47
-41
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,8 +1240,21 @@ IsFinalRequest::evaluate(Evaluator &evaluator, ValueDecl *decl) const {
12401240

12411241
llvm::Expected<bool>
12421242
IsStaticRequest::evaluate(Evaluator &evaluator, FuncDecl *decl) const {
1243-
return (decl->getStaticLoc().isValid() ||
1244-
decl->getStaticSpelling() != StaticSpellingKind::None);
1243+
bool result = (decl->getStaticLoc().isValid() ||
1244+
decl->getStaticSpelling() != StaticSpellingKind::None);
1245+
auto *dc = decl->getDeclContext();
1246+
if (!result &&
1247+
decl->isOperator() &&
1248+
dc->isTypeContext()) {
1249+
auto operatorName = decl->getFullName().getBaseIdentifier();
1250+
decl->diagnose(diag::nonstatic_operator_in_type,
1251+
operatorName, dc->getDeclaredInterfaceType())
1252+
.fixItInsert(decl->getAttributeInsertionLoc(/*forModifier=*/true),
1253+
"static ");
1254+
result = true;
1255+
}
1256+
1257+
return result;
12451258
}
12461259

12471260
llvm::Expected<bool>
@@ -3070,7 +3083,9 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
30703083
}
30713084

30723085
void visitFuncDecl(FuncDecl *FD) {
3073-
(void)FD->getInterfaceType();
3086+
// Force these requests in case they emit diagnostics.
3087+
(void) FD->getInterfaceType();
3088+
(void) FD->getOperatorDecl();
30743089

30753090
if (!FD->isInvalid()) {
30763091
checkGenericParams(FD->getGenericParams(), FD, TC);
@@ -3114,6 +3129,33 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
31143129
checkDynamicSelfType(FD, FD->getResultInterfaceType());
31153130

31163131
checkDefaultArguments(TC, FD->getParameters(), FD);
3132+
3133+
// Validate 'static'/'class' on functions in extensions.
3134+
auto StaticSpelling = FD->getStaticSpelling();
3135+
if (StaticSpelling != StaticSpellingKind::None &&
3136+
isa<ExtensionDecl>(FD->getDeclContext())) {
3137+
if (auto *NTD = FD->getDeclContext()->getSelfNominalTypeDecl()) {
3138+
if (!isa<ClassDecl>(NTD)) {
3139+
if (StaticSpelling == StaticSpellingKind::KeywordClass) {
3140+
FD->diagnose(diag::class_func_not_in_class, false)
3141+
.fixItReplace(FD->getStaticLoc(), "static");
3142+
NTD->diagnose(diag::extended_type_declared_here);
3143+
}
3144+
}
3145+
}
3146+
}
3147+
3148+
// Member functions need some special validation logic.
3149+
if (FD->getDeclContext()->isTypeContext()) {
3150+
if (FD->isOperator() && !isMemberOperator(FD, nullptr)) {
3151+
auto selfNominal = FD->getDeclContext()->getSelfNominalTypeDecl();
3152+
auto isProtocol = selfNominal && isa<ProtocolDecl>(selfNominal);
3153+
// We did not find 'Self'. Complain.
3154+
FD->diagnose(diag::operator_in_unrelated_type,
3155+
FD->getDeclContext()->getDeclaredInterfaceType(), isProtocol,
3156+
FD->getFullName());
3157+
}
3158+
}
31173159
}
31183160

31193161
void visitModuleDecl(ModuleDecl *) { }
@@ -3604,16 +3646,10 @@ FunctionOperatorRequest::evaluate(Evaluator &evaluator, FuncDecl *FD) const {
36043646
// Check for static/final/class when we're in a type.
36053647
auto dc = FD->getDeclContext();
36063648
if (dc->isTypeContext()) {
3607-
if (!FD->isStatic()) {
3608-
FD->diagnose(diag::nonstatic_operator_in_type,
3609-
operatorName, dc->getDeclaredInterfaceType())
3610-
.fixItInsert(FD->getAttributeInsertionLoc(/*forModifier=*/true),
3611-
"static ");
3612-
3613-
FD->setStatic();
3614-
} else if (auto classDecl = dc->getSelfClassDecl()) {
3649+
if (auto classDecl = dc->getSelfClassDecl()) {
36153650
// For a class, we also need the function or class to be 'final'.
36163651
if (!classDecl->isFinal() && !FD->isFinal() &&
3652+
FD->getStaticLoc().isValid() &&
36173653
FD->getStaticSpelling() != StaticSpellingKind::KeywordStatic) {
36183654
FD->diagnose(diag::nonfinal_operator_in_class,
36193655
operatorName, dc->getDeclaredInterfaceType())
@@ -3987,24 +4023,6 @@ void TypeChecker::validateDecl(ValueDecl *D) {
39874023

39884024
DeclValidationRAII IBV(FD);
39894025

3990-
// Force computing the operator decl in case it emits diagnostics.
3991-
(void) FD->getOperatorDecl();
3992-
3993-
// Validate 'static'/'class' on functions in extensions.
3994-
auto StaticSpelling = FD->getStaticSpelling();
3995-
if (StaticSpelling != StaticSpellingKind::None &&
3996-
isa<ExtensionDecl>(FD->getDeclContext())) {
3997-
if (auto *NTD = FD->getDeclContext()->getSelfNominalTypeDecl()) {
3998-
if (!isa<ClassDecl>(NTD)) {
3999-
if (StaticSpelling == StaticSpellingKind::KeywordClass) {
4000-
diagnose(FD, diag::class_func_not_in_class, false)
4001-
.fixItReplace(FD->getStaticLoc(), "static");
4002-
diagnose(NTD, diag::extended_type_declared_here);
4003-
}
4004-
}
4005-
}
4006-
}
4007-
40084026
// Accessors should pick up various parts of their type signatures
40094027
// directly from the storage declaration instead of re-deriving them.
40104028
// FIXME: should this include the generic signature?
@@ -4086,18 +4104,6 @@ void TypeChecker::validateDecl(ValueDecl *D) {
40864104
// FIXME: Roll all of this interface type computation into a request.
40874105
FD->computeType();
40884106

4089-
// Member functions need some special validation logic.
4090-
if (FD->getDeclContext()->isTypeContext()) {
4091-
if (FD->isOperator() && !isMemberOperator(FD, nullptr)) {
4092-
auto selfNominal = FD->getDeclContext()->getSelfNominalTypeDecl();
4093-
auto isProtocol = selfNominal && isa<ProtocolDecl>(selfNominal);
4094-
// We did not find 'Self'. Complain.
4095-
diagnose(FD, diag::operator_in_unrelated_type,
4096-
FD->getDeclContext()->getDeclaredInterfaceType(), isProtocol,
4097-
FD->getFullName());
4098-
}
4099-
}
4100-
41014107
// If the function is exported to C, it must be representable in (Obj-)C.
41024108
if (auto CDeclAttr = FD->getAttrs().getAttribute<swift::CDeclAttr>()) {
41034109
Optional<ForeignErrorConvention> errorConvention;

0 commit comments

Comments
 (0)