@@ -4470,16 +4470,12 @@ struct Parser::ParsedAccessors {
4470
4470
#include " swift/AST/AccessorKinds.def"
4471
4471
4472
4472
void record (Parser &P, AbstractStorageDecl *storage, bool invalid,
4473
- ParseDeclOptions flags, SourceLoc staticLoc,
4474
4473
const DeclAttributes &attrs,
4475
- TypeLoc elementTy, ParameterList *indices,
4476
4474
SmallVectorImpl<Decl *> &decls);
4477
4475
4478
4476
StorageImplInfo
4479
4477
classify (Parser &P, AbstractStorageDecl *storage, bool invalid,
4480
- ParseDeclOptions flags, SourceLoc staticLoc,
4481
- const DeclAttributes &attrs,
4482
- TypeLoc elementTy, ParameterList *indices);
4478
+ const DeclAttributes &attrs);
4483
4479
4484
4480
// / Add an accessor. If there's an existing accessor of this kind,
4485
4481
// / return it. The new accessor is still remembered but will be
@@ -4912,8 +4908,7 @@ Parser::parseDeclVarGetSet(Pattern *pattern, ParseDeclOptions Flags,
4912
4908
accessors.Set ->setInvalid ();
4913
4909
}
4914
4910
4915
- accessors.record (*this , PrimaryVar, Invalid, Flags, StaticLoc,
4916
- Attributes, TyLoc, /* indices*/ nullptr , Decls);
4911
+ accessors.record (*this , PrimaryVar, Invalid, Attributes, Decls);
4917
4912
4918
4913
return makeParserResult (PrimaryVar);
4919
4914
}
@@ -4940,13 +4935,10 @@ AccessorDecl *Parser::ParsedAccessors::add(AccessorDecl *accessor) {
4940
4935
4941
4936
// / Record a bunch of parsed accessors into the given abstract storage decl.
4942
4937
void Parser::ParsedAccessors::record (Parser &P, AbstractStorageDecl *storage,
4943
- bool invalid, ParseDeclOptions flags,
4944
- SourceLoc staticLoc,
4938
+ bool invalid,
4945
4939
const DeclAttributes &attrs,
4946
- TypeLoc elementTy, ParameterList *indices,
4947
4940
SmallVectorImpl<Decl *> &decls) {
4948
- auto storageKind = classify (P, storage, invalid, flags, staticLoc, attrs,
4949
- elementTy, indices);
4941
+ auto storageKind = classify (P, storage, invalid, attrs);
4950
4942
storage->setImplInfo (storageKind);
4951
4943
4952
4944
decls.append (Accessors.begin (), Accessors.end ());
@@ -4959,13 +4951,6 @@ static void flagInvalidAccessor(AccessorDecl *func) {
4959
4951
}
4960
4952
}
4961
4953
4962
- static void ignoreInvalidAccessor (AccessorDecl *&func) {
4963
- if (func) {
4964
- flagInvalidAccessor (func);
4965
- func = nullptr ;
4966
- }
4967
- }
4968
-
4969
4954
static void diagnoseConflictingAccessors (Parser &P, AccessorDecl *first,
4970
4955
AccessorDecl *&second) {
4971
4956
if (!second) return ;
@@ -4976,7 +4961,7 @@ static void diagnoseConflictingAccessors(Parser &P, AccessorDecl *first,
4976
4961
P.diagnose (first->getLoc (), diag::previous_accessor,
4977
4962
getAccessorNameForDiagnostic (first, /* article*/ false ),
4978
4963
/* already*/ false );
4979
- ignoreInvalidAccessor (second);
4964
+ flagInvalidAccessor (second);
4980
4965
}
4981
4966
4982
4967
template <class ... DiagArgs>
@@ -4986,11 +4971,11 @@ static void diagnoseAndIgnoreObservers(Parser &P,
4986
4971
typename std::enable_if<true , DiagArgs>::type... args) {
4987
4972
if (auto &accessor = accessors.WillSet ) {
4988
4973
P.diagnose (accessor->getLoc (), diagnostic, /* willSet*/ 0 , args...);
4989
- ignoreInvalidAccessor (accessor);
4974
+ flagInvalidAccessor (accessor);
4990
4975
}
4991
4976
if (auto &accessor = accessors.DidSet ) {
4992
4977
P.diagnose (accessor->getLoc (), diagnostic, /* didSet*/ 1 , args...);
4993
- ignoreInvalidAccessor (accessor);
4978
+ flagInvalidAccessor (accessor);
4994
4979
}
4995
4980
}
4996
4981
@@ -5013,20 +4998,10 @@ static void diagnoseAndIgnoreObservers(Parser &P,
5013
4998
// / - MaterializeToTemporary, if the decl has a setter.
5014
4999
static StorageImplInfo classifyWithHasStorageAttr (
5015
5000
Parser::ParsedAccessors &accessors, ASTContext &ctx,
5016
- AbstractStorageDecl *storage, const DeclAttributes &attrs) {
5017
-
5018
- // Determines if the storage is immutable, either by declaring itself as a
5019
- // `let` or by omitting a setter.
5020
- auto isImmutable = [&]() {
5021
- if (auto varDecl = dyn_cast<VarDecl>(storage))
5022
- return varDecl->isLet ();
5023
- if (accessors.Set == nullptr ) return true ;
5024
- return false ;
5025
- };
5001
+ VarDecl *var, const DeclAttributes &attrs) {
5026
5002
5027
- // Default to stored writes.
5028
- WriteImplKind writeImpl = WriteImplKind::Stored;
5029
- ReadWriteImplKind readWriteImpl = ReadWriteImplKind::Stored;
5003
+ WriteImplKind writeImpl;
5004
+ ReadWriteImplKind readWriteImpl;
5030
5005
5031
5006
if (accessors.Get && accessors.Set ) {
5032
5007
// If we see `@_hasStorage var x: T { get set }`, then our property has
@@ -5035,9 +5010,13 @@ static StorageImplInfo classifyWithHasStorageAttr(
5035
5010
WriteImplKind::InheritedWithObservers :
5036
5011
WriteImplKind::StoredWithObservers;
5037
5012
readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
5038
- } else if (isImmutable ()) {
5013
+ } else if (var-> isLet ()) {
5039
5014
writeImpl = WriteImplKind::Immutable;
5040
5015
readWriteImpl = ReadWriteImplKind::Immutable;
5016
+ } else {
5017
+ // Default to stored writes.
5018
+ writeImpl = WriteImplKind::Stored;
5019
+ readWriteImpl = ReadWriteImplKind::Stored;
5041
5020
}
5042
5021
5043
5022
// Always force Stored reads if @_hasStorage is present.
@@ -5046,14 +5025,7 @@ static StorageImplInfo classifyWithHasStorageAttr(
5046
5025
5047
5026
StorageImplInfo
5048
5027
Parser::ParsedAccessors::classify (Parser &P, AbstractStorageDecl *storage,
5049
- bool invalid, ParseDeclOptions flags,
5050
- SourceLoc staticLoc,
5051
- const DeclAttributes &attrs,
5052
- TypeLoc elementTy, ParameterList *indices) {
5053
- GenericParamList *genericParams = nullptr ;
5054
- if (auto *subscript = dyn_cast<SubscriptDecl>(storage))
5055
- genericParams = subscript->getGenericParams ();
5056
-
5028
+ bool invalid, const DeclAttributes &attrs) {
5057
5029
// If there was a problem parsing accessors, mark all parsed accessors
5058
5030
// as invalid to avoid tripping up later invariants.
5059
5031
// We also want to avoid diagnose missing accessors if something
@@ -5077,35 +5049,19 @@ Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
5077
5049
diagnoseAndIgnoreObservers (P, *this ,
5078
5050
diag::observing_accessor_conflicts_with_accessor,
5079
5051
getAccessorNameForDiagnostic (nonObserver, /* article*/ true ));
5080
-
5081
- // Otherwise, we have either a stored or inherited observing property.
5082
- } else {
5083
- if (attrs.hasAttribute <OverrideAttr>()) {
5084
- return StorageImplInfo (ReadImplKind::Inherited,
5085
- WriteImplKind::InheritedWithObservers,
5086
- ReadWriteImplKind::MaterializeToTemporary);
5087
- } else {
5088
- return StorageImplInfo (ReadImplKind::Stored,
5089
- WriteImplKind::StoredWithObservers,
5090
- ReadWriteImplKind::MaterializeToTemporary);
5091
- }
5092
5052
}
5093
5053
}
5094
5054
5095
5055
// Okay, observers are out of the way.
5096
- assert (!WillSet && !DidSet);
5097
5056
5098
5057
// 'get', 'read', and a non-mutable addressor are all exclusive.
5099
- ReadImplKind readImpl;
5100
5058
if (Get) {
5101
5059
diagnoseConflictingAccessors (P, Get, Read);
5102
5060
diagnoseConflictingAccessors (P, Get, Address);
5103
- readImpl = ReadImplKind::Get;
5104
5061
} else if (Read) {
5105
5062
diagnoseConflictingAccessors (P, Read, Address);
5106
- readImpl = ReadImplKind::Read;
5107
5063
} else if (Address) {
5108
- readImpl = ReadImplKind::Address;
5064
+ // Nothing can go wrong.
5109
5065
5110
5066
// If there's a writing accessor of any sort, there must also be a
5111
5067
// reading accessor.
@@ -5121,76 +5077,116 @@ Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
5121
5077
getAccessorNameForDiagnostic (mutator, /* article*/ true ));
5122
5078
}
5123
5079
5124
- readImpl = ReadImplKind::Get;
5125
-
5126
5080
// Subscripts always have to have some sort of accessor; they can't be
5127
5081
// purely stored.
5128
5082
} else if (isa<SubscriptDecl>(storage)) {
5129
5083
if (!invalid) {
5130
5084
P.diagnose (LBLoc, diag::subscript_without_get);
5131
5085
}
5086
+ }
5087
+
5088
+ // A mutable addressor is exclusive with 'set' and 'modify', but
5089
+ // 'set' and 'modify' can appear together.
5090
+ if (Set) {
5091
+ diagnoseConflictingAccessors (P, Set, MutableAddress);
5092
+ } else if (Modify) {
5093
+ diagnoseConflictingAccessors (P, Modify, MutableAddress);
5094
+ }
5095
+
5096
+ if (auto *var = dyn_cast<VarDecl>(storage)) {
5097
+ // Allow the @_hasStorage attribute to override all the accessors we parsed
5098
+ // when making the final classification.
5099
+ if (attrs.hasAttribute <HasStorageAttr>()) {
5100
+ // The SIL rules for @_hasStorage are slightly different from the non-SIL
5101
+ // rules. In SIL mode, @_hasStorage marks that the type is simply stored,
5102
+ // and the only thing that determines mutability is the existence of the
5103
+ // setter.
5104
+ //
5105
+ // FIXME: SIL should not be special cased here. The behavior should be
5106
+ // consistent between SIL and non-SIL.
5107
+ // The strategy here should be to keep track of all opaque accessors
5108
+ // along with enough information to access the storage trivially
5109
+ // if allowed. This could be a representational change to
5110
+ // StorageImplInfo such that it keeps a bitset of listed accessors
5111
+ // and dynamically determines the access strategy from that.
5112
+ if (P.isInSILMode ())
5113
+ return StorageImplInfo::getSimpleStored (
5114
+ StorageIsMutable_t (Set != nullptr ));
5115
+
5116
+ return classifyWithHasStorageAttr (*this , P.Context , var, attrs);
5117
+ }
5118
+ }
5132
5119
5120
+ // 'get', 'read', and a non-mutable addressor are all exclusive.
5121
+ ReadImplKind readImpl;
5122
+ if (Get) {
5123
+ readImpl = ReadImplKind::Get;
5124
+ } else if (Read) {
5125
+ readImpl = ReadImplKind::Read;
5126
+ } else if (Address) {
5127
+ readImpl = ReadImplKind::Address;
5128
+
5129
+ // If there's a writing accessor of any sort, there must also be a
5130
+ // reading accessor.
5131
+ } else if (auto mutator = findFirstMutator ()) {
5133
5132
readImpl = ReadImplKind::Get;
5134
5133
5134
+ // Subscripts always have to have some sort of accessor; they can't be
5135
+ // purely stored.
5136
+ } else if (isa<SubscriptDecl>(storage)) {
5137
+ readImpl = ReadImplKind::Get;
5138
+
5139
+ // Check if we have observers.
5140
+ } else if (WillSet || DidSet) {
5141
+ if (attrs.hasAttribute <OverrideAttr>()) {
5142
+ readImpl = ReadImplKind::Inherited;
5143
+ } else {
5144
+ readImpl = ReadImplKind::Stored;
5145
+ }
5146
+
5135
5147
// Otherwise, it's stored.
5136
5148
} else {
5137
5149
readImpl = ReadImplKind::Stored;
5138
5150
}
5139
5151
5140
- // A mutable addressor is exclusive with 'set' and 'modify', but
5141
- // 'set' and 'modify' can appear together.
5142
5152
// Prefer using 'set' and 'modify' over a mutable addressor.
5143
5153
WriteImplKind writeImpl;
5144
5154
ReadWriteImplKind readWriteImpl;
5145
5155
if (Set) {
5146
- diagnoseConflictingAccessors (P, Set, MutableAddress);
5147
5156
writeImpl = WriteImplKind::Set;
5148
5157
if (Modify) {
5149
5158
readWriteImpl = ReadWriteImplKind::Modify;
5150
5159
} else {
5151
5160
readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
5152
5161
}
5153
5162
} else if (Modify) {
5154
- diagnoseConflictingAccessors (P, Modify, MutableAddress);
5155
5163
writeImpl = WriteImplKind::Modify;
5156
5164
readWriteImpl = ReadWriteImplKind::Modify;
5157
5165
} else if (MutableAddress) {
5158
5166
writeImpl = WriteImplKind::MutableAddress;
5159
5167
readWriteImpl = ReadWriteImplKind::MutableAddress;
5160
5168
5161
- // Otherwise, it's stored if there was no specific reading accessor.
5169
+ // Check if we have observers.
5170
+ } else if (readImpl == ReadImplKind::Inherited) {
5171
+ writeImpl = WriteImplKind::InheritedWithObservers;
5172
+ readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
5173
+
5174
+ // Otherwise, it's stored.
5162
5175
} else if (readImpl == ReadImplKind::Stored) {
5163
- writeImpl = WriteImplKind::Stored;
5164
- readWriteImpl = ReadWriteImplKind::Stored;
5176
+ if (WillSet || DidSet) {
5177
+ writeImpl = WriteImplKind::StoredWithObservers;
5178
+ readWriteImpl = ReadWriteImplKind::MaterializeToTemporary;
5179
+ } else {
5180
+ writeImpl = WriteImplKind::Stored;
5181
+ readWriteImpl = ReadWriteImplKind::Stored;
5182
+ }
5165
5183
5166
5184
// Otherwise, it's immutable.
5167
5185
} else {
5168
5186
writeImpl = WriteImplKind::Immutable;
5169
5187
readWriteImpl = ReadWriteImplKind::Immutable;
5170
5188
}
5171
5189
5172
- // Allow the @_hasStorage attribute to override all the accessors we parsed
5173
- // when making the final classification.
5174
- if (attrs.hasAttribute <HasStorageAttr>()) {
5175
- // The SIL rules for @_hasStorage are slightly different from the non-SIL
5176
- // rules. In SIL mode, @_hasStorage marks that the type is simply stored,
5177
- // and the only thing that determines mutability is the existence of the
5178
- // setter.
5179
- //
5180
- // FIXME: SIL should not be special cased here. The behavior should be
5181
- // consistent between SIL and non-SIL.
5182
- // The strategy here should be to keep track of all opaque accessors
5183
- // along with enough information to access the storage trivially
5184
- // if allowed. This could be a representational change to
5185
- // StorageImplInfo such that it keeps a bitset of listed accessors
5186
- // and dynamically determines the access strategy from that.
5187
- if (P.isInSILMode ())
5188
- return StorageImplInfo::getSimpleStored (
5189
- StorageIsMutable_t (Set != nullptr ));
5190
-
5191
- return classifyWithHasStorageAttr (*this , P.Context , storage, attrs);
5192
- }
5193
-
5194
5190
return StorageImplInfo (readImpl, writeImpl, readWriteImpl);
5195
5191
}
5196
5192
@@ -6603,8 +6599,7 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
6603
6599
}
6604
6600
6605
6601
accessors.record (*this , Subscript, (Invalid || !Status.isSuccess ()),
6606
- Flags, StaticLoc, Attributes,
6607
- ElementTy.get (), Indices.get (), Decls);
6602
+ Attributes, Decls);
6608
6603
6609
6604
// No need to setLocalDiscriminator because subscripts cannot
6610
6605
// validly appear outside of type decls.
0 commit comments