1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PANDA_VERIFICATION_TYPE_TYPE_SYSTEM_H_ 17 #define PANDA_VERIFICATION_TYPE_TYPE_SYSTEM_H_ 18 19 #include "verification/util/lazy.h" 20 #include "verification/util/relation.h" 21 #include "type_sort.h" 22 #include "type_index.h" 23 #include "type_info.h" 24 #include "type_type.h" 25 #include "type_set.h" 26 #include "type_param.h" 27 #include "type_params.h" 28 #include "type_parametric.h" 29 #include "subtyping_closure.h" 30 31 #include "type_systems.h" 32 33 #include "runtime/include/mem/panda_containers.h" 34 35 #include "libpandabase/os/mutex.h" 36 37 #include "macros.h" 38 39 #include "type_system_kind.h" 40 41 #include <memory> 42 #include <variant> 43 #include <functional> 44 #include <algorithm> 45 46 namespace panda::verifier { 47 /* 48 Design decisions: 49 1. Subtyping relation is kept flat during types construction 50 2. Subtyping relation closing may be either incremental/implicit during types construction or explicit 51 3. Sorts are abstracted in the form of indices (of type size_t) 52 4. Types internally represented as indices (size_t) 53 5. There are special initial and final types, named as Bot and Top, and all types are implicitly related 54 as Bot <: type <: Top 55 */ 56 57 class TypeSystem { 58 public: 59 TypeSystem(const TypeSystem &) = delete; 60 TypeSystem(TypeSystem &&) = delete; 61 TypeSystem &operator=(const TypeSystem &) = delete; 62 TypeSystem &operator=(TypeSystem &&) = delete; 63 ~TypeSystem() = default; 64 65 using TypeUniverse = PandaVector<TypeInfo>; 66 using MappingToIdx = PandaUnorderedMap<TypeInfo, TypeIdx>; 67 // sort -> arity -> types 68 using TypeClasses = PandaVector<PandaUnorderedMap<size_t, VectorIdx>>; 69 70 Relation TypingRel_; 71 PandaVector<PandaUnorderedSet<TypeIdx>> ParameterOf_; 72 TypeUniverse Universe_; 73 MappingToIdx InfoToIdx_; 74 mutable TypeClasses TypeClasses_; 75 SubtypingClosureInfo SubtypingClosureCurrent_; 76 SubtypingClosureInfo SubtypingClosureNext_; 77 bool IncrementalSubtypingClosure_ = true; 78 bool DeferIncrementalSubtypingClosure_ = false; 79 80 TypeSystemKind kind_; 81 FindIdx(const TypeInfo & ti)82 Index<TypeIdx> FindIdx(const TypeInfo &ti) 83 { 84 auto it = InfoToIdx_.find(ti); 85 if (it != InfoToIdx_.end()) { 86 return it->second; 87 } 88 return {}; 89 } 90 FindIdxOrCreate(const TypeInfo & ti)91 TypeIdx FindIdxOrCreate(const TypeInfo &ti) 92 { 93 Index<TypeIdx> existing_idx = FindIdx(ti); 94 if (existing_idx.IsValid()) { 95 return existing_idx; 96 } 97 size_t idx = Universe_.size(); 98 TypingRel_.EnsureMinSize(idx); 99 Universe_.push_back(ti); 100 ParameterOf_.push_back({}); 101 const auto ¶ms = ti.ParamsIdx(); 102 for (const auto ¶m : params) { 103 ParameterOf_[param].insert(idx); 104 } 105 InfoToIdx_[ti] = idx; 106 SortIdx sort = ti.Sort(); 107 size_t arity = params.size(); 108 if (sort >= TypeClasses_.size()) { 109 TypeClasses_.resize(sort + 1); 110 } 111 TypeClasses_[sort][arity].push_back(idx); 112 Relate(idx, idx); 113 return idx; 114 } 115 TypeClassIdx(TypeIdx type)116 const VectorIdx &TypeClassIdx(TypeIdx type) const 117 { 118 const auto &info = Universe_[type]; 119 const auto ¶ms = info.ParamsIdx(); 120 return TypeClasses_[info.Sort()][params.size()]; 121 } 122 PerformClosingCurrentRelation()123 void PerformClosingCurrentRelation() NO_THREAD_SAFETY_ANALYSIS 124 { 125 auto add_to_next = [this](TypeIdx type) NO_THREAD_SAFETY_ANALYSIS { 126 const auto &info = Universe_[type]; 127 SubtypingClosureNext_.AddType(info.Sort(), type, info.Arity()); 128 return true; 129 }; 130 while (!SubtypingClosureCurrent_.Empty()) { 131 SubtypingClosureCurrent_.ForAllTypeClasses([this, &add_to_next](auto &types) { 132 for (auto type_lhs : types) { 133 for (auto type_rhs : types) { 134 bool in_direct_relation = TypingRel_.IsInDirectRelation(type_lhs, type_rhs); 135 if (!in_direct_relation && CheckIfLhsSubtypeOfRhs(type_lhs, type_rhs)) { 136 add_to_next(type_lhs); 137 add_to_next(type_rhs); 138 TypingRel_ += {type_lhs, type_rhs}; 139 for (const auto &type : ParameterOf_[type_lhs]) { 140 add_to_next(type); 141 TypingRel_.ForAllTo(type, add_to_next); 142 TypingRel_.ForAllFrom(type, add_to_next); 143 } 144 for (const auto &type : ParameterOf_[type_rhs]) { 145 add_to_next(type); 146 TypingRel_.ForAllTo(type, add_to_next); 147 TypingRel_.ForAllFrom(type, add_to_next); 148 } 149 } 150 } 151 } 152 }); 153 SubtypingClosureCurrent_.swap(SubtypingClosureNext_); 154 SubtypingClosureNext_.Clear(); 155 } 156 } 157 Relate(TypeIdx lhs,TypeIdx rhs)158 void Relate(TypeIdx lhs, TypeIdx rhs) 159 { 160 if (TypingRel_.IsInDirectRelation(lhs, rhs)) { 161 return; 162 } 163 TypingRel_ += {lhs, rhs}; 164 if (IncrementalSubtypingClosure_) { 165 auto process_type = [this](TypeIdx type) { 166 auto add_to_current = [this](TypeIdx type_idx) { 167 const auto &info = Universe_[type_idx]; 168 SubtypingClosureCurrent_.AddType(info.Sort(), type_idx, info.Arity()); 169 return true; 170 }; 171 for (const auto &type_idx : TypeClassIdx(type)) { 172 add_to_current(type_idx); 173 } 174 for (const auto &type_idx : ParameterOf_[type]) { 175 add_to_current(type_idx); 176 TypingRel_.ForAllTo(type_idx, add_to_current); 177 TypingRel_.ForAllFrom(type_idx, add_to_current); 178 } 179 }; 180 process_type(lhs); 181 if (lhs != rhs) { 182 process_type(rhs); 183 } 184 if (!DeferIncrementalSubtypingClosure_) { 185 PerformClosingCurrentRelation(); 186 } 187 } 188 } 189 CheckIfLhsParamsSubtypeOfRhs(const TypeParamsIdx & lhs,const TypeParamsIdx & rhs)190 bool CheckIfLhsParamsSubtypeOfRhs(const TypeParamsIdx &lhs, const TypeParamsIdx &rhs) const 191 { 192 if (lhs.size() != rhs.size()) { 193 return false; 194 } 195 auto lhs_it = lhs.cbegin(); 196 auto rhs_it = rhs.cbegin(); 197 for (; lhs_it != lhs.cend(); ++lhs_it, ++rhs_it) { 198 switch (lhs_it->Variance()) { 199 case TypeVariance::INVARIANT: 200 if (!TypingRel_.IsInIsoRelation(*lhs_it, *rhs_it)) { 201 return false; 202 }; 203 break; 204 case TypeVariance::COVARIANT: 205 if (!TypingRel_.IsInDirectRelation(*lhs_it, *rhs_it)) { 206 return false; 207 }; 208 break; 209 case TypeVariance::CONTRVARIANT: 210 if (!TypingRel_.IsInInverseRelation(*lhs_it, *rhs_it)) { 211 return false; 212 }; 213 break; 214 default: 215 break; 216 } 217 } 218 return true; 219 } 220 CheckIfLhsSubtypeOfRhs(TypeIdx lhs,TypeIdx rhs)221 bool CheckIfLhsSubtypeOfRhs(TypeIdx lhs, TypeIdx rhs) const 222 { 223 const TypeInfo &lhs_info = Universe_[lhs]; 224 const TypeInfo &rhs_info = Universe_[rhs]; 225 if (lhs_info.Sort() != rhs_info.Sort()) { 226 return false; 227 } 228 const TypeParamsIdx &lhs_params = lhs_info.ParamsIdx(); 229 const TypeParamsIdx &rhs_params = rhs_info.ParamsIdx(); 230 return CheckIfLhsParamsSubtypeOfRhs(lhs_params, rhs_params); 231 } 232 IsInDirectRelation(TypeIdx lhs,TypeIdx rhs)233 bool IsInDirectRelation(TypeIdx lhs, TypeIdx rhs) const 234 { 235 return TypingRel_.IsInDirectRelation(lhs, rhs); 236 } 237 GetSort(TypeIdx t)238 size_t GetSort(TypeIdx t) const 239 { 240 return Universe_[t].Sort(); 241 } 242 GetArity(TypeIdx t)243 size_t GetArity(TypeIdx t) const 244 { 245 return Universe_[t].Arity(); 246 } 247 GetParamsIdx(TypeIdx t)248 const TypeParamsIdx &GetParamsIdx(TypeIdx t) const 249 { 250 return Universe_[t].ParamsIdx(); 251 } 252 253 friend class Type; 254 friend class TypeParams; 255 friend class ParametricType; 256 SetIncrementalRelationClosureMode(bool state)257 void SetIncrementalRelationClosureMode(bool state) 258 { 259 IncrementalSubtypingClosure_ = state; 260 } 261 SetDeferIncrementalRelationClosure(bool state)262 void SetDeferIncrementalRelationClosure(bool state) 263 { 264 DeferIncrementalSubtypingClosure_ = state; 265 } 266 267 template <typename Handler> ForAllTypes(Handler && handler)268 void ForAllTypes(Handler &&handler) const 269 { 270 for (size_t idx = 0; idx < Universe_.size(); ++idx) { 271 if (!handler(Type {kind_, idx})) { 272 return; 273 } 274 } 275 } 276 277 template <typename Handler> ForAllSubtypesOf(const Type & t,Handler && handler)278 void ForAllSubtypesOf(const Type &t, Handler &&handler) const 279 { 280 auto idx = t.Index(); 281 auto callback = [this, &handler](const TypeIdx &index) { 282 bool result = handler(Type {kind_, index}); 283 return result; 284 }; 285 TypingRel_.ForAllTo(idx, callback); 286 } 287 288 template <typename Handler> ForAllSupertypesOf(const Type & t,Handler && handler)289 void ForAllSupertypesOf(const Type &t, Handler &&handler) const 290 { 291 auto idx = t.Index(); 292 auto callback = [this, &handler](const TypeIdx &index) { 293 bool result = handler(Type {kind_, index}); 294 return result; 295 }; 296 TypingRel_.ForAllFrom(idx, callback); 297 } 298 GetDirectlyRelated(TypeIdx from)299 const IntSet<TypeIdx> &GetDirectlyRelated(TypeIdx from) const 300 { 301 return TypingRel_.GetDirectlyRelated(from); 302 } 303 GetInverselyRelated(TypeIdx to)304 const IntSet<TypeIdx> &GetInverselyRelated(TypeIdx to) const 305 { 306 return TypingRel_.GetInverselyRelated(to); 307 } 308 CloseSubtypingRelation()309 void CloseSubtypingRelation() 310 { 311 ForAllTypes([this](const Type &type) { 312 auto sort = type.Sort(); 313 auto index = type.Index(); 314 auto arity = type.Arity(); 315 SubtypingClosureCurrent_.AddType(sort, index, arity); 316 return true; 317 }); 318 PerformClosingCurrentRelation(); 319 } 320 CloseAccumulatedSubtypingRelation()321 void CloseAccumulatedSubtypingRelation() 322 { 323 if (IncrementalSubtypingClosure_) { 324 if (DeferIncrementalSubtypingClosure_) { 325 PerformClosingCurrentRelation(); 326 } 327 } else { 328 CloseSubtypingRelation(); 329 } 330 } 331 Parametric(SortIdx sort)332 ParametricType Parametric(SortIdx sort) 333 { 334 return {kind_, sort}; 335 } 336 Bot()337 Type Bot() const 338 { 339 return {kind_, BotIdx_}; 340 } 341 Top()342 Type Top() const 343 { 344 return {kind_, TopIdx_}; 345 } 346 GetKind()347 TypeSystemKind GetKind() const 348 { 349 return kind_; 350 } 351 352 TypeSystem(SortIdx bot, SortIdx top, TypeSystemKind kind = TypeSystemKind::PANDA) 353 : kind_ {kind}, BotIdx_ {FindIdxOrCreate({bot, {}})}, TopIdx_ {FindIdxOrCreate({top, {}})} 354 { 355 } 356 357 private: 358 TypeIdx BotIdx_; 359 TypeIdx TopIdx_; 360 }; 361 } // namespace panda::verifier 362 363 #endif // PANDA_VERIFICATION_TYPE_TYPE_SYSTEM_H_ 364