diff --git a/docs/LangRef.html b/docs/LangRef.html index e7804c16c09..328bd33e975 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -458,7 +458,7 @@

oneof and struct declaration extensions

-

'var' decls are not allowed in a oneof or struct, +

'var' decls that do not have a getter or setter are not allowed in a oneof or struct, data members should be used instead.

diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index e31f6e2c6ce..973827b8b1e 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -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(this)) + PBD->updateDeclContextForVars(); + else if (VarDecl *Var = dyn_cast(this)) + Var->updateDeclContextForGetSet(); +} + } // end namespace swift #endif diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 694e6b78014..33b5bf78452 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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(P)->getDecl()->setDeclContext(DC); + break; + + case PatternKind::Paren: + updateDeclContextForVarsInPattern(cast(P)->getSubPattern(), + DC); + break; + + case PatternKind::Tuple: + for (auto &Elt : cast(P)->getFields()) + updateDeclContextForVarsInPattern(Elt.getPattern(), DC); + break; + + case PatternKind::Typed: + updateDeclContextForVarsInPattern(cast(P)->getSubPattern(), + DC); + break; + } +} + +void PatternBindingDecl::updateDeclContextForVars() { + updateDeclContextForVarsInPattern(Pat, getDeclContext()); +} //===----------------------------------------------------------------------===// diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c0793ecd642..6b63d37dc5c 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -349,7 +349,8 @@ bool Parser::parseDecl(SmallVectorImpl &Entries, unsigned Flags) { // FIXME: Mark decls erroneous. if (isa(D) && !(Flags & PD_AllowTopLevel)) diagnose(D->getLocStart(), diag::decl_inner_scope); - if (isa(D) && (Flags & PD_DisallowVar)) { + if (isa(D) && (Flags & PD_DisallowVar) && + !cast(D)->isProperty()) { diagnose(D->getLocStart(), diag::disallowed_var_decl); } else if (NamedDecl *ND = dyn_cast(D)) { if (ND->isOperator() && (Flags & PD_DisallowOperators)) diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index caace099587..e61c75f6824 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -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) {