Merge branch 'main' into redsun82/cargo-upgrade-2

This commit is contained in:
Paolo Tranquilli
2025-08-19 12:25:49 +02:00
9 changed files with 313 additions and 254 deletions

View File

@@ -120,9 +120,7 @@ module Stages {
or
exists(resolvePath(_))
or
exists(any(ItemNode i).getASuccessor(_))
or
exists(any(ItemNode i).getASuccessorRec(_))
exists(any(ItemNode i).getASuccessor(_, _))
or
exists(any(ImplOrTraitItemNode i).getASelfPath())
or

View File

@@ -32,24 +32,102 @@ final class Namespace extends TNamespace {
}
}
private newtype TSuccessorKind =
TInternal() or
TExternal() or
TBoth()
/** A successor kind. */
class SuccessorKind extends TSuccessorKind {
predicate isInternal() { this = TInternal() }
predicate isExternal() { this = TExternal() }
predicate isBoth() { this = TBoth() }
predicate isInternalOrBoth() { this.isInternal() or this.isBoth() }
predicate isExternalOrBoth() { this.isExternal() or this.isBoth() }
string toString() {
this.isInternal() and result = "internal"
or
this.isExternal() and result = "external"
or
this.isBoth() and result = "both"
}
}
pragma[nomagic]
private ItemNode getAChildSuccessor(ItemNode item, string name, SuccessorKind kind) {
item = result.getImmediateParent() and
name = result.getName() and
(
// type parameters are only available inside the declaring item
if result instanceof TypeParam
then kind.isInternal()
else
// associated items must always be qualified, also within the declaring
// item (using `Self`)
if item instanceof ImplOrTraitItemNode and result instanceof AssocItem
then kind.isExternal()
else
if result instanceof Use
then kind.isInternal()
else kind.isBoth()
)
}
/**
* An item that may be referred to by a path, and which is a node in
* the _item graph_.
*
* The item graph is a labeled directed graph, where an edge
* `item1 --name--> item2` means that `item2` is available inside the
* scope of `item1` under the name `name`. For example, if we have
*
* ```
* item1 --name,kind--> item2
* ```
*
* means that:
*
* - `item2` is available _inside_ the scope of `item1` under the name `name`,
* when `kind` is either `internal` or `both`, and
*
* - `item2` is available _externally_ from `item1` under the name `name`, when
* `kind` is either `external` or `both`.
*
* For example, if we have
*
* ```rust
* mod m1 {
* mod m2 { }
* pub mod m1 {
* pub mod m2 { }
* }
* ```
*
* then there is an edge `m1 --m2--> m1::m2`.
* then there is an edge `mod m1 --m2,both--> mod m2`.
*
* Associated items are example of externally visible items (inside the
* declaring item they must be `Self` prefixed), while type parameters are
* examples of internally visible items. For example, for
*
* ```rust
* mod m {
* pub trait<T> Trait {
* fn foo(&self) -> T;
* }
* }
* ```
*
* we have the following edges
*
* ```
* mod m --Trait,both--> trait Trait
* trait Trait --foo,external --> fn foo
* trait Trait --T,internal --> T
* ```
*
* Source files are also considered nodes in the item graph, and for
* each source file `f` there is an edge `f --name--> item` when `f`
* each source file `f` there is an edge `f --name,both--> item` when `f`
* declares `item` with the name `name`.
*
* For imports like
@@ -61,11 +139,13 @@ final class Namespace extends TNamespace {
* }
* ```
*
* we first generate an edge `m1::m2 --name--> f::item`, where `item` is
* any item (named `name`) inside the imported source file `f`. Using this
* edge, `m2::foo` can resolve to `f::foo`, which results in the edge
* `m1::use m2 --foo--> f::foo`. Lastly, all edges out of `use` nodes are
* lifted to predecessors in the graph, so we get an edge `m1 --foo--> f::foo`.
* we first generate an edge `mod m2 --name,kind--> f::item`, where `item` is
* any item (named `name`) inside the imported source file `f`, and `kind` is
* either `external` or `both`. Using this edge, `m2::foo` can resolve to
* `f::foo`, which results in the edge `use m2 --foo,internal--> f::foo`
* (would have been `external` if it was `pub use m2::foo`). Lastly, all edges
* out of `use` nodes are lifted to predecessors in the graph, so we get
* an edge `mod m1 --foo,internal--> f::foo`.
*
*
* References:
@@ -112,42 +192,40 @@ abstract class ItemNode extends Locatable {
result = this.(SourceFileItemNode).getSuper()
}
pragma[nomagic]
private ItemNode getAChildSuccessor(string name) {
this = result.getImmediateParent() and
name = result.getName()
}
/** Gets a successor named `name` of the given `kind`, if any. */
cached
ItemNode getASuccessorRec(string name) {
ItemNode getASuccessor(string name, SuccessorKind kind) {
Stages::PathResolutionStage::ref() and
sourceFileEdge(this, name, result)
sourceFileEdge(this, name, result) and
kind.isBoth()
or
result = this.getAChildSuccessor(name)
result = getAChildSuccessor(this, name, kind)
or
fileImportEdge(this, name, result)
fileImportEdge(this, name, result, kind)
or
useImportEdge(this, name, result)
useImportEdge(this, name, result, kind)
or
crateDefEdge(this, name, result)
crateDefEdge(this, name, result, kind)
or
crateDependencyEdge(this, name, result)
crateDependencyEdge(this, name, result) and
kind.isInternal()
or
externCrateEdge(this, name, result)
externCrateEdge(this, name, result) and
kind.isInternal()
or
// items made available through `use` are available to nodes that contain the `use`
exists(UseItemNode use |
use = this.getASuccessorRec(_) and
result = use.(ItemNode).getASuccessorRec(name)
use = this.getASuccessor(_, _) and
result = use.(ItemNode).getASuccessor(name, kind)
)
or
exists(ExternCrateItemNode ec | result = ec.(ItemNode).getASuccessorRec(name) |
ec = this.getASuccessorRec(_)
exists(ExternCrateItemNode ec | result = ec.(ItemNode).getASuccessor(name, kind) |
ec = this.getASuccessor(_, _)
or
// if the extern crate appears in the crate root, then the crate name is also added
// to the 'extern prelude', see https://doc.rust-lang.org/reference/items/extern-crates.html
exists(Crate c |
ec = c.getSourceFile().(ItemNode).getASuccessorRec(_) and
ec = c.getSourceFile().(ItemNode).getASuccessor(_, _) and
this = c.getASourceFile()
)
)
@@ -155,7 +233,8 @@ abstract class ItemNode extends Locatable {
// a trait has access to the associated items of its supertraits
this =
any(TraitItemNode trait |
result = trait.resolveABound().getASuccessorRec(name) and
result = trait.resolveABound().getASuccessor(name, kind) and
kind.isExternalOrBoth() and
result instanceof AssocItemNode and
not trait.hasAssocItem(name)
)
@@ -163,50 +242,39 @@ abstract class ItemNode extends Locatable {
// items made available by an implementation where `this` is the implementing type
exists(ItemNode node |
this = node.(ImplItemNode).resolveSelfTy() and
result = node.getASuccessorRec(name) and
result instanceof AssocItemNode and
not result instanceof TypeAlias
result = node.getASuccessor(name, kind) and
kind.isExternalOrBoth() and
result instanceof AssocItemNode
)
or
// trait items with default implementations made available in an implementation
exists(ImplItemNode impl, ItemNode trait |
this = impl and
trait = impl.resolveTraitTy() and
result = trait.getASuccessorRec(name) and
result = trait.getASuccessor(name, kind) and
result.(AssocItemNode).hasImplementation() and
kind.isExternalOrBoth() and
not impl.hasAssocItem(name)
)
or
// type parameters have access to the associated items of its bounds
result = this.(TypeParamItemNode).resolveABound().getASuccessorRec(name).(AssocItemNode)
result = this.(TypeParamItemNode).resolveABound().getASuccessor(name, kind).(AssocItemNode) and
kind.isExternalOrBoth()
or
result = this.(ImplTraitTypeReprItemNode).resolveABound().getASuccessorRec(name).(AssocItemNode)
result =
this.(ImplTraitTypeReprItemNode).resolveABound().getASuccessor(name, kind).(AssocItemNode) and
kind.isExternalOrBoth()
or
result = this.(TypeAliasItemNode).resolveAlias().getASuccessorRec(name) and
// type parameters defined in the RHS are not available in the LHS
not result instanceof TypeParam
}
/**
* Gets a successor named `name` of this item, if any.
*
* Whenever a function exists in both source code and in library code,
* both are included
*/
cached
ItemNode getASuccessor(string name) {
Stages::PathResolutionStage::ref() and
result = this.getASuccessorRec(name)
or
preludeEdge(this, name, result)
or
this instanceof SourceFile and
builtin(name, result)
result = this.(TypeAliasItemNode).resolveAlias().getASuccessor(name, kind) and
kind.isExternalOrBoth()
or
name = "super" and
if this instanceof Module or this instanceof SourceFile
then result = this.getImmediateParentModule()
else result = this.getImmediateParentModule().getImmediateParentModule()
then (
kind.isBoth() and result = this.getImmediateParentModule()
) else (
kind.isInternal() and result = this.getImmediateParentModule().getImmediateParentModule()
)
or
name = "self" and
if
@@ -214,51 +282,40 @@ abstract class ItemNode extends Locatable {
this instanceof Enum or
this instanceof Struct or
this instanceof Crate
then result = this
else result = this.getImmediateParentModule()
then (
kind.isBoth() and
result = this
) else (
kind.isInternal() and
result = this.getImmediateParentModule()
)
or
name = "Self" and
this = result.(ImplOrTraitItemNode).getAnItemInSelfScope()
or
name = "crate" and
this = result.(CrateItemNode).getASourceFile()
or
// todo: implement properly
name = "$crate" and
result = any(CrateItemNode crate | this = crate.getASourceFile()).(Crate).getADependency*() and
result.(CrateItemNode).isPotentialDollarCrateTarget()
kind.isInternal() and
(
preludeEdge(this, name, result)
or
this instanceof SourceFile and
builtin(name, result)
or
name = "Self" and
this = result.(ImplOrTraitItemNode).getAnItemInSelfScope()
or
name = "crate" and
this = result.(CrateItemNode).getASourceFile()
or
// todo: implement properly
name = "$crate" and
result = any(CrateItemNode crate | this = crate.getASourceFile()).(Crate).getADependency*() and
result.(CrateItemNode).isPotentialDollarCrateTarget()
)
}
/**
* Holds if the successor `item` with the name `name` is not available locally
* for unqualified paths.
*
* This has the effect that a path of the form `name` inside `this` will not
* resolve to `item`.
*/
pragma[nomagic]
predicate excludedLocally(string name, ItemNode item) {
// Associated items in an impl or trait block are not directly available
// inside the block, they require a qualified path with a `Self` prefix.
item = this.getAChildSuccessor(name) and
this instanceof ImplOrTraitItemNode and
item instanceof AssocItemNode
}
/**
* Holds if the successor `item` with the name `name` is not available
* externally for qualified paths that resolve to this item.
*
* This has the effect that a path of the form `Qualifier::name`, where
* `Qualifier` resolves to this item, will not resolve to `item`.
*/
pragma[nomagic]
predicate excludedExternally(string name, ItemNode item) {
// Type parameters for an `impl` or trait block are not available outside of
// the block.
item = this.getAChildSuccessor(name) and
this instanceof ImplOrTraitItemNode and
item instanceof TypeParamItemNode
/** Gets an _external_ successor named `name`, if any. */
ItemNode getASuccessor(string name) {
exists(SuccessorKind kind |
result = this.getASuccessor(name, kind) and
kind.isExternalOrBoth()
)
}
/** Holds if this item has a canonical path belonging to the crate `c`. */
@@ -552,7 +609,7 @@ abstract class ImplOrTraitItemNode extends ItemNode {
Path getASelfPath() {
Stages::PathResolutionStage::ref() and
isUnqualifiedSelfPath(result) and
this = unqualifiedPathLookup(result, _)
this = unqualifiedPathLookup(result, _, _)
}
/** Gets an associated item belonging to this trait or `impl` block. */
@@ -580,7 +637,7 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }
ItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
TypeItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }
@@ -615,7 +672,7 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
if this.hasCanonicalPath(c2)
then c1 = c2
else (
c2 = c1.getADependency() or c1 = c2.getADependency()
c2 = c1.getADependency+() or c1 = c2.getADependency+()
)
)
}
@@ -669,7 +726,7 @@ class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
}
}
private class ImplTraitTypeReprItemNode extends ItemNode instanceof ImplTraitTypeRepr {
private class ImplTraitTypeReprItemNode extends TypeItemNode instanceof ImplTraitTypeRepr {
pragma[nomagic]
Path getABoundPath() {
result = super.getTypeBoundList().getABound().getTypeRepr().(PathTypeRepr).getPath()
@@ -1090,10 +1147,10 @@ predicate fileImport(Module m, SourceFile f) {
* in scope under the name `name`.
*/
pragma[nomagic]
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
private predicate fileImportEdge(Module mod, string name, ItemNode item, SuccessorKind kind) {
exists(SourceFileItemNode f |
fileImport(mod, f) and
item = f.getASuccessorRec(name)
item = f.getASuccessor(name, kind)
)
}
@@ -1101,9 +1158,9 @@ private predicate fileImportEdge(Module mod, string name, ItemNode item) {
* Holds if crate `c` defines the item `i` named `name`.
*/
pragma[nomagic]
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i) {
i = c.getSourceFile().getASuccessorRec(name) and
not i instanceof Crate
private predicate crateDefEdge(CrateItemNode c, string name, ItemNode i, SuccessorKind kind) {
i = c.getSourceFile().getASuccessor(name, kind) and
kind.isExternalOrBoth()
}
private class BuiltinSourceFile extends SourceFileItemNode {
@@ -1116,11 +1173,6 @@ private class BuiltinSourceFile extends SourceFileItemNode {
pragma[nomagic]
private predicate crateDependencyEdge(SourceFileItemNode file, string name, CrateItemNode dep) {
exists(CrateItemNode c | dep = c.(Crate).getDependency(name) | file = c.getASourceFile())
or
// Give builtin files access to `std`
file instanceof BuiltinSourceFile and
dep.getName() = name and
name = "std"
}
private predicate useTreeDeclares(UseTree tree, string name) {
@@ -1147,12 +1199,13 @@ private predicate useTreeDeclares(UseTree tree, string name) {
*/
pragma[nomagic]
private predicate declares(ItemNode item, Namespace ns, string name) {
exists(ItemNode child | child.getImmediateParent() = item |
child.getName() = name and
exists(ItemNode child, SuccessorKind kind | child = getAChildSuccessor(item, name, kind) |
child.getNamespace() = ns and
// If `item` is excluded locally then it does not declare `name`.
not item.excludedLocally(name, child)
or
kind.isInternalOrBoth()
)
or
exists(ItemNode child |
child.getImmediateParent() = item and
useTreeDeclares(child.(Use).getUseTree(), name) and
exists(ns) // `use foo::bar` can refer to both a value and a type
)
@@ -1224,8 +1277,8 @@ private predicate unqualifiedPathLookup(ItemNode encl, string name, Namespace ns
}
pragma[nomagic]
private ItemNode getASuccessor(ItemNode pred, string name, Namespace ns) {
result = pred.getASuccessor(name) and
private ItemNode getASuccessor(ItemNode pred, string name, Namespace ns, SuccessorKind kind) {
result = pred.getASuccessor(name, kind) and
ns = result.getNamespace()
}
@@ -1258,9 +1311,10 @@ private predicate keywordLookup(ItemNode encl, string name, RelevantPath p) {
}
pragma[nomagic]
private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns) {
private ItemNode unqualifiedPathLookup(RelevantPath p, Namespace ns, SuccessorKind kind) {
exists(ItemNode encl, string name |
result = getASuccessor(encl, name, ns) and not encl.excludedLocally(name, result)
result = getASuccessor(encl, name, ns, kind) and
kind.isInternalOrBoth()
|
unqualifiedPathLookup(encl, name, ns, p)
or
@@ -1272,9 +1326,9 @@ pragma[nomagic]
private predicate isUnqualifiedSelfPath(RelevantPath path) { path.isUnqualified("Self") }
pragma[nomagic]
private ItemNode resolvePath0(RelevantPath path, Namespace ns) {
private ItemNode resolvePath0(RelevantPath path, Namespace ns, SuccessorKind kind) {
exists(ItemNode res |
res = unqualifiedPathLookup(path, ns) and
res = unqualifiedPathLookup(path, ns, kind) and
if
not any(RelevantPath parent).getQualifier() = path and
isUnqualifiedSelfPath(path) and
@@ -1285,11 +1339,11 @@ private ItemNode resolvePath0(RelevantPath path, Namespace ns) {
or
exists(ItemNode q, string name |
q = resolvePathQualifier(path, name) and
result = getASuccessor(q, name, ns) and
not q.excludedExternally(name, result)
result = getASuccessor(q, name, ns, kind) and
kind.isExternalOrBoth()
)
or
result = resolveUseTreeListItem(_, _, path) and
result = resolveUseTreeListItem(_, _, path, kind) and
ns = result.getNamespace()
}
@@ -1326,7 +1380,17 @@ private predicate pathUsesNamespace(Path p, Namespace n) {
/** Gets the item that `path` resolves to, if any. */
cached
ItemNode resolvePath(RelevantPath path) {
exists(Namespace ns | result = resolvePath0(path, ns) |
exists(Namespace ns |
result = resolvePath0(path, ns, _) and
if path = any(ImplItemNode i).getSelfPath()
then
result instanceof TypeItemNode and
not result instanceof TraitItemNode
else
if path = any(ImplItemNode i).getTraitPath()
then result instanceof TraitItemNode
else any()
|
pathUsesNamespace(path, ns)
or
not pathUsesNamespace(path, _) and
@@ -1357,17 +1421,20 @@ private predicate isUseTreeSubPathUnqualified(UseTree tree, RelevantPath path, s
}
pragma[nomagic]
private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path) {
exists(UseTree midTree, ItemNode mid, string name |
mid = resolveUseTreeListItem(use, midTree) and
tree = midTree.getUseTreeList().getAUseTree() and
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
result = mid.getASuccessor(pragma[only_bind_into](name))
)
or
exists(ItemNode q, string name |
q = resolveUseTreeListItemQualifier(use, tree, path, name) and
result = q.getASuccessor(name)
private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path, SuccessorKind kind) {
kind.isExternalOrBoth() and
(
exists(UseTree midTree, ItemNode mid, string name |
mid = resolveUseTreeListItem(use, midTree) and
tree = midTree.getUseTreeList().getAUseTree() and
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
result = mid.getASuccessor(pragma[only_bind_into](name), kind)
)
or
exists(ItemNode q, string name |
q = resolveUseTreeListItemQualifier(use, tree, path, name) and
result = q.getASuccessor(name, kind)
)
)
}
@@ -1375,7 +1442,7 @@ pragma[nomagic]
private ItemNode resolveUseTreeListItemQualifier(
Use use, UseTree tree, RelevantPath path, string name
) {
result = resolveUseTreeListItem(use, tree, path.getQualifier()) and
result = resolveUseTreeListItem(use, tree, path.getQualifier(), _) and
name = path.getText()
}
@@ -1384,23 +1451,25 @@ private ItemNode resolveUseTreeListItem(Use use, UseTree tree) {
tree = use.getUseTree() and
result = resolvePath(tree.getPath())
or
result = resolveUseTreeListItem(use, tree, tree.getPath())
result = resolveUseTreeListItem(use, tree, tree.getPath(), _)
}
/** Holds if `use` imports `item` as `name`. */
pragma[nomagic]
private predicate useImportEdge(Use use, string name, ItemNode item) {
private predicate useImportEdge(Use use, string name, ItemNode item, SuccessorKind kind) {
(if use.hasVisibility() then kind.isBoth() else kind.isInternal()) and
exists(UseTree tree, ItemNode used |
used = resolveUseTreeListItem(use, tree) and
not tree.hasUseTreeList() and
if tree.isGlob()
then
exists(ItemNode encl, Namespace ns |
exists(ItemNode encl, Namespace ns, SuccessorKind kind1 |
encl.getADescendant() = use and
item = getASuccessor(used, name, ns) and
item = getASuccessor(used, name, ns, kind1) and
kind1.isExternalOrBoth() and
// glob imports can be shadowed
not declares(encl, ns, name) and
not name = ["super", "self", "Self", "$crate", "crate"]
not name = ["super", "self"]
)
else (
item = used and
@@ -1433,13 +1502,21 @@ private predicate externCrateEdge(ExternCrateItemNode ec, string name, CrateItem
pragma[nomagic]
private predicate preludeItem(string name, ItemNode i) {
exists(Crate stdOrCore, ModuleLikeNode mod, ModuleItemNode prelude, ModuleItemNode rust |
stdOrCore.getName() = ["std", "core"] and
exists(
Crate stdOrCore, string stdOrCoreName, ModuleLikeNode mod, ModuleItemNode prelude,
ModuleItemNode rust
|
stdOrCore.getName() = stdOrCoreName and
stdOrCoreName = ["std", "core"] and
mod = stdOrCore.getSourceFile() and
prelude = mod.getASuccessorRec("prelude") and
rust = prelude.getASuccessorRec(["rust_2015", "rust_2018", "rust_2021", "rust_2024"]) and
i = rust.getASuccessorRec(name) and
not i instanceof Use
prelude = mod.getASuccessor("prelude") and
rust = prelude.getASuccessor(["rust_2015", "rust_2018", "rust_2021", "rust_2024"])
|
i = rust.getASuccessor(name) and
not name = ["super", "self"]
or
name = stdOrCoreName and
i = stdOrCore
)
}
@@ -1463,7 +1540,7 @@ pragma[nomagic]
private predicate builtin(string name, ItemNode i) {
exists(BuiltinSourceFile builtins |
builtins.getFile().getBaseName() = "types.rs" and
i = builtins.getASuccessorRec(name)
i = builtins.getASuccessor(name)
)
}
@@ -1490,19 +1567,19 @@ private module Debug {
result = resolvePath(path)
}
predicate debugUseImportEdge(Use use, string name, ItemNode item) {
predicate debugUseImportEdge(Use use, string name, ItemNode item, SuccessorKind kind) {
use = getRelevantLocatable() and
useImportEdge(use, name, item)
useImportEdge(use, name, item, kind)
}
ItemNode debugGetASuccessorRec(ItemNode i, string name) {
ItemNode debuggetASuccessor(ItemNode i, string name, SuccessorKind kind) {
i = getRelevantLocatable() and
result = i.getASuccessor(name)
result = i.getASuccessor(name, kind)
}
predicate debugFileImportEdge(Module mod, string name, ItemNode item) {
predicate debugFileImportEdge(Module mod, string name, ItemNode item, SuccessorKind kind) {
mod = getRelevantLocatable() and
fileImportEdge(mod, name, item)
fileImportEdge(mod, name, item, kind)
}
predicate debugFileImport(Module m, SourceFile f) {

View File

@@ -224,8 +224,9 @@ private import M2
module Consistency {
import M2::Consistency
query predicate nonUniqueCertainType(AstNode n, TypePath path) {
strictcount(CertainTypeInference::inferCertainType(n, path)) > 1
predicate nonUniqueCertainType(AstNode n, TypePath path, Type t) {
strictcount(CertainTypeInference::inferCertainType(n, path)) > 1 and
t = CertainTypeInference::inferCertainType(n, path)
}
}
@@ -2513,7 +2514,6 @@ private module Debug {
Type debugInferCertainNonUniqueType(AstNode n, TypePath path) {
n = getRelevantLocatable() and
Consistency::nonUniqueCertainType(n, path) and
result = CertainTypeInference::inferCertainType(n, path)
Consistency::nonUniqueCertainType(n, path, result)
}
}

View File

@@ -17,6 +17,10 @@ query predicate illFormedTypeMention(TypeMention tm) {
tm.fromSource()
}
query predicate nonUniqueCertainType(AstNode n, TypePath path) {
Consistency::nonUniqueCertainType(n, path, _)
}
int getTypeInferenceInconsistencyCounts(string type) {
type = "Missing type parameter ID" and
result = count(TypeParameter tp | missingTypeParameterId(tp) | tp)

View File

@@ -1,3 +0,0 @@
nonUniqueCertainType
| sqlx.rs:158:13:158:24 | { ... } | E |
| sqlx.rs:160:17:160:28 | { ... } | E |

View File

@@ -1,4 +0,0 @@
nonUniqueCertainType
| test_logging.rs:17:8:19:12 | { ... } | E |
| test_logging.rs:29:8:31:12 | { ... } | E |
| test_storage.rs:177:8:179:9 | { ... } | E |

View File

@@ -1,18 +1,3 @@
multipleCallTargets
| main.rs:218:14:218:30 | ...::malloc(...) |
| main.rs:219:13:219:27 | ...::malloc(...) |
| main.rs:220:13:220:37 | ...::aligned_alloc(...) |
| main.rs:221:13:221:37 | ...::aligned_alloc(...) |
| main.rs:222:13:222:31 | ...::calloc(...) |
| main.rs:223:13:223:55 | ...::calloc(...) |
| main.rs:224:13:224:32 | ...::realloc(...) |
| main.rs:229:13:229:40 | ...::with_capacity(...) |
| main.rs:233:18:233:47 | ...::with_capacity(...) |
multiplePathResolutions
| main.rs:218:14:218:17 | libc |
| main.rs:219:13:219:16 | libc |
| main.rs:220:13:220:16 | libc |
| main.rs:221:13:221:16 | libc |
| main.rs:222:13:222:16 | libc |
| main.rs:223:13:223:16 | libc |
| main.rs:224:13:224:16 | libc |

View File

@@ -1,6 +1,4 @@
multipleCallTargets
| deallocation.rs:106:16:106:32 | ...::malloc(...) |
| deallocation.rs:112:3:112:41 | ...::free(...) |
| deallocation.rs:260:11:260:29 | ...::from(...) |
| deallocation.rs:261:11:261:29 | ...::from(...) |
| lifetime.rs:610:13:610:31 | ...::from(...) |
@@ -9,7 +7,3 @@ multipleCallTargets
| lifetime.rs:612:41:612:52 | bar.as_str() |
| lifetime.rs:628:13:628:31 | ...::from(...) |
| lifetime.rs:629:32:629:43 | baz.as_str() |
multiplePathResolutions
| deallocation.rs:106:16:106:19 | libc |
| deallocation.rs:112:3:112:6 | libc |
| deallocation.rs:112:29:112:32 | libc |

View File

@@ -873,77 +873,85 @@ module Make<LocationSig Location, InputSig<Location> Input> {
private signature predicate baseGuardValueSig(Guard guard, GuardValue v);
/**
* Calculates the transitive closure of all the guard implication steps
* starting from a given set of base cases.
*/
cached
private module ImpliesTC<baseGuardValueSig/2 baseGuardValue> {
private module Cached {
/**
* Holds if `tgtGuard` evaluating to `tgtVal` implies that `guard`
* evaluates to `v`.
* Calculates the transitive closure of all the guard implication steps
* starting from a given set of base cases.
*/
pragma[nomagic]
cached
predicate guardControls(Guard guard, GuardValue v, Guard tgtGuard, GuardValue tgtVal) {
baseGuardValue(tgtGuard, tgtVal) and
guard = tgtGuard and
v = tgtVal
or
exists(Guard g0, GuardValue v0 |
guardControls(g0, v0, tgtGuard, tgtVal) and
impliesStep2(g0, v0, guard, v)
)
or
exists(Guard g0, GuardValue v0 |
guardControls(g0, v0, tgtGuard, tgtVal) and
unboundImpliesStep(g0, v0, guard, v)
)
or
exists(SsaDefinition def0, GuardValue v0 |
ssaControls(def0, v0, tgtGuard, tgtVal) and
impliesStepSsaGuard(def0, v0, guard, v)
)
or
exists(Guard g0, GuardValue v0 |
guardControls(g0, v0, tgtGuard, tgtVal) and
WrapperGuard::wrapperImpliesStep(g0, v0, guard, v)
)
or
exists(Guard g0, GuardValue v0 |
guardControls(g0, v0, tgtGuard, tgtVal) and
additionalImpliesStep(g0, v0, guard, v)
)
module ImpliesTC<baseGuardValueSig/2 baseGuardValue> {
/**
* Holds if `tgtGuard` evaluating to `tgtVal` implies that `guard`
* evaluates to `v`.
*/
pragma[nomagic]
cached
predicate guardControls(Guard guard, GuardValue v, Guard tgtGuard, GuardValue tgtVal) {
baseGuardValue(tgtGuard, tgtVal) and
guard = tgtGuard and
v = tgtVal
or
exists(Guard g0, GuardValue v0 |
guardControls(g0, v0, tgtGuard, tgtVal) and
impliesStep2(g0, v0, guard, v)
)
or
exists(Guard g0, GuardValue v0 |
guardControls(g0, v0, tgtGuard, tgtVal) and
unboundImpliesStep(g0, v0, guard, v)
)
or
exists(SsaDefinition def0, GuardValue v0 |
ssaControls(def0, v0, tgtGuard, tgtVal) and
impliesStepSsaGuard(def0, v0, guard, v)
)
or
exists(Guard g0, GuardValue v0 |
guardControls(g0, v0, tgtGuard, tgtVal) and
WrapperGuard::wrapperImpliesStep(g0, v0, guard, v)
)
or
exists(Guard g0, GuardValue v0 |
guardControls(g0, v0, tgtGuard, tgtVal) and
additionalImpliesStep(g0, v0, guard, v)
)
}
/**
* Holds if `tgtGuard` evaluating to `tgtVal` implies that `def`
* evaluates to `v`.
*/
pragma[nomagic]
cached
predicate ssaControls(SsaDefinition def, GuardValue v, Guard tgtGuard, GuardValue tgtVal) {
exists(Guard g0 |
guardControls(g0, v, tgtGuard, tgtVal) and
guardReadsSsaVar(g0, def)
)
or
exists(SsaDefinition def0 |
ssaControls(def0, v, tgtGuard, tgtVal) and
impliesStepSsa(def0, v, def)
)
}
}
/**
* Holds if `tgtGuard` evaluating to `tgtVal` implies that `def`
* evaluates to `v`.
* Holds if `guard` evaluating to `v` implies that `e` is guaranteed to be
* null if `isNull` is true, and non-null if `isNull` is false.
*/
pragma[nomagic]
cached
predicate ssaControls(SsaDefinition def, GuardValue v, Guard tgtGuard, GuardValue tgtVal) {
exists(Guard g0 |
guardControls(g0, v, tgtGuard, tgtVal) and
guardReadsSsaVar(g0, def)
)
or
exists(SsaDefinition def0 |
ssaControls(def0, v, tgtGuard, tgtVal) and
impliesStepSsa(def0, v, def)
)
predicate nullGuard(Guard guard, GuardValue v, Expr e, boolean isNull) {
impliesStep2(guard, v, e, any(GuardValue gv | gv.isNullness(isNull))) or
WrapperGuard::wrapperImpliesStep(guard, v, e, any(GuardValue gv | gv.isNullness(isNull))) or
additionalImpliesStep(guard, v, e, any(GuardValue gv | gv.isNullness(isNull)))
}
}
/**
* Holds if `guard` evaluating to `v` implies that `e` is guaranteed to be
* null if `isNull` is true, and non-null if `isNull` is false.
*/
predicate nullGuard(Guard guard, GuardValue v, Expr e, boolean isNull) {
impliesStep2(guard, v, e, any(GuardValue gv | gv.isNullness(isNull))) or
WrapperGuard::wrapperImpliesStep(guard, v, e, any(GuardValue gv | gv.isNullness(isNull))) or
additionalImpliesStep(guard, v, e, any(GuardValue gv | gv.isNullness(isNull)))
}
private import Cached
predicate nullGuard = Cached::nullGuard/4;
private predicate hasAValueBranchEdge(Guard guard, GuardValue v) {
guard.hasValueBranchEdge(_, _, v)