mirror of
https://github.com/github/codeql.git
synced 2026-04-22 23:35:14 +02:00
Merge pull request #19534 from hvitved/rust/type-inference-performance
Rust: Improve performance of type inference
This commit is contained in:
@@ -229,13 +229,6 @@ private predicate typeEquality(AstNode n1, TypePath path1, AstNode n2, TypePath
|
||||
path1 = path2
|
||||
)
|
||||
or
|
||||
n2 =
|
||||
any(PrefixExpr pe |
|
||||
pe.getOperatorName() = "*" and
|
||||
pe.getExpr() = n1 and
|
||||
path1 = TypePath::cons(TRefTypeParameter(), path2)
|
||||
)
|
||||
or
|
||||
n1 = n2.(ParenExpr).getExpr() and
|
||||
path1 = path2
|
||||
or
|
||||
@@ -261,12 +254,36 @@ private predicate typeEquality(AstNode n1, TypePath path1, AstNode n2, TypePath
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[path1]
|
||||
private predicate typeEqualityLeft(AstNode n1, TypePath path1, AstNode n2, TypePath path2) {
|
||||
typeEquality(n1, path1, n2, path2)
|
||||
or
|
||||
n2 =
|
||||
any(PrefixExpr pe |
|
||||
pe.getOperatorName() = "*" and
|
||||
pe.getExpr() = n1 and
|
||||
path1.isCons(TRefTypeParameter(), path2)
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[path2]
|
||||
private predicate typeEqualityRight(AstNode n1, TypePath path1, AstNode n2, TypePath path2) {
|
||||
typeEquality(n1, path1, n2, path2)
|
||||
or
|
||||
n2 =
|
||||
any(PrefixExpr pe |
|
||||
pe.getOperatorName() = "*" and
|
||||
pe.getExpr() = n1 and
|
||||
path1 = TypePath::cons(TRefTypeParameter(), path2)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferTypeEquality(AstNode n, TypePath path) {
|
||||
exists(AstNode n2, TypePath path2 | result = inferType(n2, path2) |
|
||||
typeEquality(n, path, n2, path2)
|
||||
typeEqualityRight(n, path, n2, path2)
|
||||
or
|
||||
typeEquality(n2, path2, n, path)
|
||||
typeEqualityLeft(n2, path2, n, path)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -931,7 +948,7 @@ private Type inferRefExprType(Expr e, TypePath path) {
|
||||
e = re.getExpr() and
|
||||
exists(TypePath exprPath, TypePath refPath, Type exprType |
|
||||
result = inferType(re, exprPath) and
|
||||
exprPath = TypePath::cons(TRefTypeParameter(), refPath) and
|
||||
exprPath.isCons(TRefTypeParameter(), refPath) and
|
||||
exprType = inferType(e)
|
||||
|
|
||||
if exprType = TRefType()
|
||||
@@ -945,8 +962,9 @@ private Type inferRefExprType(Expr e, TypePath path) {
|
||||
|
||||
pragma[nomagic]
|
||||
private Type inferTryExprType(TryExpr te, TypePath path) {
|
||||
exists(TypeParam tp |
|
||||
result = inferType(te.getExpr(), TypePath::cons(TTypeParamTypeParameter(tp), path))
|
||||
exists(TypeParam tp, TypePath path0 |
|
||||
result = inferType(te.getExpr(), path0) and
|
||||
path0.isCons(TTypeParamTypeParameter(tp), path)
|
||||
|
|
||||
tp = any(ResultEnum r).getGenericParamList().getGenericParam(0)
|
||||
or
|
||||
@@ -1020,7 +1038,7 @@ private module Cached {
|
||||
pragma[nomagic]
|
||||
Type getTypeAt(TypePath path) {
|
||||
exists(TypePath path0 | result = inferType(this, path0) |
|
||||
path0 = TypePath::cons(TRefTypeParameter(), path)
|
||||
path0.isCons(TRefTypeParameter(), path)
|
||||
or
|
||||
not path0.isCons(TRefTypeParameter(), _) and
|
||||
not (path0.isEmpty() and result = TRefType()) and
|
||||
|
||||
@@ -181,18 +181,29 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
/** Holds if this type path is empty. */
|
||||
predicate isEmpty() { this = "" }
|
||||
|
||||
/** Gets the length of this path, assuming the length is at least 2. */
|
||||
bindingset[this]
|
||||
pragma[inline_late]
|
||||
private int lengthAtLeast2() {
|
||||
// Same as
|
||||
// `result = strictcount(this.indexOf(".")) + 1`
|
||||
// but performs better because it doesn't use an aggregate
|
||||
result = this.regexpReplaceAll("[0-9]+", "").length() + 1
|
||||
}
|
||||
|
||||
/** Gets the length of this path. */
|
||||
bindingset[this]
|
||||
pragma[inline_late]
|
||||
int length() {
|
||||
this.isEmpty() and result = 0
|
||||
or
|
||||
result = strictcount(this.indexOf(".")) + 1
|
||||
if this.isEmpty()
|
||||
then result = 0
|
||||
else
|
||||
if exists(TypeParameter::decode(this))
|
||||
then result = 1
|
||||
else result = this.lengthAtLeast2()
|
||||
}
|
||||
|
||||
/** Gets the path obtained by appending `suffix` onto this path. */
|
||||
bindingset[suffix, result]
|
||||
bindingset[this, result]
|
||||
bindingset[this, suffix]
|
||||
TypePath append(TypePath suffix) {
|
||||
if this.isEmpty()
|
||||
@@ -202,21 +213,40 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
then result = this
|
||||
else (
|
||||
result = this + "." + suffix and
|
||||
not result.length() > getTypePathLimit()
|
||||
(
|
||||
not exists(getTypePathLimit())
|
||||
or
|
||||
result.lengthAtLeast2() <= getTypePathLimit()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path obtained by appending `suffix` onto this path.
|
||||
*
|
||||
* Unlike `append`, this predicate has `result` in the binding set,
|
||||
* so there is no need to check the length of `result`.
|
||||
*/
|
||||
bindingset[this, result]
|
||||
TypePath appendInverse(TypePath suffix) { suffix = result.stripPrefix(this) }
|
||||
|
||||
/** Gets the path obtained by removing `prefix` from this path. */
|
||||
bindingset[this, prefix]
|
||||
TypePath stripPrefix(TypePath prefix) {
|
||||
if prefix.isEmpty()
|
||||
then result = this
|
||||
else (
|
||||
this = prefix and
|
||||
result.isEmpty()
|
||||
or
|
||||
this = prefix + "." + result
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this path starts with `tp`, followed by `suffix`. */
|
||||
bindingset[this]
|
||||
predicate isCons(TypeParameter tp, TypePath suffix) {
|
||||
tp = TypeParameter::decode(this) and
|
||||
suffix.isEmpty()
|
||||
or
|
||||
exists(int first |
|
||||
first = min(this.indexOf(".")) and
|
||||
suffix = this.suffix(first + 1) and
|
||||
tp = TypeParameter::decode(this.prefix(first))
|
||||
)
|
||||
suffix = this.stripPrefix(TypePath::singleton(tp))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +262,6 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
* Gets the type path obtained by appending the singleton type path `tp`
|
||||
* onto `suffix`.
|
||||
*/
|
||||
bindingset[result]
|
||||
bindingset[suffix]
|
||||
TypePath cons(TypeParameter tp, TypePath suffix) { result = singleton(tp).append(suffix) }
|
||||
}
|
||||
@@ -556,7 +585,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
TypeMention tm1, TypeMention tm2, TypeParameter tp, TypePath path, Type t
|
||||
) {
|
||||
exists(TypePath prefix |
|
||||
tm2.resolveTypeAt(prefix) = tp and t = tm1.resolveTypeAt(prefix.append(path))
|
||||
tm2.resolveTypeAt(prefix) = tp and t = tm1.resolveTypeAt(prefix.appendInverse(path))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -899,7 +928,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
exists(AccessPosition apos, DeclarationPosition dpos, TypePath pathToTypeParam |
|
||||
tp = target.getDeclaredType(dpos, pathToTypeParam) and
|
||||
accessDeclarationPositionMatch(apos, dpos) and
|
||||
adjustedAccessType(a, apos, target, pathToTypeParam.append(path), t)
|
||||
adjustedAccessType(a, apos, target, pathToTypeParam.appendInverse(path), t)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -998,7 +1027,9 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
|
||||
RelevantAccess() { this = MkRelevantAccess(a, apos, path) }
|
||||
|
||||
Type getTypeAt(TypePath suffix) { a.getInferredType(apos, path.append(suffix)) = result }
|
||||
Type getTypeAt(TypePath suffix) {
|
||||
a.getInferredType(apos, path.appendInverse(suffix)) = result
|
||||
}
|
||||
|
||||
/** Holds if this relevant access has the type `type` and should satisfy `constraint`. */
|
||||
predicate hasTypeConstraint(Type type, Type constraint) {
|
||||
@@ -1077,7 +1108,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
t0 = abs.getATypeParameter() and
|
||||
exists(TypePath path3, TypePath suffix |
|
||||
sub.resolveTypeAt(path3) = t0 and
|
||||
at.getTypeAt(path3.append(suffix)) = t and
|
||||
at.getTypeAt(path3.appendInverse(suffix)) = t and
|
||||
path = prefix0.append(suffix)
|
||||
)
|
||||
)
|
||||
@@ -1149,7 +1180,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
not exists(getTypeArgument(a, target, tp, _)) and
|
||||
target = a.getTarget() and
|
||||
exists(AccessPosition apos, DeclarationPosition dpos, Type base, TypePath pathToTypeParam |
|
||||
accessBaseType(a, apos, base, pathToTypeParam.append(path), t) and
|
||||
accessBaseType(a, apos, base, pathToTypeParam.appendInverse(path), t) and
|
||||
declarationBaseType(target, dpos, base, pathToTypeParam, tp) and
|
||||
accessDeclarationPositionMatch(apos, dpos)
|
||||
)
|
||||
@@ -1217,7 +1248,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
|
||||
typeParameterConstraintHasTypeParameter(target, dpos, pathToTp2, _, constraint, pathToTp,
|
||||
tp) and
|
||||
AccessConstraint::satisfiesConstraintTypeMention(a, apos, pathToTp2, constraint,
|
||||
pathToTp.append(path), t)
|
||||
pathToTp.appendInverse(path), t)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user