|
| 1 | +/** Provides classes representing types without type arguments. */ |
| 2 | + |
| 3 | +import swift |
| 4 | +private import swift as Swift |
| 5 | +private import codeql.swift.generated.Raw |
| 6 | +private import codeql.swift.generated.Synth |
| 7 | + |
| 8 | +cached |
| 9 | +newtype TType = |
| 10 | + TTypeDeclType(TypeDecl decl) { |
| 11 | + not decl instanceof AssociatedTypeDecl and |
| 12 | + // handled in `TSelfTypeParameter` |
| 13 | + not decl = any(GenericTypeParamDecl g | decl.getName() = "Self") |
| 14 | + } or |
| 15 | + TTupleType(int arity) { arity = [0 .. any(Swift::TupleType tt).getNumberOfTypes()] } or |
| 16 | + TAssociatedTypeTypeParameter(ProtocolDecl protocol, AssociatedTypeDecl associatedType) { |
| 17 | + associatedType.getDeclaringDecl().(ProtocolDecl).getABaseTypeDecl*() = protocol |
| 18 | + } or |
| 19 | + TSelfTypeParameter(ProtocolDecl protocol) or |
| 20 | + TTupleTypeTypeParameter(int arity, int index) { |
| 21 | + arity = [0 .. any(Swift::TupleType tt).getNumberOfTypes()] and |
| 22 | + index = [0 .. arity - 1] |
| 23 | + } or |
| 24 | + TUnknownType() |
| 25 | + |
| 26 | +/** |
| 27 | + * A type without type arguments. |
| 28 | + * |
| 29 | + * Note that this type includes things that, strictly speaking, are not Rust |
| 30 | + * types, such as traits and implementation blocks. |
| 31 | + */ |
| 32 | +abstract class Type extends TType { |
| 33 | + /** |
| 34 | + * Gets the `i`th positional type parameter of this type, if any. |
| 35 | + * |
| 36 | + * This excludes synthetic type parameters, such as associated types in traits. |
| 37 | + */ |
| 38 | + abstract TypeParameter getPositionalTypeParameter(int i); |
| 39 | + |
| 40 | + /** Gets the default type for the `i`th type parameter, if any. */ |
| 41 | + TypeRepr getTypeParameterDefault(int i) { none() } |
| 42 | + |
| 43 | + /** |
| 44 | + * Gets a type parameter of this type. |
| 45 | + * |
| 46 | + * This includes both positional type parameters and synthetic type parameters, |
| 47 | + * such as associated types in traits. |
| 48 | + */ |
| 49 | + TypeParameter getATypeParameter() { result = this.getPositionalTypeParameter(_) } |
| 50 | + |
| 51 | + /** Gets a textual representation of this type. */ |
| 52 | + abstract string toString(); |
| 53 | + |
| 54 | + /** Gets the location of this type. */ |
| 55 | + abstract Location getLocation(); |
| 56 | +} |
| 57 | + |
| 58 | +class TypeDeclType extends Type, TTypeDeclType { |
| 59 | + TypeDecl decl; |
| 60 | + |
| 61 | + TypeDeclType() { this = TTypeDeclType(decl) } |
| 62 | + |
| 63 | + /** Gets the type item that this data type represents. */ |
| 64 | + TypeDecl getDecl() { result = decl } |
| 65 | + |
| 66 | + override TypeParameter getPositionalTypeParameter(int i) { |
| 67 | + result = TTypeDeclType(decl.(GenericTypeDecl).getGenericTypeParam(i)) |
| 68 | + } |
| 69 | + |
| 70 | + override TypeParameter getATypeParameter() { |
| 71 | + result = super.getATypeParameter() |
| 72 | + or |
| 73 | + result = TAssociatedTypeTypeParameter(decl, _) |
| 74 | + } |
| 75 | + |
| 76 | + override TypeRepr getTypeParameterDefault(int i) { |
| 77 | + // todo: it appears Swift does support this |
| 78 | + none() |
| 79 | + } |
| 80 | + |
| 81 | + override string toString() { result = decl.getName() } |
| 82 | + |
| 83 | + override Location getLocation() { result = decl.getLocation() } |
| 84 | +} |
| 85 | + |
| 86 | +class StringType extends TypeDeclType { |
| 87 | + StringType() { decl.getName() = "String" } |
| 88 | +} |
| 89 | + |
| 90 | +class IntType extends TypeDeclType { |
| 91 | + IntType() { decl.getName() = "Int" } |
| 92 | +} |
| 93 | + |
| 94 | +class TupleType extends Type, TTupleType { |
| 95 | + int arity; |
| 96 | + |
| 97 | + TupleType() { this = TTupleType(arity) } |
| 98 | + |
| 99 | + override TypeParameter getPositionalTypeParameter(int i) { |
| 100 | + result = TTupleTypeTypeParameter(arity, i) |
| 101 | + } |
| 102 | + |
| 103 | + override string toString() { result = "(T_" + arity + ")" } |
| 104 | + |
| 105 | + override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) } |
| 106 | +} |
| 107 | + |
| 108 | +class VoidType extends TupleType { |
| 109 | + VoidType() { arity = 0 } |
| 110 | +} |
| 111 | + |
| 112 | +/** A type parameter. */ |
| 113 | +abstract class TypeParameter extends Type { |
| 114 | + override TypeParameter getPositionalTypeParameter(int i) { none() } |
| 115 | +} |
| 116 | + |
| 117 | +class GenericTypeParamDeclTypeParameter extends TypeParameter, TypeDeclType { |
| 118 | + override GenericTypeParamDecl decl; |
| 119 | + |
| 120 | + override TypeParameter getPositionalTypeParameter(int i) { |
| 121 | + result = TypeParameter.super.getPositionalTypeParameter(i) |
| 122 | + } |
| 123 | +} |
| 124 | + |
| 125 | +/** |
| 126 | + * A type parameter corresponding to an associated type in a protocol. |
| 127 | + * |
| 128 | + * We treat associated type declarations in protocols as type parameters. E.g., a |
| 129 | + * protocol such as |
| 130 | + * |
| 131 | + * ```swift |
| 132 | + * protocol Protocol { |
| 133 | + * associatedtype AssociatedType |
| 134 | + * // ... |
| 135 | + * } |
| 136 | + * ``` |
| 137 | + * |
| 138 | + * is treated as if it was |
| 139 | + * |
| 140 | + * ```swift |
| 141 | + * protocol Protocol<AssociatedType> { |
| 142 | + * // ... |
| 143 | + * } |
| 144 | + * ``` |
| 145 | + * |
| 146 | + * Furthermore, associated types of a super protocol induce a corresponding type |
| 147 | + * parameter in any subprotocols. E.g., if we have a protocol `SubProtocol: AProtocol` then |
| 148 | + * `SubProtocol` also has a type parameter for the associated type |
| 149 | + * `AssociatedType`. |
| 150 | + */ |
| 151 | +class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypeParameter { |
| 152 | + ProtocolDecl protocol; |
| 153 | + AssociatedTypeDecl associatedType; |
| 154 | + |
| 155 | + AssociatedTypeTypeParameter() { this = TAssociatedTypeTypeParameter(protocol, associatedType) } |
| 156 | + |
| 157 | + AssociatedTypeDecl getAssociatedType() { result = associatedType } |
| 158 | + |
| 159 | + /** Gets the protocol that contains this associated type declaration. */ |
| 160 | + ProtocolDecl getProtocol() { result = protocol } |
| 161 | + |
| 162 | + /** |
| 163 | + * Holds if this associated type type parameter corresponds directly its |
| 164 | + * protocol, that is, it is not inherited from a superprotocol. |
| 165 | + */ |
| 166 | + predicate isDirect() { protocol = associatedType.getDeclaringDecl() } |
| 167 | + |
| 168 | + override string toString() { |
| 169 | + exists(string fromString, ProtocolDecl protocol2 | |
| 170 | + result = associatedType.getName() + "[" + protocol.getName() + fromString + "]" and |
| 171 | + protocol2 = associatedType.getDeclaringDecl() and |
| 172 | + if protocol = protocol2 |
| 173 | + then fromString = "" |
| 174 | + else fromString = " (inherited from " + protocol2.getName() + ")" |
| 175 | + ) |
| 176 | + } |
| 177 | + |
| 178 | + override Location getLocation() { result = associatedType.getLocation() } |
| 179 | + |
| 180 | + override TypeParameter getPositionalTypeParameter(int i) { |
| 181 | + // todo: it appears that associated types can also have type parameters |
| 182 | + result = TypeParameter.super.getPositionalTypeParameter(i) |
| 183 | + } |
| 184 | +} |
| 185 | + |
| 186 | +/** |
| 187 | + * The implicit `Self` type parameter of a protocol, that refers to the |
| 188 | + * implementing type of the protocol. |
| 189 | + */ |
| 190 | +class SelfTypeParameter extends TypeParameter, TSelfTypeParameter { |
| 191 | + private ProtocolDecl protocol; |
| 192 | + |
| 193 | + SelfTypeParameter() { this = TSelfTypeParameter(protocol) } |
| 194 | + |
| 195 | + ProtocolDecl getProtocol() { result = protocol } |
| 196 | + |
| 197 | + override string toString() { result = "Self [" + protocol.getName() + "]" } |
| 198 | + |
| 199 | + override Location getLocation() { result = protocol.getLocation() } |
| 200 | +} |
| 201 | + |
| 202 | +class TupleTypeTypeParameter extends TypeParameter, TTupleTypeTypeParameter { |
| 203 | + int arity; |
| 204 | + int index; |
| 205 | + |
| 206 | + TupleTypeTypeParameter() { this = TTupleTypeTypeParameter(arity, index) } |
| 207 | + |
| 208 | + override string toString() { result = "element " + index + " of tuple of arity " + arity } |
| 209 | + |
| 210 | + override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) } |
| 211 | +} |
| 212 | + |
| 213 | +/** |
| 214 | + * A special pseudo type used to indicate that the actual type may have to be |
| 215 | + * inferred by propagating type information back into call arguments. |
| 216 | + * |
| 217 | + * For example, in |
| 218 | + * |
| 219 | + * ```rust |
| 220 | + * let x = Default::default(); |
| 221 | + * foo(x); |
| 222 | + * ``` |
| 223 | + * |
| 224 | + * `Default::default()` is assigned this type, which allows us to infer the actual |
| 225 | + * type from the type of `foo`'s first parameter. |
| 226 | + * |
| 227 | + * Unknown types are not restricted to root types, for example in a call like |
| 228 | + * `Vec::new()` we assign this type at the type path corresponding to the type |
| 229 | + * parameter of `Vec`. |
| 230 | + * |
| 231 | + * Unknown types are used to restrict when type information is allowed to flow |
| 232 | + * into call arguments (including method call receivers), in order to avoid |
| 233 | + * combinatorial explosions. |
| 234 | + */ |
| 235 | +class UnknownType extends Type, TUnknownType { |
| 236 | + override TypeParameter getPositionalTypeParameter(int i) { none() } |
| 237 | + |
| 238 | + override string toString() { result = "(context typed)" } |
| 239 | + |
| 240 | + override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) } |
| 241 | +} |
| 242 | + |
| 243 | +private class RawTypeParameter = |
| 244 | + @generic_type_param_decl or @associated_type_decl or @protocol_decl; |
| 245 | + |
| 246 | +private predicate id(RawTypeParameter x, RawTypeParameter y) { x = y } |
| 247 | + |
| 248 | +private predicate idOfRaw(RawTypeParameter x, int y) = equivalenceRelation(id/2)(x, y) |
| 249 | + |
| 250 | +int idOfTypeParameterAstNode(AstNode node) { idOfRaw(Synth::convertAstNodeToRaw(node), result) } |
0 commit comments