mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Allow variables with a getter or setter to be declared in a
struct/oneof/class extension, making them instance methods. Normal variables are still not allowed in these contexts, however. The fact that we set DeclContexts late causes some consternation here, because it's not clear just how far we need to recurse in DeclContext. I've done enough to make properties work, but I'm still rather uneasy about the current state of affairs. Swift SVN r1423
This commit is contained in:
@@ -458,7 +458,7 @@
|
||||
<h4 id="decl-extension-oneof-struct"><a href="#decl-oneof">oneof</a> and <a
|
||||
href="#decl-struct">struct</a> declaration extensions</h4>
|
||||
|
||||
<p>'<a href="#decl-var">var</a>' decls are not allowed in a oneof or struct,
|
||||
<p>'<a href="#decl-var">var</a>' decls that do not have a getter or setter are not allowed in a oneof or struct,
|
||||
data members should be used instead.</p>
|
||||
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
DeclKind getKind() const { return DeclKind(DeclBits.Kind); }
|
||||
|
||||
DeclContext *getDeclContext() const { return Context; }
|
||||
void setDeclContext(DeclContext *DC) { Context = DC; }
|
||||
void setDeclContext(DeclContext *DC);
|
||||
|
||||
/// getASTContext - Return the ASTContext that this decl lives in.
|
||||
ASTContext &getASTContext() const {
|
||||
@@ -218,6 +218,12 @@ class PatternBindingDecl : public Decl {
|
||||
Pattern *Pat; // The pattern which this decl binds
|
||||
Expr *Init; // Initializer for the variables
|
||||
|
||||
friend class Decl;
|
||||
|
||||
/// \brief Update the DeclContext for any variables in the pattern to
|
||||
/// refer to the same DeclContext as this declaration.
|
||||
void updateDeclContextForVars();
|
||||
|
||||
public:
|
||||
PatternBindingDecl(SourceLoc VarLoc, Pattern *Pat, Expr *E,
|
||||
DeclContext *Parent)
|
||||
@@ -425,6 +431,9 @@ private:
|
||||
|
||||
GetSetRecord *GetSet;
|
||||
|
||||
friend class Decl;
|
||||
void updateDeclContextForGetSet();
|
||||
|
||||
public:
|
||||
VarDecl(SourceLoc VarLoc, Identifier Name, Type Ty, DeclContext *DC,
|
||||
bool IsModuleScope)
|
||||
@@ -540,6 +549,14 @@ public:
|
||||
|
||||
};
|
||||
|
||||
inline void Decl::setDeclContext(DeclContext *DC) {
|
||||
Context = DC;
|
||||
if (PatternBindingDecl *PBD = dyn_cast<PatternBindingDecl>(this))
|
||||
PBD->updateDeclContextForVars();
|
||||
else if (VarDecl *Var = dyn_cast<VarDecl>(this))
|
||||
Var->updateDeclContextForGetSet();
|
||||
}
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
|
||||
@@ -146,6 +146,16 @@ void VarDecl::setProperty(ASTContext &Context, SourceLoc LBraceLoc,
|
||||
GetSet->Set = Set;
|
||||
}
|
||||
|
||||
void VarDecl::updateDeclContextForGetSet() {
|
||||
if (!GetSet)
|
||||
return;
|
||||
|
||||
if (GetSet->Get)
|
||||
GetSet->Get->setDeclContext(getDeclContext());
|
||||
if (GetSet->Set)
|
||||
GetSet->Set->setDeclContext(getDeclContext());
|
||||
}
|
||||
|
||||
/// getExtensionType - If this is a method in a type extension for some type,
|
||||
/// return that type, otherwise return Type().
|
||||
Type FuncDecl::getExtensionType() const {
|
||||
@@ -212,6 +222,35 @@ VarDecl *FuncDecl::getImplicitThisDecl() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void updateDeclContextForVarsInPattern(Pattern *P, DeclContext *DC) {
|
||||
switch (P->getKind()) {
|
||||
case PatternKind::Any:
|
||||
break;
|
||||
|
||||
case PatternKind::Named:
|
||||
cast<NamedPattern>(P)->getDecl()->setDeclContext(DC);
|
||||
break;
|
||||
|
||||
case PatternKind::Paren:
|
||||
updateDeclContextForVarsInPattern(cast<ParenPattern>(P)->getSubPattern(),
|
||||
DC);
|
||||
break;
|
||||
|
||||
case PatternKind::Tuple:
|
||||
for (auto &Elt : cast<TuplePattern>(P)->getFields())
|
||||
updateDeclContextForVarsInPattern(Elt.getPattern(), DC);
|
||||
break;
|
||||
|
||||
case PatternKind::Typed:
|
||||
updateDeclContextForVarsInPattern(cast<TypedPattern>(P)->getSubPattern(),
|
||||
DC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PatternBindingDecl::updateDeclContextForVars() {
|
||||
updateDeclContextForVarsInPattern(Pat, getDeclContext());
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -349,7 +349,8 @@ bool Parser::parseDecl(SmallVectorImpl<Decl*> &Entries, unsigned Flags) {
|
||||
// FIXME: Mark decls erroneous.
|
||||
if (isa<ImportDecl>(D) && !(Flags & PD_AllowTopLevel))
|
||||
diagnose(D->getLocStart(), diag::decl_inner_scope);
|
||||
if (isa<VarDecl>(D) && (Flags & PD_DisallowVar)) {
|
||||
if (isa<VarDecl>(D) && (Flags & PD_DisallowVar) &&
|
||||
!cast<VarDecl>(D)->isProperty()) {
|
||||
diagnose(D->getLocStart(), diag::disallowed_var_decl);
|
||||
} else if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
|
||||
if (ND->isOperator() && (Flags & PD_DisallowOperators))
|
||||
|
||||
@@ -121,6 +121,12 @@ public:
|
||||
void visitVarDecl(VarDecl *VD) {
|
||||
// Delay type-checking on VarDecls until we see the corresponding
|
||||
// PatternBindingDecl.
|
||||
if (VD->isProperty()) {
|
||||
if (FuncDecl *Get = VD->getGetter())
|
||||
visitFuncDecl(Get);
|
||||
if (FuncDecl *Set = VD->getSetter())
|
||||
visitFuncDecl(Set);
|
||||
}
|
||||
}
|
||||
|
||||
void visitFuncDecl(FuncDecl *FD) {
|
||||
|
||||
Reference in New Issue
Block a user