@@ -181,18 +181,29 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
181
181
/** Holds if this type path is empty. */
182
182
predicate isEmpty ( ) { this = "" }
183
183
184
+ /** Gets the length of this path, assuming the length is at least 2. */
185
+ bindingset [ this ]
186
+ pragma [ inline_late]
187
+ private int lengthAtLeast2 ( ) {
188
+ // Same as
189
+ // `result = strictcount(this.indexOf(".")) + 1`
190
+ // but performs better because it doesn't use an aggregate
191
+ result = this .regexpReplaceAll ( "[0-9]+" , "" ) .length ( ) + 1
192
+ }
193
+
184
194
/** Gets the length of this path. */
185
195
bindingset [ this ]
186
196
pragma [ inline_late]
187
197
int length ( ) {
188
- this .isEmpty ( ) and result = 0
189
- or
190
- result = strictcount ( this .indexOf ( "." ) ) + 1
198
+ if this .isEmpty ( )
199
+ then result = 0
200
+ else
201
+ if exists ( TypeParameter:: decode ( this ) )
202
+ then result = 1
203
+ else result = this .lengthAtLeast2 ( )
191
204
}
192
205
193
206
/** Gets the path obtained by appending `suffix` onto this path. */
194
- bindingset [ suffix, result ]
195
- bindingset [ this , result ]
196
207
bindingset [ this , suffix]
197
208
TypePath append ( TypePath suffix ) {
198
209
if this .isEmpty ( )
@@ -202,21 +213,40 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
202
213
then result = this
203
214
else (
204
215
result = this + "." + suffix and
205
- not result .length ( ) > getTypePathLimit ( )
216
+ (
217
+ not exists ( getTypePathLimit ( ) )
218
+ or
219
+ result .lengthAtLeast2 ( ) <= getTypePathLimit ( )
220
+ )
206
221
)
207
222
}
208
223
224
+ /**
225
+ * Gets the path obtained by appending `suffix` onto this path.
226
+ *
227
+ * Unlike `append`, this predicate has `result` in the binding set,
228
+ * so there is no need to check the length of `result`.
229
+ */
230
+ bindingset [ this , result ]
231
+ TypePath appendInverse ( TypePath suffix ) { suffix = result .stripPrefix ( this ) }
232
+
233
+ /** Gets the path obtained by removing `prefix` from this path. */
234
+ bindingset [ this , prefix]
235
+ TypePath stripPrefix ( TypePath prefix ) {
236
+ if prefix .isEmpty ( )
237
+ then result = this
238
+ else (
239
+ this = prefix and
240
+ result .isEmpty ( )
241
+ or
242
+ this = prefix + "." + result
243
+ )
244
+ }
245
+
209
246
/** Holds if this path starts with `tp`, followed by `suffix`. */
210
247
bindingset [ this ]
211
248
predicate isCons ( TypeParameter tp , TypePath suffix ) {
212
- tp = TypeParameter:: decode ( this ) and
213
- suffix .isEmpty ( )
214
- or
215
- exists ( int first |
216
- first = min ( this .indexOf ( "." ) ) and
217
- suffix = this .suffix ( first + 1 ) and
218
- tp = TypeParameter:: decode ( this .prefix ( first ) )
219
- )
249
+ suffix = this .stripPrefix ( TypePath:: singleton ( tp ) )
220
250
}
221
251
}
222
252
@@ -232,7 +262,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
232
262
* Gets the type path obtained by appending the singleton type path `tp`
233
263
* onto `suffix`.
234
264
*/
235
- bindingset [ result ]
236
265
bindingset [ suffix]
237
266
TypePath cons ( TypeParameter tp , TypePath suffix ) { result = singleton ( tp ) .append ( suffix ) }
238
267
}
@@ -556,7 +585,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
556
585
TypeMention tm1 , TypeMention tm2 , TypeParameter tp , TypePath path , Type t
557
586
) {
558
587
exists ( TypePath prefix |
559
- tm2 .resolveTypeAt ( prefix ) = tp and t = tm1 .resolveTypeAt ( prefix .append ( path ) )
588
+ tm2 .resolveTypeAt ( prefix ) = tp and t = tm1 .resolveTypeAt ( prefix .appendInverse ( path ) )
560
589
)
561
590
}
562
591
@@ -899,7 +928,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
899
928
exists ( AccessPosition apos , DeclarationPosition dpos , TypePath pathToTypeParam |
900
929
tp = target .getDeclaredType ( dpos , pathToTypeParam ) and
901
930
accessDeclarationPositionMatch ( apos , dpos ) and
902
- adjustedAccessType ( a , apos , target , pathToTypeParam .append ( path ) , t )
931
+ adjustedAccessType ( a , apos , target , pathToTypeParam .appendInverse ( path ) , t )
903
932
)
904
933
}
905
934
@@ -998,7 +1027,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
998
1027
999
1028
RelevantAccess ( ) { this = MkRelevantAccess ( a , apos , path ) }
1000
1029
1001
- Type getTypeAt ( TypePath suffix ) { a .getInferredType ( apos , path .append ( suffix ) ) = result }
1030
+ Type getTypeAt ( TypePath suffix ) {
1031
+ a .getInferredType ( apos , path .appendInverse ( suffix ) ) = result
1032
+ }
1002
1033
1003
1034
/** Holds if this relevant access has the type `type` and should satisfy `constraint`. */
1004
1035
predicate hasTypeConstraint ( Type type , Type constraint ) {
@@ -1077,7 +1108,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1077
1108
t0 = abs .getATypeParameter ( ) and
1078
1109
exists ( TypePath path3 , TypePath suffix |
1079
1110
sub .resolveTypeAt ( path3 ) = t0 and
1080
- at .getTypeAt ( path3 .append ( suffix ) ) = t and
1111
+ at .getTypeAt ( path3 .appendInverse ( suffix ) ) = t and
1081
1112
path = prefix0 .append ( suffix )
1082
1113
)
1083
1114
)
@@ -1149,7 +1180,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1149
1180
not exists ( getTypeArgument ( a , target , tp , _) ) and
1150
1181
target = a .getTarget ( ) and
1151
1182
exists ( AccessPosition apos , DeclarationPosition dpos , Type base , TypePath pathToTypeParam |
1152
- accessBaseType ( a , apos , base , pathToTypeParam .append ( path ) , t ) and
1183
+ accessBaseType ( a , apos , base , pathToTypeParam .appendInverse ( path ) , t ) and
1153
1184
declarationBaseType ( target , dpos , base , pathToTypeParam , tp ) and
1154
1185
accessDeclarationPositionMatch ( apos , dpos )
1155
1186
)
@@ -1217,7 +1248,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
1217
1248
typeParameterConstraintHasTypeParameter ( target , dpos , pathToTp2 , _, constraint , pathToTp ,
1218
1249
tp ) and
1219
1250
AccessConstraint:: satisfiesConstraintTypeMention ( a , apos , pathToTp2 , constraint ,
1220
- pathToTp .append ( path ) , t )
1251
+ pathToTp .appendInverse ( path ) , t )
1221
1252
)
1222
1253
}
1223
1254
0 commit comments