mirror of
https://github.com/github/codeql.git
synced 2026-02-11 20:51:06 +01:00
Merge pull request #21305 from hvitved/rust/type-inference-speedup
Rust: Speedup `inferMethodCallTypeSelf`
This commit is contained in:
@@ -2477,10 +2477,10 @@ private module MethodCallMatchingInput implements MatchingWithEnvironmentInputSi
|
||||
additional predicate decodeDerefChainBorrow(
|
||||
string derefChainBorrow, DerefChain derefChain, BorrowKind borrow
|
||||
) {
|
||||
exists(string regexp |
|
||||
regexp = "^(.*);(.*)$" and
|
||||
derefChain = derefChainBorrow.regexpCapture(regexp, 1) and
|
||||
borrow.toString() = derefChainBorrow.regexpCapture(regexp, 2)
|
||||
exists(int i |
|
||||
i = derefChainBorrow.indexOf(";") and
|
||||
derefChain = derefChainBorrow.prefix(i) and
|
||||
borrow.toString() = derefChainBorrow.suffix(i + 1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2604,27 +2604,30 @@ private Type inferMethodCallTypeNonSelf(AstNode n, boolean isReturn, TypePath pa
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of `n` at `path` after applying `derefChain` and `borrow`,
|
||||
* where `n` is the `self` argument of a method call.
|
||||
* Gets the type of `n` at `path` after applying `derefChain`, where `n` is the
|
||||
* `self` argument of a method call.
|
||||
*
|
||||
* The predicate recursively pops the head of `derefChain` until it becomes
|
||||
* empty, at which point the inferred type can be applied back to `n`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Type inferMethodCallTypeSelf(
|
||||
AstNode n, DerefChain derefChain, BorrowKind borrow, TypePath path
|
||||
) {
|
||||
exists(MethodCallMatchingInput::AccessPosition apos, string derefChainBorrow |
|
||||
result = inferMethodCallType0(_, apos, n, derefChainBorrow, path) and
|
||||
private Type inferMethodCallTypeSelf(AstNode n, DerefChain derefChain, TypePath path) {
|
||||
exists(
|
||||
MethodCallMatchingInput::AccessPosition apos, string derefChainBorrow, BorrowKind borrow,
|
||||
TypePath path0
|
||||
|
|
||||
result = inferMethodCallType0(_, apos, n, derefChainBorrow, path0) and
|
||||
apos.isSelf() and
|
||||
MethodCallMatchingInput::decodeDerefChainBorrow(derefChainBorrow, derefChain, borrow)
|
||||
)
|
||||
or
|
||||
// adjust for implicit borrow
|
||||
exists(TypePath path0, BorrowKind borrow0 |
|
||||
result = inferMethodCallTypeSelf(n, derefChain, borrow0, path0) and
|
||||
path0.isCons(borrow0.getRefType().getPositionalTypeParameter(0), path) and
|
||||
borrow.isNoBorrow()
|
||||
|
|
||||
borrow.isNoBorrow() and
|
||||
path = path0
|
||||
or
|
||||
// adjust for implicit borrow
|
||||
exists(TypePath prefix |
|
||||
prefix = TypePath::singleton(borrow.getRefType().getPositionalTypeParameter(0)) and
|
||||
path0 = prefix.appendInverse(path)
|
||||
)
|
||||
)
|
||||
or
|
||||
// adjust for implicit deref
|
||||
@@ -2632,9 +2635,8 @@ private Type inferMethodCallTypeSelf(
|
||||
DerefChain derefChain0, Type t0, TypePath path0, DerefImplItemNode impl, Type selfParamType,
|
||||
TypePath selfPath
|
||||
|
|
||||
t0 = inferMethodCallTypeSelf(n, derefChain0, borrow, path0) and
|
||||
t0 = inferMethodCallTypeSelf(n, derefChain0, path0) and
|
||||
derefChain0.isCons(impl, derefChain) and
|
||||
borrow.isNoBorrow() and
|
||||
selfParamType = impl.resolveSelfTypeAt(selfPath)
|
||||
|
|
||||
result = selfParamType and
|
||||
@@ -2653,7 +2655,7 @@ private Type inferMethodCallTypeSelf(
|
||||
private Type inferMethodCallTypePreCheck(AstNode n, boolean isReturn, TypePath path) {
|
||||
result = inferMethodCallTypeNonSelf(n, isReturn, path)
|
||||
or
|
||||
result = inferMethodCallTypeSelf(n, DerefChain::nil(), TNoBorrowKind(), path) and
|
||||
result = inferMethodCallTypeSelf(n, DerefChain::nil(), path) and
|
||||
isReturn = false
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,9 @@ module Make<LocationSig Location, InputSig<Location> Input> {
|
||||
/** Holds if this list is empty. */
|
||||
predicate isEmpty() { this = "" }
|
||||
|
||||
bindingset[this]
|
||||
private int stringLength() { result = super.length() }
|
||||
|
||||
/** Gets the length of this list. */
|
||||
bindingset[this]
|
||||
pragma[inline_late]
|
||||
@@ -115,19 +118,23 @@ module Make<LocationSig Location, InputSig<Location> Input> {
|
||||
/** Holds if this list starts with `e`, followed by `suffix`. */
|
||||
bindingset[this]
|
||||
predicate isCons(Element e, UnboundList suffix) {
|
||||
exists(string regexp | regexp = "^([0-9]+)\\.(.*)$" |
|
||||
e = decode(this.regexpCapture(regexp, 1)) and
|
||||
suffix = this.regexpCapture(regexp, 2)
|
||||
exists(string elem |
|
||||
// it is more efficient to not create a capture group for the suffix, since
|
||||
// `regexpCapture` will then always join in both groups, only to afterwards filter
|
||||
// based on the requested group (the group number is not part of the binding set
|
||||
// of `regexpCapture`)
|
||||
elem = this.regexpCapture("^([0-9]+)\\..*$", 1) and
|
||||
e = decode(elem) and
|
||||
suffix = this.suffix(elem.length() + 1)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this list starts with `prefix`, followed by `e`. */
|
||||
bindingset[this]
|
||||
predicate isSnoc(UnboundList prefix, Element e) {
|
||||
exists(string regexp | regexp = "^(|.+\\.)([0-9]+)\\.$" |
|
||||
prefix = this.regexpCapture(regexp, 1) and
|
||||
e = decode(this.regexpCapture(regexp, 2))
|
||||
)
|
||||
// same remark as above about not using multiple capture groups
|
||||
prefix = this.regexpCapture("^(|.+\\.)[0-9]+\\.$", 1) and
|
||||
e = decode(this.substring(prefix.stringLength(), this.stringLength() - 1))
|
||||
}
|
||||
|
||||
/** Gets the head of this list, if any. */
|
||||
|
||||
Reference in New Issue
Block a user