Skip to content

Commit 935142f

Browse files
committed
[ConstraintSystem] InitAccessors: Detect invalid references to members within init accessors
Only properties that are listed in 'initializes' and 'accesses' attributes could be referenced within init accessor. Detect any and all invalid member references in the solver.
1 parent 5613006 commit 935142f

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,6 +1879,11 @@ struct MemberLookupResult {
18791879
/// This is a static member being access through a protocol metatype
18801880
/// but its result type doesn't conform to this protocol.
18811881
UR_InvalidStaticMemberOnProtocolMetatype,
1882+
1883+
/// This is a member that doesn't appear in 'initializes' and/or
1884+
/// 'accesses' attributes of the init accessor and therefore canno
1885+
/// t be referenced in its body.
1886+
UR_UnavailableWithinInitAccessor,
18821887
};
18831888

18841889
/// This is a list of considered (but rejected) candidates, along with a

lib/Sema/CSSimplify.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9632,6 +9632,44 @@ performMemberLookup(ConstraintKind constraintKind, DeclNameRef memberName,
96329632
}
96339633
}
96349634

9635+
if (auto *UDE =
9636+
getAsExpr<UnresolvedDotExpr>(memberLocator->getAnchor())) {
9637+
auto *base = UDE->getBase();
9638+
if (auto *accessor = DC->getInnermostPropertyAccessorContext()) {
9639+
if (accessor->isInitAccessor() && isa<DeclRefExpr>(base) &&
9640+
accessor->getImplicitSelfDecl() ==
9641+
cast<DeclRefExpr>(base)->getDecl()) {
9642+
bool isValidReference = false;
9643+
9644+
// If name doesn't appear in either `initializes` or `accesses`
9645+
// then it's invalid instance member.
9646+
9647+
if (auto *initializesAttr =
9648+
accessor->getAttrs().getAttribute<InitializesAttr>()) {
9649+
isValidReference |= llvm::any_of(
9650+
initializesAttr->getProperties(), [&](Identifier name) {
9651+
return DeclNameRef(name) == memberName;
9652+
});
9653+
}
9654+
9655+
if (auto *accessesAttr =
9656+
accessor->getAttrs().getAttribute<AccessesAttr>()) {
9657+
isValidReference |= llvm::any_of(
9658+
accessesAttr->getProperties(), [&](Identifier name) {
9659+
return DeclNameRef(name) == memberName;
9660+
});
9661+
}
9662+
9663+
if (!isValidReference) {
9664+
result.addUnviable(
9665+
candidate,
9666+
MemberLookupResult::UR_UnavailableWithinInitAccessor);
9667+
return;
9668+
}
9669+
}
9670+
}
9671+
}
9672+
96359673
// If the underlying type of a typealias is fully concrete, it is legal
96369674
// to access the type with a protocol metatype base.
96379675
} else if (instanceTy->isExistentialType() &&
@@ -10208,6 +10246,9 @@ fixMemberRef(ConstraintSystem &cs, Type baseTy,
1020810246

1020910247
case MemberLookupResult::UR_InvalidStaticMemberOnProtocolMetatype:
1021010248
return AllowInvalidStaticMemberRefOnProtocolMetatype::create(cs, locator);
10249+
10250+
case MemberLookupResult::UR_UnavailableWithinInitAccessor:
10251+
return nullptr;
1021110252
}
1021210253
}
1021310254

0 commit comments

Comments
 (0)